我正在使用Spring 4 Encryptors类处理加密:
String salt = KeyGenerators.string().generateKey();
TextEncryptor textEncryptor = Encryptors.text("MY_SECRET_KEY", salt);
textEncryptor.encrypt(json);
在客户端javascript中我试图使用CryptoJS解密
var uncrypted = CryptoJS.AES.decrypt(serverEncrypted, "MY_SECRET_KEY");
$("#encrypted-data").val(uncrypted);
我猜我需要恢复十六进制编码部分,但我不明白需要做什么。
我在解密前尝试过解析,但没有什么好处。
CryptoJS.enc.Hex.parse(serverEncrypted)
spring文档说文本方法将在“标准”加密方法中以十六进制值加密,使用PKCS#5的PBKDF2进行256位AES加密
[搜索进度]
这就是Spring创建密钥的方式:
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 1024, 256);
SecretKey secretKey = newSecretKey("PBKDF2WithHmacSHA1", keySpec);
SecretKeySpec secretKey = new SecretKeySpec(secretKey.getEncoded(), "AES");
加密:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv));
iv是一个8字节的安全随机数组,并且是加密数据的前缀。
答案 0 :(得分:1)
经过一番研究,我找到了一个解决方案,如何结合Spring 4加密器和CryptoJS。 Spring在其加密器256位AES中使用PKCS#5的PBKDF2,如文档中提供的那样 - Spring Crypto docs,IV大小等于16字节。在CryptoJS中创建代码时,该信息至关重要。要记住的另一件事是在加密/解密的整个过程中使用相同的盐和iv 一条消息。有了这个信息,我们可以开始编码(在这个例子中,我加密CryptoJS中的消息并在Spring中解密): CryptoJS
const keySize = 256;
const ivSize = 128;
const iterations = 1024;
function encrypt(msg, pass) {
const salt = CryptoJS.lib.WordArray.random(128 / 8);
const key = CryptoJS.PBKDF2(pass, salt, {
keySize: keySize / 32,
iterations: iterations
});
const iv = CryptoJS.lib.WordArray.random(ivSize / 8);
const encrypted = CryptoJS.AES.encrypt(msg, key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
});
// salt, iv will be hex 32 in length
// append them to the ciphertext for use in decryption
return salt.toString() + iv.toString() + encrypted.ciphertext.toString();
}
如您所见,所有加密的结果都是 salt + iv + encryptedMessage 的串联。同样重要的是,在Spring代码中我发现密钥是以256长度和1024次迭代创建的:
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), Hex.decode(salt), 1024, 256);
现在我们可以将这个准备好的结果带到我们的Spring代码并解密:
private static String decrypt(String encryptedData, String keyStr) {
final String salt = encryptedData.substring(0, 32);
final String encryptedPart = encryptedData.substring(32);
final TextEncryptor textEncryptor = Encryptors.text(keyStr, salt);
return textEncryptor.decrypt(encryptedPart);
}
Spring AES加密器将使用IV切割部分并将其用于解密过程。当然,所有内容都必须是 Hex编码,但这就是Spring TextEncrytpors的工作方式。
相反的过程(在Spring中加密和在CryptoJS中解密)将完全相同。在CryptoJS中,我们必须提取 salt 和 iv :
const keySize = 256;
function decrypt (encryptedMessage, pass) {
var salt = CryptoJS.enc.Hex.parse(encryptedMessage.substr(0, 32));
var iv = CryptoJS.enc.Hex.parse(encryptedMessage.substr(32, 32))
var encrypted = encryptedMessage.substring(64);
var key = CryptoJS.PBKDF2(pass, salt, {
keySize: keySize / 32,
iterations: iterations
});
var decrypted = CryptoJS.AES.decrypt(encrypted, key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
})
return decrypted;
}
我希望它能帮到某人:)
干杯!