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 相关文章推荐
ezSQL PHP数据库操作类库
May 16 PHP
php下将多个数组合并成一个数组的方法与实例代码
Feb 03 PHP
php安全开发 添加随机字符串验证,防止伪造跨站请求
Feb 14 PHP
smarty模板局部缓存方法使用示例
Jun 17 PHP
php实现学生管理系统
Mar 21 PHP
php array_merge_recursive 数组合并
Oct 26 PHP
thinkPHP5.0框架应用请求生命周期分析
Mar 25 PHP
PHP基于PDO实现的SQLite操作类【包含增删改查及事务等操作】
Jun 21 PHP
php反射学习之依赖注入示例
Jun 14 PHP
laravel框架模型、视图与控制器简单操作示例
Oct 10 PHP
TP5框架安全机制实例分析
Apr 05 PHP
PHP连接MSSQL数据库案例,PHPWAMP多个PHP版本连接SQL Server数据库
Apr 16 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
php魔术方法与魔术变量、内置方法与内置变量的深入分析
2013/06/03 PHP
php使用标签替换的方式生成静态页面
2015/05/21 PHP
Joomla调用系统自带编辑器的实现方法
2016/05/05 PHP
alixixi runcode.asp的代码不错的应用
2007/08/08 Javascript
解决Jquery向页面append新元素之后事件的绑定问题
2015/03/16 Javascript
Bootstrap入门书籍之(一)排版
2016/02/17 Javascript
使用bootstrap3开发响应式网站
2016/05/12 Javascript
webpack中引用jquery的简单实现
2016/06/08 Javascript
JavaScript的instanceof运算符学习教程
2016/06/08 Javascript
js时间戳格式化成日期格式的多种方法介绍
2017/02/16 Javascript
微信小程序五星评分效果实现代码
2017/04/06 Javascript
Node.js中sequelize时区的配置方法
2017/12/10 Javascript
发布Angular应用至生产环境的方法
2018/12/10 Javascript
在Vue mounted方法中使用data变量详解
2019/11/05 Javascript
javascript实现简易的计算器
2020/01/17 Javascript
Postman参数化实现过程及原理解析
2020/08/13 Javascript
适用于 Vue 的播放器组件Vue-Video-Player操作
2020/11/16 Javascript
python实现基于信息增益的决策树归纳
2018/12/18 Python
Python读取指定日期邮件的实例
2019/02/01 Python
python实现维吉尼亚加密法
2019/03/20 Python
Python基本语法之运算符功能与用法详解
2019/10/22 Python
python numpy矩阵信息说明,shape,size,dtype
2020/05/22 Python
部署Django到阿里云服务器教程示例
2020/06/03 Python
CSS3 中filter(滤镜)属性使用详解
2020/04/07 HTML / CSS
HTML5本地存储localStorage、sessionStorage基本用法、遍历操作、异常处理等
2014/05/08 HTML / CSS
苹果香港官方商城:Apple香港
2016/09/14 全球购物
国际政治个人自荐信范文
2013/11/26 职场文书
生产部主管岗位职责
2014/01/06 职场文书
霸气队列口号
2014/06/18 职场文书
人力资源管理专业求职信
2014/07/23 职场文书
党员批评与自我批评发言稿
2014/10/14 职场文书
大雁塔导游词
2015/02/04 职场文书
迎新晚会主持词开场白
2015/05/28 职场文书
学校学习型党组织建设心得体会
2019/06/21 职场文书
自己搭建resnet18网络并加载torchvision自带权重的操作
2021/05/13 Python
默认网关不可用修复后过一会又不好使了解决方法
2022/04/08 数码科技