我正在使用 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 创建其 key 的方式:
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 字节的安全随机数组,并添加到加密数据之前。
最佳答案
经过一些研究,我找到了一个解决方案,即如何结合 Spring 4 Encryptors 和 CryptoJS。 Spring 在使用 PKCS #5 的 PBKDF2 的加密器 256 位 AES 中使用文档中提供的 - Spring Crypto docs IV 大小等于 16 字节。在 CryptoJS 中创建代码时,该信息至关重要。要记住的另一件事是在整个加密/解密过程中使用相同的 salt 和 iv one message。有了这些信息,我们就可以开始编码了(在这个例子中,我在 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 代码中,我发现 key 的创建长度为 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 的一部分切掉,单独用于解密过程。当然,一切都必须是十六进制编码,但这就是 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;
}
希望对大家有所帮助:)
干杯!
关于java - Spring 4 加密器与 cryptojs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29927385/