home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 August / PCWorld_2001-08_cd.bin / Komunikace / phptriad / phptriadsetup2-11.exe / php / pear / Crypt / CBC.php next >
PHP Script  |  2001-02-13  |  9KB  |  295 lines

  1. <?php
  2. /* vim: set ts=4 sw=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4.0                                                      |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 2001 The PHP Group                                     |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Colin Viebrock <colin@easydns.com>                          |
  17. // |          Mike Glover <mpg4@duluoz.net>                               |
  18. // +----------------------------------------------------------------------+
  19. //
  20.  
  21. /**
  22. * Class to emulate Perl's Crypt::CBC module
  23. *
  24. * Blowfish support is not completely working, mainly because of a bug
  25. * discovered in libmcrypt (version 2.4.8 and earlier).  If you are running
  26. * a later version of libmcrypt > 2.4.8, you can do Blowfish encryption
  27. * that is compatable with Perl.  However, check the libmcrypt documenation
  28. * as to whether you should use 'BLOWFISH' or 'BLOWFISH-COMPAT' when
  29. * specifying the cipher.
  30. *
  31. * If you are using libmcrypt <= 2.4.8, Blowfish encryption will work,
  32. * but your data will not be readable by Perl scripts.  It will work
  33. * "internally" .. i.e. this class will be able to encode/decode the data.
  34. *
  35. * NOTE: the cipher names in this class may change depending on how
  36. * the author of libcrypt decides to name things internally.
  37. *
  38. *
  39. * @version  $Id: CBC.php,v 1.6 2001/02/13 21:53:48 cmv Exp $
  40. * @author   Colin Viebrock <colin@easydns.com>
  41. * @author   Mike Glover <mpg4@duluoz.net>
  42. *
  43. */
  44.  
  45.  
  46.  
  47. require_once 'PEAR.php';
  48.  
  49.  
  50.  
  51. if (function_exists('mcrypt_module_open')) {
  52.     define('CRYPT_CBC_USING_24x', 1);
  53. } else {
  54.     define('CRYPT_CBC_USING_24x', 0);
  55. }
  56.  
  57.  
  58.  
  59. class Crypt_CBC extends PEAR {
  60.  
  61.     var $known_ciphers = array (
  62.         'DES'               => MCRYPT_DES,
  63.         'BLOWFISH'          => MCRYPT_BLOWFISH,
  64.         'BLOWFISH-COMPAT'   => MCRYPT_BLOWFISH_COMPAT,
  65.     );
  66.  
  67.     var $cipher;                        # used cipher
  68.     var $TD;                            # crypt resource, for 2.4.x
  69.     var $blocksize;                     # blocksize of cipher
  70.     var $keysize;                       # keysize of cipher
  71.     var $keyhash;                       # mangled key
  72.     var $error;
  73.     var $rand_source    = MCRYPT_RAND;  # or MCRYPT_DEV_URANDOM or MCRYPT_DEV_RANDOM
  74.     var $header_spec    = 'RandomIV';   # header
  75.  
  76.     var $_last_clear;                   # debugging
  77.     var $_last_crypt;                   # debugging
  78.  
  79.  
  80.  
  81.     /**
  82.     * Constructor
  83.     *
  84.     * @param    $key        encryption key
  85.     * @param    $cipher     which algorithm to use, defaults to DES
  86.     *
  87.     * @return   $return     either a PEAR error or true
  88.     *
  89.     * @access   public
  90.     *
  91.     */
  92.  
  93.     function Crypt_CBC ($key, $cipher='DES')
  94.     {
  95.  
  96.         if (!extension_loaded('mcrypt')) {
  97.             $this->error = new Crypt_CBC_Error('mcrypt module is not compiled into PHP: compile PHP using --with-mcrypt.');
  98.             return $this->error;
  99.         }
  100.  
  101.         /* seed randomizer */
  102.  
  103.         srand ((double)microtime()*1000000);
  104.  
  105.         /* initialize */
  106.  
  107.         $this->header_spec = 'RandomIV';
  108.  
  109.         /* check for key */
  110.  
  111.         if (!$key) {
  112.             $this->error = new Crypt_CBC_Error('No key specified');
  113.             return $this->error;
  114.         }
  115.  
  116.         /* check for cipher */
  117.  
  118.         $cipher = strtoupper($cipher);
  119.         if (!isset($this->known_ciphers[$cipher])) {
  120.             $this->error = new Crypt_CBC_Error('Unknown cipher: ' . $cipher);
  121.             return $this->error;
  122.         }
  123.  
  124.         $this->cipher = $this->known_ciphers[$cipher];
  125.  
  126.         /* initialize cipher */
  127.  
  128.         if (CRYPT_CBC_USING_24x) {
  129.             $this->blocksize = mcrypt_get_block_size($this->cipher,'cbc');
  130.             $this->keysize = mcrypt_get_key_size($this->cipher,'cbc');
  131.             $this->TD = mcrypt_module_open ($this->cipher, '', 'ecb', '');
  132.         } else {
  133.             $this->blocksize = mcrypt_get_block_size('cbc');
  134.             $this->keysize = mcrypt_get_key_size('cbc');
  135.             $this->TD = false;
  136.         }
  137.  
  138.         /* mangle key with MD5 */
  139.  
  140.         $this->keyhash = $this->_md5perl($key);
  141.         while( strlen($this->keyhash) < $this->keysize ) {
  142.             $this->keyhash .= $this->_md5perl($this->keyhash);
  143.         }
  144.  
  145.         $this->key = substr($this->keyhash, 0, $this->keysize);
  146.  
  147.         return true;
  148.  
  149.     }
  150.  
  151.  
  152.  
  153.     /**
  154.     * Encryption method
  155.     *
  156.     * @param    $clear      plaintext
  157.     *
  158.     * @return   $crypt      encrypted text, or PEAR error
  159.     *
  160.     * @access   public
  161.     *
  162.     */
  163.  
  164.     function encrypt($clear)
  165.     {
  166.  
  167.         $this->last_clear = $clear;
  168.  
  169.         /* new IV for each message */
  170.  
  171.         $iv = mcrypt_create_iv($this->blocksize, $this->rand_source);
  172.  
  173.         /* create the message header */
  174.  
  175.         $crypt = $this->header_spec . $iv;
  176.  
  177.         /* pad the cleartext */
  178.  
  179.         $padsize = $this->blocksize - (strlen($clear) % $this->blocksize);
  180.         $clear .= str_repeat(pack ('C*', $padsize), $padsize);
  181.  
  182.  
  183.         /* do the encryption */
  184.  
  185.         $start = 0;
  186.         while ( $block = substr($clear, $start, $this->blocksize) ) {
  187.             $start += $this->blocksize;
  188.             if (CRYPT_CBC_USING_24x) {
  189.                 mcrypt_generic_init($this->TD, $this->key, $iv);
  190.                 $cblock = mcrypt_generic($this->TD, $iv^$block );
  191.             } else {
  192.                 $cblock = mcrypt_ECB($this->cipher, $this->key, $iv^$block, MCRYPT_ENCRYPT );
  193.             }
  194.             $iv = $cblock;
  195.             $crypt .= $cblock;
  196.         }
  197.  
  198.         $this->last_crypt = $crypt;
  199.         return $crypt;
  200.  
  201.     }
  202.  
  203.  
  204.  
  205.     /**
  206.     * Decryption method
  207.     *
  208.     * @param    $crypt      encrypted text
  209.     *
  210.     * @return   $clear      plaintext, or PEAR error
  211.     *
  212.     * @access   public
  213.     *
  214.     */
  215.  
  216.     function decrypt($crypt) {
  217.  
  218.         $this->last_crypt = $crypt;
  219.  
  220.         /* get the IV from the message header */
  221.  
  222.         $iv_offset = strlen($this->header_spec);
  223.         $header = substr($crypt, 0, $iv_offset);
  224.         $iv = substr ($crypt, $iv_offset, $this->blocksize);
  225.         if ( $header != $this->header_spec ) {
  226.             $this->error = new Crypt_CBC_Error('No initialization vector');
  227.             return $this->error;
  228.         }
  229.  
  230.         $crypt = substr($crypt, $iv_offset+$this->blocksize);
  231.  
  232.         /* decrypt the message */
  233.  
  234.         $start = 0;
  235.         $clear = '';
  236.  
  237.         while ( $cblock = substr($crypt, $start, $this->blocksize) ) {
  238.             $start += $this->blocksize;
  239.             if (CRYPT_CBC_USING_24x) {
  240.                 mcrypt_generic_init($this->TD, $this->key, $iv);
  241.                 $block = $iv ^ mdecrypt_generic($this->TD, $cblock);
  242.             } else {
  243.                 $block = $iv ^ mcrypt_ECB($this->cipher, $this->key, $cblock, MCRYPT_DECRYPT );
  244.             }
  245.             $iv = $cblock;
  246.             $clear .= $block;
  247.         }
  248.  
  249.         /* remove the padding from the end of the cleartext */
  250.  
  251.         $padsize = ord(substr($clear, -1));
  252.         $clear = substr($clear, 0, -$padsize);
  253.  
  254.         $this->last_clear = $clear;
  255.         return $clear;
  256.  
  257.     }
  258.  
  259.  
  260.  
  261.     /**
  262.     * Emulate Perl's MD5 function, which returns binary data
  263.     *
  264.     * @param    $string     string to MD5
  265.     *
  266.     * @return   $hash       binary hash
  267.     *
  268.     * @access private
  269.     *
  270.     */
  271.  
  272.     function _md5perl($string)
  273.     {
  274.         return pack('H*', md5($string));
  275.     }
  276.  
  277.  
  278. }
  279.  
  280.  
  281. class Crypt_CBC_Error extends PEAR_Error
  282. {
  283.     var $classname             = 'Crypt_CBC_Error';
  284.     var $error_message_prepend = 'Error in Crypt_CBC';
  285.  
  286.     function Crypt_CBC_Error ($message, $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE)
  287.     {
  288.         $this->PEAR_Error ($message, $code, $mode, $level);
  289.     }
  290.  
  291. }
  292.  
  293.  
  294. ?>
  295.