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 相关文章推荐
sourcesafe管理phpproj文件的补充说明(downmoon)
Apr 11 PHP
PHP去掉从word直接粘贴过来的没有用格式的函数
Oct 29 PHP
深入解析php之apc
May 15 PHP
解析获取优酷视频真实下载地址的PHP源代码
Jun 26 PHP
学习php中的正则表达式
Aug 17 PHP
thinkphp的静态缓存用法分析
Nov 29 PHP
CodeIgniter基于Email类发邮件的方法
Mar 29 PHP
PHP.vs.JAVA
Apr 29 PHP
Yii CGridView用法实例详解
Jul 12 PHP
php执行多个存储过程的方法【基于thinkPHP】
Nov 08 PHP
php实现的支付宝网页支付功能示例【基于TP5框架】
Sep 16 PHP
Aliyun Linux 编译安装 php7.3 tengine2.3.2 mysql8.0 redis5的过程详解
Oct 20 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 google或baidu分页代码
2009/11/26 PHP
PHP图片处理之使用imagecopyresampled函数实现图片缩放例子
2014/11/19 PHP
php中socket通信机制实例详解
2015/01/03 PHP
PHP实现链式操作的核心思想
2015/06/23 PHP
php英文单词统计器
2016/06/23 PHP
PHPUnit测试私有属性和方法功能示例
2018/06/12 PHP
JavaScript去除空格的几种方法
2006/10/03 Javascript
extjs render 用法介绍
2013/09/11 Javascript
jquery实现多级下拉菜单的实例代码
2013/10/02 Javascript
js打开新窗口方法整理
2014/02/17 Javascript
JS实现的仿东京商城菜单、仿Win右键菜单及仿淘宝TAB特效合集
2015/09/28 Javascript
jquery.validate提示错误信息位置方法
2016/01/22 Javascript
Javascript技术栈中的四种依赖注入详解
2016/02/23 Javascript
全面解析DOM操作和jQuery实现选项移动操作代码分享
2016/06/07 Javascript
监听angularJs列表数据是否渲染完毕的方法示例
2018/11/07 Javascript
Node.js JSON模块用法实例分析
2019/01/04 Javascript
JavaScript实现汉字转换为拼音及缩写的方法示例
2019/03/28 Javascript
详解Angular Karma测试的持续集成实践
2019/11/15 Javascript
python使用multiprocessing模块实现带回调函数的异步调用方法
2015/04/18 Python
简单介绍Python中利用生成器实现的并发编程
2015/05/04 Python
python利用wx实现界面按钮和按钮监听和字体改变的方法
2019/07/17 Python
python函数声明和调用定义及原理详解
2019/12/02 Python
使用matplotlib动态刷新指定曲线实例
2020/04/23 Python
Python如何利用Har文件进行遍历指定字典替换提交的数据详解
2020/11/05 Python
世界著名的顶级牛排:Omaha Steak(奥马哈牛排)
2016/09/20 全球购物
美国运动鞋类和服装零售连锁店:Shoe Palace
2019/08/13 全球购物
中国一家综合的外贸B2C电子商务网站:DealeXtreme(DX)
2020/03/10 全球购物
DataList 能否分页,请问如何实现?
2015/05/03 面试题
ruby如何进行集成操作?Ruby能进行多重继承吗?
2013/10/16 面试题
企业治理工作自我评价
2013/09/26 职场文书
基层干部2014全国两会学习心得体会
2014/03/10 职场文书
周年庆促销方案
2014/03/15 职场文书
专业技术职务聘任书
2014/03/29 职场文书
银行主办会计岗位职责
2014/08/13 职场文书
委托证明书
2014/09/17 职场文书
python3中apply函数和lambda函数的使用详解
2022/02/28 Python