【问题标题】:Java DES/ECB/PKCS5Padding encrypted value are not sameJava DES/ECB/PKCS5Padding 加密值不相同
【发布时间】:2020-04-19 08:24:05
【问题描述】:

我正在尝试使用带有硬编码密钥的 DES/ECB/PKCS5Padding 算法在 Java 中加密相同的数据。我使用online tool 验证了我的加密值。如果我使用带有特殊字符的密钥,那么 Java 和 online tool 的加密值就不一样了。

如果我使用密钥 2b7e151628aed2a6abf71589 并输入文本 1234 则加密结果与online tool 相同。此文本使用 Java 的加密结果是 SRC/0ptoT78=online tool 相同,图片也附上供参考

但如果我使用密钥 /£½ZBÝy‚÷Í(Ó—&*Ænù;'³ 并再次输入文本 1234 则加密结果与 @ 不同987654326@。本文使用Java加密后的结果为UUoh48bB9dM=,与online tool不同,另附图片供参考

我的java代码如下

import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.Key;

public class Main {

    public static void main(String[] args) {
        try {
            System.out.println(encrypt("/£½ZBÝy‚÷Í( Ó—&*Ænù­;‘³", "1234"));

             System.out.println(encrypt("2b7e151628aed2a6abf71589", "1234"));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String encrypt(String key, String str) throws Exception {



        DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
         System.out.println(new String(key.getBytes(), "UTF-8"));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        Key secretKey = keyFactory.generateSecret(desKeySpec);

        cipher.init(Cipher.ENCRYPT_MODE, secretKey);


        byte[] bytes = cipher.doFinal(str.getBytes("utf-8"));

        byte[] base64Bytes = Base64.encodeBase64(bytes);
        return new String(base64Bytes);
    }


    public static String decrypt(String key, String str) throws Exception {
        byte[] data =Base64.decodeBase64(str);
        DESKeySpec dks = new DESKeySpec(key.getBytes());
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        Key secretKey = keyFactory.generateSecret(dks);
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decryptedBytes = cipher.doFinal(data);
        return new String(decryptedBytes, "gb2312");
    }
}

【问题讨论】:

  • DES 使用二进制密钥,而不是文本格式的密码。您应该以二进制形式提供您的密钥,例如字节数组或十六进制编码字符串。在线工具不允许您正确提供二进制 DES 密钥,这使得该工具对 DES 毫无用处。
  • 此外,针对测试向量进行测试比针对糟糕的网站进行测试更有意义。

标签: java spring-boot encryption java-8 3des


【解决方案1】:

这很可能是您本地默认编码和网站默认编码之间的冲突。

要解决这个问题,请在提取密钥字节时指定编码:

import static java.nio.charsets.StandardCharsets.UTF_8;
...
DESKeySpec dks = new DESKeySpec(key.getBytes(UTF_8))

另外,您指定了非标准编码gb2312。尝试改用 UTF-8、UTF-16 或朋友。

return new String(decryptedBytes, UTF_8);

如果仍然不起作用,请尝试使用StandardCharsets 中提供的其他值(请参阅Javadoc)。

【讨论】:

  • 我尝试了java文档中提到的每个编码,但是使用这个键时结果仍然不一样 /£½ZBÝy‚÷Í(Ó—&*Ænù;‘³
  • DES 已过时,ECB 模式很危险,因为它会泄露数据。你真的需要使用更好的东西,比如 AES-GCM。
  • 我知道 DES 已过时,但我们必须使用它,因为我们正在使用需要 DES 加密的第 3 方 api
猜你喜欢
  • 1970-01-01
  • 2017-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-03
相关资源
最近更新 更多