Java DES算法轉Python3的坑


參考博客:https://www.cnblogs.com/Tommy-Yu/p/5867181.html

今天寫mock遇到一個比較坑的事情,Java加密的Python解不了密,具體看一下代碼:

Java代碼:

 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 }
View Code

坑一: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代碼:

 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
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM