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


Posted in PHP onAugust 16, 2018

本文实例讲述了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 = '3water.com';
echo $x = $rc4->encrypt($text);//加密
echo '<br />';
echo $rc4->decrypt( $x) ;//解密

运行结果:

7907bb7c6694f179e9642ebd
3water.com

PHP 相关文章推荐
PHP配置文件中最常用四个ini函数
Mar 19 PHP
基于PHP选项与信息函数的使用详解
May 10 PHP
解析PHP可变函数的经典用法
Jun 20 PHP
CodeIgniter上传图片成功的全部过程分享
Aug 12 PHP
php分页函数完整实例代码
Sep 22 PHP
php实现图片文件与下载文件防盗链的方法
Nov 03 PHP
php实现用于删除整个目录的递归函数
Mar 16 PHP
Yii获取当前url和域名的方法
Jun 08 PHP
php中header设置常见文件类型的content-type
Jun 23 PHP
PHP对象克隆clone用法示例
Sep 28 PHP
PHP排序算法之归并排序(Merging Sort)实例详解
Apr 21 PHP
PHP配置ZendOpcache插件加速
Feb 14 PHP
Laravel框架实现定时发布任务的方法
Aug 16 #PHP
Laravel框架使用monolog_mysql实现将系统日志信息保存到mysql数据库的方法
Aug 16 #PHP
Laravel中的chunk组块结果集处理与注意问题
Aug 15 #PHP
PHP curl批处理及多请求并发实现方法分析
Aug 15 #PHP
php使用curl_init()和curl_multi_init()多线程的速度比较详解
Aug 15 #PHP
php使用curl获取header检测开启GZip压缩的方法
Aug 15 #PHP
深入研究PHP中的preg_replace和代码执行
Aug 15 #PHP
You might like
laravel5.2表单验证,并显示错误信息的实例
2019/09/29 PHP
js自定义方法通过隐藏iframe实现文件下载
2013/02/21 Javascript
js保留两位小数使用toFixed实现
2013/07/29 Javascript
JS辨别访问浏览器判断是android还是ios系统
2014/08/19 Javascript
javascript实时显示当天日期的方法
2015/05/20 Javascript
JavaScript常用数组算法小结
2016/02/13 Javascript
web 前端常用组件之Layer弹出层组件
2016/09/22 Javascript
ajax实现加载页面、删除、查看详细信息 bootstrap美化页面!
2017/03/14 Javascript
JavaScript之iterable_动力节点Java学院整理
2017/06/29 Javascript
JavaScript中重名的函数与对象示例详析
2017/09/28 Javascript
解决使用vue.js路由后失效的问题
2018/03/17 Javascript
Java设计中的Builder模式的介绍
2018/03/22 Javascript
axios取消请求的实践记录分享
2018/09/26 Javascript
Webstorm2016使用技巧(SVN插件使用)
2018/10/29 Javascript
vue实现的组件兄弟间通信功能示例
2018/12/04 Javascript
微信小程序模板消息限制实现无限制主动推送的示例代码
2019/08/27 Javascript
解决mui框架中switch开关通过js控制开或者关状态时小圆点不动的问题
2019/09/03 Javascript
js+canvas实现刮刮奖功能
2020/09/13 Javascript
Vue——解决报错 Computed property &quot;****&quot; was assigned to but it has no setter.
2020/12/19 Vue.js
[02:08]DOTA2英雄基础教程 马格纳斯
2014/01/17 DOTA
Python中的自定义函数学习笔记
2014/09/23 Python
详解Python中表达式i += x与i = i + x是否等价
2017/02/08 Python
Python cookbook(数据结构与算法)实现查找两个字典相同点的方法
2018/02/18 Python
Python 获取windows桌面路径的5种方法小结
2019/07/15 Python
Django框架HttpRequest对象用法实例分析
2019/11/01 Python
pytorch-神经网络拟合曲线实例
2020/01/15 Python
Python class的继承方法代码实例
2020/02/14 Python
python怎么提高计算速度
2020/06/11 Python
HTML5新增加的功能详解
2016/09/05 HTML / CSS
新加坡网上化妆品店:Best Buy World
2018/05/18 全球购物
美国小蜜蜂Burt’s Bees德国官网:天然唇部、皮肤和身体护理产品
2020/06/14 全球购物
华为慧通笔试题
2016/04/22 面试题
改进作风怎么办发言材料
2014/08/17 职场文书
《1942》观后感
2015/06/08 职场文书
Python机器学习之逻辑回归
2021/05/11 Python
Pandas实现DataFrame的简单运算、统计与排序
2022/03/31 Python