我需要你的帮助,如何在 Spring Boot 中使用 CryptoJS 库。在我的客户端中使用来自https://stackoverflow.com/a/27582253的这个库 但我很难找到解密的解决方案。例如,在我的客户中,有一个像这样的损坏:
var encData = {"ct":"d97K/kt03Inh9wYp90iyNwefnaTwMAeQXTjOwJR+gU0=","iv":"4101e6c0938e312952ea24f19306cfb2","s":"615cc2b4480e260a"}
对于
public_key = S!ZcdNb4XXcw_jXbHQqiFsHp6
那么如何在服务器端使用Spring Boot解密encData?
我一直在尝试使用
javax.crypto
但总是出现错误
Wrong IV length: must be 16 bytes long
public static String decrypt(String passphrase, String jsonString) throws Exception {
JsonObject jsonObject = new Gson().fromJson(jsonString, JsonObject.class);
String saltHex = jsonObject.get("s").getAsString();
String ctBase64 = jsonObject.get("ct").getAsString();
String ivHex = jsonObject.get("iv").getAsString();
System.out.println(passphrase);
byte[] salt = hexStringToByteArray(saltHex);
byte[] ct = Base64.getDecoder().decode(ctBase64);
byte[] iv = hexStringToByteArray(ivHex);
//String concatedPassphrase = passphrase + new String(salt, StandardCharsets.UTF_8);
String concatedPassphrase = passphrase + byteArrayToString(salt);
System.out.println(concatedPassphrase);
byte[] md5 = md5(concatedPassphrase.getBytes(StandardCharsets.UTF_8));
for (int i = 1; i < 3; i++) {
md5 = md5(concatArrays(md5, concatedPassphrase.getBytes(StandardCharsets.UTF_8)));
}
byte[] key = Arrays.copyOf(md5, 32);
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
byte[] decryptedData = cipher.doFinal(ct);
return new String(decryptedData, StandardCharsets.UTF_8);
} catch (Exception e) {
//e.printStackTrace();
return e.getMessage();
}
}
有人可以帮助我吗?
您错误地移植了密钥导出函数。正确的是例如:
...
byte[] concatedPassphrase = concatArrays(passphrase.getBytes(StandardCharsets.UTF_8), salt);
byte[] md5 = md5(concatedPassphrase);
byte[] result = md5;
for (int i = 1; i < 3; i++) {
md5 = md5(concatArrays(md5, concatedPassphrase));
result = concatArrays(result, md5);
}
byte[] key = Arrays.copyOf(result, 32);
...
通过此更改,解密有效。
请注意,密钥派生函数应实现 OpenSSL 专有密钥派生函数
EVP_BytesToKey()
(至少此处需要的部分功能)。作为用户定义实现的替代方案,也可以使用 EVP_BytesToKey()
的 BouncyCastle 实现(如果在您的环境中可行):
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
...
OpenSSLPBEParametersGenerator pbeGenerator = new OpenSSLPBEParametersGenerator(new MD5Digest());
pbeGenerator.init(passphrase.getBytes(StandardCharsets.UTF_8), salt);
ParametersWithIV parameters = (ParametersWithIV) pbeGenerator.generateDerivedParameters(256, 0); // keySize, ivSize in bits
byte[] key = ((KeyParameter)parameters.getParameters()).getKey();
提示:BouncyCastle 还提供各种编码器(例如用于十六进制编码/解码)。
安全性:请注意,今天
EVP_BytesToKey()
被认为是不安全的。更可靠的密钥导出函数是 Argon2 或至少 PBKDF2(与随机盐结合)。