• 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'')  # 解密完成后将加密时添加的多余字符''删除
    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''补足
    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
  • 相关阅读:
    ECMAScript 6 基础入门
    软件历史版本存档及下载
    arduino 编程基础
    生活中的实验 —— 家庭电路
    电子元件 —— 继电器
    电与磁 —— 电磁铁
    windows cmd 命令行 —— 进程与服务
    计算机硬件、摄影设备、物质、材料英语
    DHCP服务器备份、还原、迁移
    SVN同步
  • 原文地址:https://www.cnblogs.com/sammy1989/p/9814983.html
Copyright © 2020-2023  润新知