缘起
由于需要,引入了rc4加密算法,网上搜到了一些PHP实现,Java实现,当然,对于PHP来讲,还有openssl的实现。
网址: http://zhiwei.li/text/2011/08/7777777777777777777/
上还证明了PHP的实现和openssl的实现是相同的,由于该网址有测试例子,自己执行一边,果然如该网址所言。
由于存在java实现的需要 ,于是就测试一下,java实现和PHP实现是否相同,由于PHP的实现和openssl的实现相同,于是只比较了openssl 和java的解密结果,果然不让人省心,结果是:不同!
开始折腾
好在rc4的算法比较简单,怀疑可能是网上找到的java版本实现有问题,参考PHP的实现,自己实现了一遍java版本,结果让人纠结,自己实现的和网上找到的结果完全一样,问题在哪里?
当我再次比较openssl和php的加密结果时:发现加密结果100%不同。事情进展到这个地步,更显扑朔迷离,怀疑自己原来测试的有问题,再次测试N边,依然没有问题,其不叫人发疯。
最后,再拿出 http://zhiwei.li/text/2011/08/7777777777777777777/ 来研究;发现里面的key是md5一个密钥字符串后再pack得到的,这个也有关系?试试吧,果然有关系。至此,想起来自己两次测试使用的key是不同的,成功的那次测试,key刚好也是16字节的,而失败的那次测试的key是“testkey”,才想起来,openssl在做加密时,如果key不够长(16字节),则会在后面补 “\0″(是零,不是圈儿),但是自己实现的RC4算法,是没有在key后面补 “\0” 的。
真相大白。
郁闷啊
附测试脚本:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43  | 
						<?php function RC4($key, $pt) {     $s = array();     for ($i=0; $i<256; $i++) {         $s[$i] = $i;     }     $j = 0;     $key_len = strlen($key);     for ($i=0; $i<256; $i++) {         $j = ($j + $s[$i] + ord($key[$i % $key_len])) % 256;         //swap         $x = $s[$i];         $s[$i] = $s[$j];         $s[$j] = $x;     }     $i = 0;     $j = 0;     $ct = '';     $data_len = strlen($pt);     for ($y=0; $y< $data_len; $y++) {         $i = ($i + 1) % 256;         $j = ($j + $s[$i]) % 256;         //swap         $x = $s[$i];         $s[$i] = $s[$j];         $s[$j] = $x;         $ct .= $pt[$y] ^ chr($s[($s[$i] + $s[$j]) % 256]);     }     return $ct; } $text = 'This is a test string.'; $md5 = md5('password'); echo $md5 . "\n"; $key = pack('H*', $md5);  //嫌的话,让 $key = 'testkey'; 试试 print bin2hex(RC4($key, $text)); echo "\n"; echo bin2hex(openssl_encrypt($text, "RC4", $key, true)); echo "\n";  |