Javascript 如何在CBC模式和PKCS7填充下解码使用AES-256加密的数据?

Javascript 如何在CBC模式和PKCS7填充下解码使用AES-256加密的数据?,javascript,java,cryptojs,Javascript,Java,Cryptojs,我们使用下面的java代码来解密在CBC模式下使用AES-256和PKCS7填充加密的数据 Java代码: import javax.crypto.spec.SecretKeySpec; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import java.security.*; import org.apache.commons.codec.binary.Base64; import org.apac

我们使用下面的java代码来解密在CBC模式下使用AES-256和PKCS7填充加密的数据

Java代码:

import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import java.security.*;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;


public class AES256 {

    private static byte[] initVector = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

    public String decrypt (String encryptedDataBase64, String keyBase64)
    {
       try {
           Security.setProperty("crypto.policy", "unlimited");
           IvParameterSpec ivSpec = new IvParameterSpec(initVector);  // Get the init vector

           // Get the Base64-encoded key
           byte[] key = Base64.decodeBase64(keyBase64.getBytes("UTF-8"));
           Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");  // AES / CBC / PKCS5 padding
           SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
           cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec);
           byte[] encryptedData = Base64.decodeBase64(encryptedDataBase64.getBytes("UTF-8"));
           byte[] decryptedData = cipher.doFinal(encryptedData);

           return new String(decryptedData);
       }
       catch (Exception e) {
           logger.error("AES256 Decrypt: Decryption exception: "+ e.getMessage());
           return null;
       }
    }
}
现在我们需要将这个解密逻辑转换为Javascript,因为我们的应用程序在从服务器请求index.html的同时发送头中的加密数据。我尝试使用Crypto.js解密,但我得到的解码字符串为空。下面是我试图使用的Javascript代码

var key = CryptoJS.enc.Base64.parse(keyBase64);
var data = CryptoJS.enc.Base64.parse(encryptedDataBase64);
var dec_data = CryptoJS.AES.decrypt(data, key);
dec_数据是空的


我在阅读了一些堆栈溢出问题后尝试了这个方法。任何人都可以告诉我代码中是否有错误。

很遗憾,您没有提供任何样本数据来测试您的环境,因此我设置了自己的值。使用此值:

ciphertext = rjygE0TjIqiQ4ETnpszoieRWzaSD+9oINf1c748VcL/3zD5AazSFomx4paeanihz
keyBase64 = MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=
ivBase =  AAAAAAAAAAAAAAAAAAAAAA==
我在Java上得到了这个解密结果:

The quick brown fox jumps over the lazy dog
在Javascript方面,我收到与代码相同的结果:

decrypted (str): The quick brown fox jumps over the lazy dog
可以在这里进行实时测试-Java:和Javascript:

请注意,我的代码没有异常处理,仅用于教育目的。此外,您的代码是不安全的,因为它使用静态(固定)键和初始化向量。

Java代码(在使用Java 11内置Base64编码器时略有更改):

Javascript代码:

let keyBase64 = 'MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=';
let ivBase64 = 'AAAAAAAAAAAAAAAAAAAAAA==';
let iv = CryptoJS.enc.Base64.parse(ivBase64);
let secret_key = CryptoJS.enc.Base64.parse(keyBase64);
ciphertext = 'rjygE0TjIqiQ4ETnpszoieRWzaSD+9oINf1c748VcL/3zD5AazSFomx4paeanihz';
console.log('ciphertext: ', ciphertext);
var decrypted = CryptoJS.AES.decrypt(ciphertext, secret_key,{
  iv: iv,
  padding: CryptoJS.pad.Pkcs7,
  mode: CryptoJS.mode.CBC,
});
console.log('decrypted (str): ', CryptoJS.enc.Utf8.stringify(decrypted).toString());

非常感谢,迈克尔。我可以知道什么是ivBase64吗?因为我们没有在Java代码中使用它。我们使用initVector={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};代码正在使用我的密钥和数据。我只是想了解为什么ivBase64是用“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa。正如您在Java代码中看到的,您的“null”iv被简单地编码为Base64字符串。我使用这个字符串作为Javascript端的init,所以我很高兴使用这个值(通过Base64解码)。还有其他方法可以直接创建16字节长的“null”变量:-)
let keyBase64 = 'MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=';
let ivBase64 = 'AAAAAAAAAAAAAAAAAAAAAA==';
let iv = CryptoJS.enc.Base64.parse(ivBase64);
let secret_key = CryptoJS.enc.Base64.parse(keyBase64);
ciphertext = 'rjygE0TjIqiQ4ETnpszoieRWzaSD+9oINf1c748VcL/3zD5AazSFomx4paeanihz';
console.log('ciphertext: ', ciphertext);
var decrypted = CryptoJS.AES.decrypt(ciphertext, secret_key,{
  iv: iv,
  padding: CryptoJS.pad.Pkcs7,
  mode: CryptoJS.mode.CBC,
});
console.log('decrypted (str): ', CryptoJS.enc.Utf8.stringify(decrypted).toString());