Java DES算法转Python3的坑
参考博客:https://www.cnblogs.com/Tommy-Yu/p/5867181.html
今天写mock遇到一个比较坑的事情,Java加密的Python解不了密,具体看一下代码:
Java代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.vcredit.entrustdelegator.utils; 2 3 import javax.crypto.Cipher; 4 import javax.crypto.SecretKey; 5 import javax.crypto.SecretKeyFactory; 6 import javax.crypto.spec.DESKeySpec; 7 import java.nio.charset.StandardCharsets; 8 import java.security.SecureRandom; 9 10 11 public class Encrypt { 12 13 /** 14 * 解密报文 15 * 16 * @param value 密文 17 * @param key 密钥 18 * @return 解密明文 19 * @throws Exception 异常 20 */ 21 public static String decrypt3DES(String value, String key) throws Exception { 22 return new String(decrypt(hex2byte(value.getBytes()), key.getBytes()), StandardCharsets.UTF_8); 23 } 24 25 26 /** 27 * 加密报文 28 * 29 * @param value 明文 30 * @param key 密钥 31 * @return 加密报文 32 * @throws Exception 异常 33 */ 34 public static String encrypt3DES(String value, String key) throws Exception { 35 return byte2hex(encrypt(value.getBytes(StandardCharsets.UTF_8), key.getBytes())); 36 } 37 38 private static byte[] hex2byte(byte[] buffer) { 39 if (buffer.length % 2 != 0) { 40 throw new IllegalArgumentException("长度不是偶数"); 41 } else { 42 byte[] var1 = new byte[buffer.length / 2]; 43 44 for (int var2 = 0; var2 < buffer.length; var2 += 2) { 45 String var3 = new String(buffer, var2, 2); 46 var1[var2 / 2] = (byte) Integer.parseInt(var3, 16); 47 } 48 49 return var1; 50 } 51 } 52 53 private static String byte2hex(byte[] buffer) { 54 StringBuilder var1 = new StringBuilder(); 55 for (byte aBuffer : buffer) { 56 String var2; 57 if ((var2 = Integer.toHexString(aBuffer & 255)).length() == 1) { 58 var1.append("0").append(var2); 59 } else { 60 var1.append(var2); 61 } 62 } 63 return var1.toString().toUpperCase(); 64 } 65 66 private static byte[] encrypt(byte[] src, byte[] key) throws Exception { 67 SecureRandom var2 = new SecureRandom(); 68 DESKeySpec key1 = new DESKeySpec(key); 69 SecretKey key2 = SecretKeyFactory.getInstance("DES").generateSecret(key1); 70 Cipher var3; 71 (var3 = Cipher.getInstance("DES")).init(1, key2, var2); 72 return var3.doFinal(src); 73 } 74 75 private static byte[] decrypt(byte[] src, byte[] key) throws Exception { 76 SecureRandom var2 = new SecureRandom(); 77 DESKeySpec key1 = new DESKeySpec(key); 78 SecretKey key2 = SecretKeyFactory.getInstance("DES").generateSecret(key1); 79 Cipher var3; 80 (var3 = Cipher.getInstance("DES")).init(2, key2, var2); 81 return var3.doFinal(src); 82 } 83 }
坑一:3DES
从上面的代码看解密函数是decrypt3DES,“3DES”让人以为是DES3算法,其实Java中的3DES对应的是“DESede”,于是利用Python的DES3算法解密,结果解不出来。这里其实用的还是DES算法。
坑二:DES
上面代码写的是getInstance("DES"),没有指明具体是什么算法,按照默认的来了,Java默认算法应该是DES/ECB/PKCS5Padding,Python我也用默认的了,还好默认的算法和Java一样,不过这里编码的时候最好明确指出,避免歧义。
坑三:Java的DES对key没有检查(参考的博客中有说明,写的很给力,很到位,一针见血)
如果key大于8位,则默认截取前8位用来加密!不报错!
但是Python中会报错,所以一开始用DES算法,看到报错了就觉得是算法用错了,然后用DES3算法,坑啊。
最后还是用DES算法,密码截取前8位,然后解密成功了!
对应Python代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from Crypto.Cipher import DES 2 import binascii 3 4 def des_decode(data, key): 5 """aes解密 6 :param key: 7 :param data: 8 """ 9 cipher = DES.new(key) 10 result2 = binascii.a2b_hex(data) # 十六进制还原成二进制 11 decrypted = cipher.decrypt(result2) 12 print(decrypted) 13 return decrypted.rstrip(b'\0') # 解密完成后将加密时添加的多余字符'\0'删除 14 15 16 def aes_encrypt(data, key): 17 """des加密函数,如果data不是16的倍数【加密文本data必须为16的倍数!】,那就补足为16的倍数 18 :param key: 19 :param data: 20 """ 21 cipher = DES.new(key) 22 block_size = DES.block_size 23 # 判断data是不是16的倍数,如果不是用b'\0'补足 24 if len(data) % block_size != 0: 25 add = block_size - (len(data) % block_size) 26 else: 27 add = 0 28 data += b'\x03' * add 29 encrypted = cipher.encrypt(data) # des加密 30 result = binascii.b2a_hex(encrypted) # b2a_hex encode 将二进制转换成16进制 31 return result
posted on 2018-10-19 10:32 sammy1989 阅读(1588) 评论(0) 编辑 收藏 举报