【问题标题】:Decrypt Java AES/CBC/PKCS5Padding with CryptoJS使用 CryptoJS 解密 Java AES/CBC/PKCS5Padding
【发布时间】:2021-08-13 13:38:01
【问题描述】:

我在用 Java 加密的 CryptoJS 解密文本时遇到了一些问题。解密应该使用 AES/CBC/PKCS5Padding 完成。加密的字符串是 base64 编码的,我在尝试解密字符串之前对其进行解码。

Java 代码如下所示:

private static byte[] doAES(int mode, byte[] dataToEncrypt, String secretKey, String salt) throws Exception {
        byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        IvParameterSpec ivspec = new IvParameterSpec(iv);
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), 65536, 256);
        SecretKey tmp = factory.generateSecret(spec);
        SecretKeySpec secretKeySpec = new SecretKeySpec(tmp.getEncoded(), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(mode, secretKeySpec, ivspec);
        
        return cipher.doFinal(dataToEncrypt);
}

这就是我尝试在 CryptoJS 中解密它的方式。 SharedSecretKey 是 Java 中的 secretKey 和 salt 值。

let decoded = Buffer.from(encodedString, 'base64')
console.log("Result: " + CryptoJS.AES.decrypt({
  ciphertext: CryptoJS.enc.Hex.parse(decoded.toString().substring(32))
}, CryptoJS.enc.Hex.parse(CryptoJS.SHA1(sharedSecretKey).toString().substring(0,32)),  
  {
    iv: CryptoJS.lib.WordArray.create(Buffer.alloc(16)),
  }).toString(CryptoJS.enc.Utf8))

decoded 是我要解密的解码后的 Base64 字符串。但是,这不起作用,我收到错误“错误:格式错误的 UTF-8 数据”。我不确定我是否遗漏了什么,非常感谢任何帮助。

【问题讨论】:

  • Java 中的 encrypt 函数使用了一种名为 PBKDF2密钥派生方法,cryptojs 中缺少该方法。您的 Java 加密没有显示密文(doAES 的结果)使用了哪些进一步的编码,但在另一个框架中讨论解密时这很重要。可以在这里找到一些如何使用 PBKDF2 和 AES/CBC 运行完整的跨平台加密的示例(免责声明:我是作者):github.com/java-crypto/cross_platform_crypto/blob/main/docs/…

标签: java encryption cryptography aes cryptojs


【解决方案1】:

在 CryptoJS 代码中,缺少使用 PBKDF2 的密钥派生。 CryptoJS 默认使用 SHA1。
密文可以通过Base64编码,会隐式转换为CipherParams对象:

var encodedString = "0O15lUg8sE1G0+BjO5N2j8AjVKXV4J+18z5DinbM6tYjoILhL0WDTFWbcTiN+pG/";
var key = CryptoJS.PBKDF2(
  "my passphrase", 
  "my salt", 
  {
    keySize: 256 / 32, 
    iterations: 65536
  }
);
var decryptedData = CryptoJS.AES.decrypt(encodedString, key,  
  {
    iv: CryptoJS.enc.Utf8.parse("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"),
  }
);

console.log("Result: " + decryptedData.toString(CryptoJS.enc.Utf8));
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>

上述示例中的密文是之前使用发布的 Java 代码生成的。

请注意,静态 IV 是不安全的。 IV 通常是为每次加密随机生成的,并与密文一起传递(通常是连接的)。与盐类似,它是为每个密钥派生随机生成的,并与密文和 IV 一起传递,例如盐|iv|密文。 IV 和 salt 都不是秘密的,不需要加密。

另外,用getBytes()编码和用new String()解码时要在Java代码中指定编码,否则可能会出现跨平台问题。

【讨论】:

    猜你喜欢
    • 2019-06-27
    • 1970-01-01
    • 1970-01-01
    • 2018-11-28
    • 1970-01-01
    • 2018-11-13
    • 2020-04-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多