php 3des加密 兼容JAVA 多么痛的领悟呀
最近和别人做接口用到SOCKET TCP/IP方式
其中需要对账号和密码进行3DES加密
对方提供了一个加密比对的软件和JAVA的实现代码
并且给了我们一个长度为32位的密钥
这边需要用PHP来实现!
PHP 3des加密的密钥位24位!关于这个密钥长度的问题纠结了很久
最后被哥蒙对了!
32位长度如何转化为24位呢
我是这样做的
将32位的前16位取出来放到后面 这样32+16 = 48位
然后用
$key = pack('H48',$key)
正好是24位!
也就是16进制转化为字节流
这也是有依据的,这种叫着对称加密
当然加密的方式为cbc模式
cbc模式加密是需要一个向量来增加安全性的
看JAVA代码如下
IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
这样就看到JAVA中的向量是用字节数组表示的!
但是在PHP中该如何表示呢
当然需要先将此字节数组转化成16进制字符串
在php中就是
00 00 00 00 00 00 00 00(在实际运算中中间的空格要去掉)
如果JAVA的向量为new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }呢
那么在PHP中就是 01 02 03 04 05 06 07 08
然后再用PACK函数转化一下,如下:
$iv = pack('H*','0000000000000000')
好了 向量和密钥确定了,剩下的就是加密了
代码如下:
function en3DESEx($str){ $key = '56781234D56F012BCD5E701A3CDD670956781234D56F012B';//已经改变成48位 $key = pack('H48',$key); $td = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_CBC, ''); // $iv = pack('H*',"0102030405060708"); //like c# new byte[]{1,2,3,4,5,6,7,8} $iv = pack('H*','0000000000000000'); mcrypt_generic_init($td, $key, $iv); $encrypted_data = mcrypt_generic($td,$str ); mcrypt_generic_deinit($td); mcrypt_module_close($td); return bin2hex($encrypted_data); // 转化成16进制字符串 } $str = '12345678' echo en3DESEx($str); 结果 /** * 明文:12345678 * 密文:b2a85cf088D9ff03 */
而别人给我的软件加密的结果为:B2A85CF088D9FF03
正好将小写转化成大写字母就对了
附带解密函数
function de3DESEx($str){ // 注意 由于加密的时候转化成了16进制,所以解密的字符串也位16进制 $key = '56781234D56F012BCD5E701A3CDD670956781234D56F012B'; $key = pack('H48',$key); $td = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_CBC, ''); // $iv = pack('H*',"0102030405060708"); //like c# new byte[]{1,2,3,4,5,6,7,8} $iv = pack('H*','0000000000000000'); mcrypt_generic_init($td, $key, $iv); $encrypted_data = mdecrypt_generic($td, pack('H*',$str)); // 解密用的PHP自带函数 mcrypt_generic_deinit($td); mcrypt_module_close($td); return $encrypted_data; } // 然后神奇般的解密成功了!
总结!其实现在的很多语言已经很自能化了,一切的东西别人已经给你封装好了,该怎么用?
呵呵!已经要深刻的了解好业务,不然最后会是多么痛苦的领悟呀!