【问题标题】:How can I decrypt the cipher encrypt from Java using CryptoJS like this如何像这样使用 CryptoJS 解密从 Java 加密的密码
【发布时间】:2021-05-30 08:29:19
【问题描述】:

首先,很抱歉我的英语不好,可能会让你混淆我在说什么。但我真的希望有人能帮助我……

这是我加密密码的 Java 代码:

public static String decryptByAES_CBC(String data, String key) {
    try {
        byte[] decryptFrom = convertHexStringToBytes(data);

        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");

        String iv = new StringBuffer(key).reverse().toString();
        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());

        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

        byte[] original = cipher.doFinal(decryptFrom);
        return new String(original);
    } catch (Exception e) {
        LogUtil.exception(e);
        return null;
    }
}

现在开始用 Java 加密:

EncryptionUtil.encryptByAES_CBC("whywhywhywhywhywhy", "9999999999999999”);

然后得到结果:

030f7c7d57e82c6fb7d3066363e59c9dd6de7daa486146857552d31403a7cc71

我可以在 CryptoJS 中得到相同的加密结果,这是我的 CryptoJS 代码:

encodeByAES_CBC(data, key) {
    return CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(key), {
            iv : CryptoJS.enc.Utf8.parse(key),
            mode : CryptoJS.mode.CBC,
            padding : CryptoJS.pad.ZeroPadding
        }).ciphertext.toString();
},
decodeByAES_CBC(data, key) {
    return CryptoJS.AES.decrypt(data, CryptoJS.enc.Utf8.parse(key), {
            iv : CryptoJS.enc.Utf8.parse(key),
            mode : CryptoJS.mode.CBC,
            padding : CryptoJS.pad.ZeroPadding
        }).toString(CryptoJS.enc.Utf8);
}

这是一个让我困惑的问题: 例如:

var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase");
console.log(decrypted.toString(CryptoJS.enc.Utf8)); \\ The output is "Message"

输出是正确的,因为参数encryptedCipherParams 类型。

但是当我只有从服务器获得的030f7c7d57e82c6fb7d3066363e59c9dd6de7daa486146857552d31403a7cc71 和密钥9999999999999999 一样的密文时,我不知道如何获得正确的解密答案。

嗯……就是这样,希望我说的足够清楚……

【问题讨论】:

  • 您必须以 CryptoJS 在解密期间隐式或显式地提供 CipherParams 对象的方式传递数据。您可以将数据作为CipherParams 对象显式传递(封装密文,如果使用密码短语,则为盐)。或者您可以传递 OpenSSL 格式的数据,然后 CryptoJS 将执行隐式转换。
  • @Topaco THX!你是对的!让我感到困惑的是,当我没有盐时,如何解密。但它可能不需要盐,因为我使用填充模式:CryptoJS.pad.ZeroPadding

标签: javascript java encryption aes cryptojs


【解决方案1】:

我已经找到方法了。

var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase”);

CryptoJS.AES.decrypt(CryptoJS.lib.CipherParams.create({
            ciphertext: encrypted.ciphertext,
            salt: encrypted.salt
        }).toString(CryptoJS.format.OpenSSL),key).toString(CryptoJS.enc.Utf8)); \\ The output also is "Message"

在我的 Java 代码中,因为我使用了 Noppading(注意:Java 中的 Noppading = CryptoJS 中的 Zeropadding !!!这给我带来了很多麻烦……),所以不需要在 CryptoJS.lib.CipherParams 中添加盐.create()。

所以如果我只能从 Java 加密中获取密码和密钥。我可以解密

CryptoJS.AES.decrypt(CryptoJS.lib.CipherParams.create({
        ciphertext: CryptoJS.enc.Hex.parse(data)
      }).toString(CryptoJS.format.OpenSSL), CryptoJS.enc.Utf8.parse(key), {
        iv : CryptoJS.enc.Utf8.parse(key),
        mode : CryptoJS.mode.CBC,
        padding : CryptoJS.pad.ZeroPadding
    }).toString(CryptoJS.enc.Utf8);

仍然希望我所说的对这个问题足够清楚。我希望它可以帮助其他人......

【讨论】:

  • 如果盐是在相关加密期间生成的,则解密需要盐,这是从密码短语派生密钥(和 IV)的情况,请参阅The Cipher Input
  • Padding 与盐无关。 Java 的NoPadding 对应的是CryptoJS.pad.NoPaddingZeroPadding 可能对你有用,因为如果明文长度已经是块大小的整数倍,CryptoJS 的ZeroPadding 不会填充)。
  • @Topaco OK!我将详细了解为什么我使用CryptoJS.pad.ZeroPadding.THX 时它可以在不加盐的情况下成功解密!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-17
  • 2014-12-16
  • 2016-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多