欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

php实现的rc4加密解密类定义与用法示例

程序员文章站 2023-11-02 13:46:22
本文实例讲述了php实现的rc4加密解密类。分享给大家供大家参考,具体如下: class.rc4crypt.php文件:

本文实例讲述了php实现的rc4加密解密类。分享给大家供大家参考,具体如下:

class.rc4crypt.php文件:

<?php
/* 
 * by julying.com
 */
define('crypt_rc4_mode_internal', 1);
define('crypt_rc4_mode_mcrypt', 2);
define('crypt_rc4_encrypt', 0);
define('crypt_rc4_decrypt', 1);
class crypt_rc4 {
 /**
  * the key
  *
  * @see crypt_rc4::setkey()
  * @var string
  * @access private
  */
 var $key = "\0";
 /**
  * the key stream for encryption
  *
  * if crypt_rc4_mode == crypt_rc4_mode_mcrypt, this will be equal to the mcrypt object
  *
  * @see crypt_rc4::setkey()
  * @var array
  * @access private
  */
 var $encryptstream = false;
 /**
  * the key stream for decryption
  *
  * if crypt_rc4_mode == crypt_rc4_mode_mcrypt, this will be equal to the mcrypt object
  *
  * @see crypt_rc4::setkey()
  * @var array
  * @access private
  */
 var $decryptstream = false;
 /**
  * the $i and $j indexes for encryption
  *
  * @see crypt_rc4::_crypt()
  * @var integer
  * @access private
  */
 var $encryptindex = 0;
 /**
  * the $i and $j indexes for decryption
  *
  * @see crypt_rc4::_crypt()
  * @var integer
  * @access private
  */
 var $decryptindex = 0;
 /**
  * mcrypt parameters
  *
  * @see crypt_rc4::setmcrypt()
  * @var array
  * @access private
  */
 var $mcrypt = array('', '');
 /**
  * the encryption algorithm
  *
  * only used if crypt_rc4_mode == crypt_rc4_mode_mcrypt. only possible values are mcrypt_rc4 or mcrypt_arcfour.
  *
  * @see crypt_rc4::crypt_rc4()
  * @var integer
  * @access private
  */
 var $mode;
 /**
  * default constructor.
  *
  * determines whether or not the mcrypt extension should be used.
  *
  * @param optional integer $mode
  * @return crypt_rc4
  * @access public
  */
 var $continuousbuffer ;
 function crypt_rc4()
 {
  if ( !defined('crypt_rc4_mode') ) {
   switch (true) {
    case extension_loaded('mcrypt') && (defined('mcrypt_arcfour') || defined('mcrypt_rc4')):
     // i'd check to see if rc4 was supported, by doing in_array('arcfour', mcrypt_list_algorithms('')),
     // but since that can be changed after the object has been created, there doesn't seem to be
     // a lot of point...
     define('crypt_rc4_mode', crypt_rc4_mode_mcrypt);
     break;
    default:
     define('crypt_rc4_mode', crypt_rc4_mode_internal);
   }
  }
  switch ( crypt_rc4_mode ) {
   case crypt_rc4_mode_mcrypt:
    switch (true) {
     case defined('mcrypt_arcfour'):
      $this->mode = mcrypt_arcfour;
      break;
     case defined('mcrypt_rc4');
      $this->mode = mcrypt_rc4;
    }
  }
 }
 /**
  * sets the key.
  *
  * keys can be between 1 and 256 bytes long. if they are longer then 256 bytes, the first 256 bytes will
  * be used. if no key is explicitly set, it'll be assumed to be a single null byte.
  *
  * @access public
  * @param string $key
  */
 function setkey($key)
 {
  $this->key = $key;
  if ( crypt_rc4_mode == crypt_rc4_mode_mcrypt ) {
   return;
  }
  $keylength = strlen($key);
  $keystream = array();
  for ($i = 0; $i < 256; $i++) {
   $keystream[$i] = $i;
  }
  $j = 0;
  for ($i = 0; $i < 256; $i++) {
   $j = ($j + $keystream[$i] + ord($key[$i % $keylength])) & 255;
   $temp = $keystream[$i];
   $keystream[$i] = $keystream[$j];
   $keystream[$j] = $temp;
  }
  $this->encryptindex = $this->decryptindex = array(0, 0);
  $this->encryptstream = $this->decryptstream = $keystream;
 }
 /**
  * dummy function.
  *
  * some protocols, such as wep, prepend an "initialization vector" to the key, effectively creating a new key [1].
  * if you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
  * calling setkey().
  *
  * [1] wep's initialization vectors (iv's) are used in a somewhat insecure way. since, in that protocol,
  * the iv's are relatively easy to predict, an attack described by
  * {@link http://www.drizzle.com/~aboba/ieee/rc4_ksaproc.pdf scott fluhrer, itsik mantin, and adi shamir}
  * can be used to quickly guess at the rest of the key. the following links elaborate:
  *
  * {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
  * {@link http://en.wikipedia.org/wiki/related_key_attack http://en.wikipedia.org/wiki/related_key_attack}
  *
  * @param string $iv
  * @see crypt_rc4::setkey()
  * @access public
  */
 function setiv($iv)
 {
 }
 /**
  * sets mcrypt parameters. (optional)
  *
  * if mcrypt is being used, empty strings will be used, unless otherwise specified.
  *
  * @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
  * @access public
  * @param optional integer $algorithm_directory
  * @param optional integer $mode_directory
  */
 function setmcrypt($algorithm_directory = '', $mode_directory = '')
 {
  if ( crypt_rc4_mode == crypt_rc4_mode_mcrypt ) {
   $this->mcrypt = array($algorithm_directory, $mode_directory);
   $this->_closemcrypt();
  }
 }
 /**
  * encrypts a message.
  *
  * @see crypt_rc4::_crypt()
  * @access public
  * @param string $plaintext
  */
 function encrypt($plaintext)
 {
  return self::tohex($this->_crypt($plaintext, crypt_rc4_encrypt));
 }
 /**
  * decrypts a message.
  *
  * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
  * atleast if the continuous buffer is disabled.
  *
  * @see crypt_rc4::_crypt()
  * @access public
  * @param string $ciphertext
  */
 function decrypt($ciphertext)
 {
  $ciphertext = self::fromhex($ciphertext);
  return $this->_crypt($ciphertext, crypt_rc4_decrypt);
 }
 /**
  * encrypts or decrypts a message.
  *
  * @see crypt_rc4::encrypt()
  * @see crypt_rc4::decrypt()
  * @access private
  * @param string $text
  * @param integer $mode
  */
 function _crypt($text, $mode)
 {
  if ( crypt_rc4_mode == crypt_rc4_mode_mcrypt ) {
   $keystream = $mode == crypt_rc4_encrypt ? 'encryptstream' : 'decryptstream';
   if ($this->$keystream === false) {
    $this->$keystream = mcrypt_module_open($this->mode, $this->mcrypt[0], mcrypt_mode_stream, $this->mcrypt[1]);
    mcrypt_generic_init($this->$keystream, $this->key, '');
   } else if (!$this->continuousbuffer) {
    mcrypt_generic_init($this->$keystream, $this->key, '');
   }
   $newtext = mcrypt_generic($this->$keystream, $text);
   if (!$this->continuousbuffer) {
    mcrypt_generic_deinit($this->$keystream);
   }
   return $newtext;
  }
  if ($this->encryptstream === false) {
   $this->setkey($this->key);
  }
  switch ($mode) {
   case crypt_rc4_encrypt:
    $keystream = $this->encryptstream;
    list($i, $j) = $this->encryptindex;
    break;
   case crypt_rc4_decrypt:
    $keystream = $this->decryptstream;
    list($i, $j) = $this->decryptindex;
  }
  $newtext = '';
  for ($k = 0; $k < strlen($text); $k++) {
   $i = ($i + 1) & 255;
   $j = ($j + $keystream[$i]) & 255;
   $temp = $keystream[$i];
   $keystream[$i] = $keystream[$j];
   $keystream[$j] = $temp;
   $temp = $keystream[($keystream[$i] + $keystream[$j]) & 255];
   $newtext.= chr(ord($text[$k]) ^ $temp);
  }
  if ($this->continuousbuffer) {
   switch ($mode) {
    case crypt_rc4_encrypt:
     $this->encryptstream = $keystream;
     $this->encryptindex = array($i, $j);
     break;
    case crypt_rc4_decrypt:
     $this->decryptstream = $keystream;
     $this->decryptindex = array($i, $j);
   }
  }
  return $newtext;
 }
 /**
  * treat consecutive "packets" as if they are a continuous buffer.
  *
  * say you have a 16-byte plaintext $plaintext. using the default behavior, the two following code snippets
  * will yield different outputs:
  *
  * <code>
  * echo $rc4->encrypt(substr($plaintext, 0, 8));
  * echo $rc4->encrypt(substr($plaintext, 8, 8));
  * </code>
  * <code>
  * echo $rc4->encrypt($plaintext);
  * </code>
  *
  * the solution is to enable the continuous buffer. although this will resolve the above discrepancy, it creates
  * another, as demonstrated with the following:
  *
  * <code>
  * $rc4->encrypt(substr($plaintext, 0, 8));
  * echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
  * </code>
  * <code>
  * echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
  * </code>
  *
  * with the continuous buffer disabled, these would yield the same output. with it enabled, they yield different
  * outputs. the reason is due to the fact that the initialization vector's change after every encryption /
  * decryption round when the continuous buffer is enabled. when it's disabled, they remain constant.
  *
  * put another way, when the continuous buffer is enabled, the state of the crypt_des() object changes after each
  * encryption / decryption round, whereas otherwise, it'd remain constant. for this reason, it's recommended that
  * continuous buffers not be used. they do offer better security and are, in fact, sometimes required (ssh uses them),
  * however, they are also less intuitive and more likely to cause you problems.
  *
  * @see crypt_rc4::disablecontinuousbuffer()
  * @access public
  */
 function enablecontinuousbuffer()
 {
  $this->continuousbuffer = true;
 }
 /**
  * treat consecutive packets as if they are a discontinuous buffer.
  *
  * the default behavior.
  *
  * @see crypt_rc4::enablecontinuousbuffer()
  * @access public
  */
 function disablecontinuousbuffer()
 {
  if ( crypt_rc4_mode == crypt_rc4_mode_internal ) {
   $this->encryptindex = $this->decryptindex = array(0, 0);
   $this->setkey($this->key);
  }
  $this->continuousbuffer = false;
 }
 /**
  * dummy function.
  *
  * since rc4 is a stream cipher and not a block cipher, no padding is necessary. the only reason this function is
  * included is so that you can switch between a block cipher and a stream cipher transparently.
  *
  * @see crypt_rc4::disablepadding()
  * @access public
  */
 function enablepadding()
 {
 }
 /**
  * dummy function.
  *
  * @see crypt_rc4::enablepadding()
  * @access public
  */
 function disablepadding()
 {
 }
 /**
  * class destructor.
  *
  * will be called, automatically, if you're using php5. if you're using php4, call it yourself. only really
  * needs to be called if mcrypt is being used.
  *
  * @access public
  */
 function __destruct()
 {
  if ( crypt_rc4_mode == crypt_rc4_mode_mcrypt ) {
   $this->_closemcrypt();
  }
 }
 /**
  * properly close the mcrypt objects.
  *
  * @access prviate
  */
 function _closemcrypt()
 {
  if ( $this->encryptstream !== false ) {
   if ( $this->continuousbuffer ) {
    mcrypt_generic_deinit($this->encryptstream);
   }
   mcrypt_module_close($this->encryptstream);
   $this->encryptstream = false;
  }
  if ( $this->decryptstream !== false ) {
   if ( $this->continuousbuffer ) {
    mcrypt_generic_deinit($this->decryptstream);
   }
   mcrypt_module_close($this->decryptstream);
   $this->decryptstream = false;
  }
 }
 // @function fromhex 把十六进制数转换成字符串
 function tohex($sa , $len = 0){
  $buf = "";
  if( $len == 0 )
   $len = strlen($sa) ;
  for ($i = 0; $i < $len; $i++)
  {
   $val = dechex(ord($sa{$i}));  
   if(strlen($val)< 2) 
    $val = "0".$val;
   $buf .= $val;
  }
  return $buf;
 }
 // @function fromhex 把十六进制数转换成字符串 
 function fromhex($sa){
  $buf = "";
  $len = strlen($sa) ;
  for($i = 0; $i < $len; $i += 2){
   $val = chr(hexdec(substr($sa, $i, 2)));
   $buf .= $val;
  }
  return $buf;
 }
}

使用方法:

include('class.rc4crypt.php');
$rc4 = new crypt_rc4();
$rc4 -> setkey('21sd54a1w5q');
$text = 'www.jb51.net';
echo $x = $rc4->encrypt($text);//加密
echo '<br />';
echo $rc4->decrypt( $x) ;//解密

运行结果:

7907bb7c6694f179e9642ebd
www.jb51.net

ps:关于加密解密感兴趣的朋友还可以参考本站在线工具:

在线rc4加密/解密工具:

文字在线加密解密工具(包含aes、des、rc4等):

在线散列/哈希算法加密工具:

在线md5/hash/sha-1/sha-2/sha-256/sha-512/sha-3/ripemd-160加密工具:

在线sha1/sha224/sha256/sha384/sha512加密工具:

更多关于php相关内容感兴趣的读者可查看本站专题:《php加密方法总结》、《php编码与转码操作技巧汇总》、《php数学运算技巧总结》、《php数组(array)操作技巧大全》、《php字符串(string)用法总结》、《php数据结构与算法教程》、《php程序设计算法总结》及《php正则表达式用法总结

希望本文所述对大家php程序设计有所帮助。