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程序设计有所帮助。
上一篇: 排查线上问题常用的几个Linux命令
下一篇: JS中遍历数组、对象的方式