CryptoJS AES加密和Java AES解密
我之所以这么问,是因为我已经阅读了两天的许多关于加密AES加密的文章,而当我以为自己得到了它时,我意识到我根本没有得到它。
我已经尝试了许多方法来做,但是我做得还没对。
加密在CryptoJS上完成,它们将加密的字符串作为GET参数发送。
GetParamsForAppUrl.prototype.generateUrlParams = function() {const self = this;
return new Promise((resolve, reject) => {
const currentDateInMilliseconds = new Date().getTime();
const secret = tokenSecret.secret;
var encrypted = CryptoJS.AES.encrypt(self.authorization, secret);
encrypted = encrypted.toString();
self.urlParams = {
token: encrypted,
time: currentDateInMilliseconds
};
resolve();
});
};
我可以使用CryptoJS在javascript上通过以下方式轻松解密:
var decrypted = CryptoJS.AES.decrypt(encrypted_string, secret); console.log(decrypted.toString(CryptoJS.enc.Utf8));
但是出于安全原因,我不想在Javascript上执行此操作,因此我尝试在Java上进行解密:
String secret = "secret";byte[] cipherText = encrypted_string.getBytes("UTF8");
SecretKey secKey = new SecretKeySpec(secret.getBytes(), "AES");
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.DECRYPT_MODE, secKey);
byte[] bytePlainText = aesCipher.doFinal(byteCipherText);
String myDecryptedText = = new String(bytePlainText);
在我不知道自己在做什么之前,我尝试了base64解码,添加了一些IV和我读过的很多东西,当然,这些都不起作用。
但是,当我开始理解我在做什么之后,我在上面写了一个简单的脚本,并在帖子中得到了相同的错误:
我不知道从这里去哪里。在阅读了大量有关此内容的内容之后,解决方案似乎是散列或填充,但是我无法控制加密方法,因此我无法真正地散列或填充秘密。
但是正如我说的,我可以更改密钥,使其可以匹配特定的长度,并且我尝试过更改它,但是由于我在黑暗中拍摄,所以我真的不知道这是否是解决方案。
所以,我的问题基本上是,如果我得到了加密的字符串( )和密钥,是否有办法(
)对其进行解密?如果是这样,该怎么办?
回答:
CryptoJS实现与OpenSSL相同的密钥派生功能,并采用相同的格式将IV放入加密的数据中。因此,适用于处理OpenSSL编码数据的所有Java代码。
给出以下Javascript代码:
var text = "The quick brown fox jumps over the lazy dog. ???? ????";var secret = "René Über";
var encrypted = CryptoJS.AES.encrypt(text, secret);
encrypted = encrypted.toString();
console.log("Cipher text: " + encrypted);
我们得到密文:
U2FsdGVkX1+tsmZvCEFa/iGeSA0K7gvgs9KXeZKwbCDNCs2zPo+BXjvKYLrJutMK+hxTwl/hyaQLOaD7LLIRo2I5fyeRMPnroo6k8N9uwKk=
在Java方面,
String secret = "René Über";String cipherText = "U2FsdGVkX1+tsmZvCEFa/iGeSA0K7gvgs9KXeZKwbCDNCs2zPo+BXjvKYLrJutMK+hxTwl/hyaQLOaD7LLIRo2I5fyeRMPnroo6k8N9uwKk=";
byte[] cipherData = Base64.getDecoder().decode(cipherText);
byte[] saltData = Arrays.copyOfRange(cipherData, 8, 16);
MessageDigest md5 = MessageDigest.getInstance("MD5");
final byte[][] keyAndIV = GenerateKeyAndIV(32, 16, 1, saltData, secret.getBytes(StandardCharsets.UTF_8), md5);
SecretKeySpec key = new SecretKeySpec(keyAndIV[0], "AES");
IvParameterSpec iv = new IvParameterSpec(keyAndIV[1]);
byte[] encrypted = Arrays.copyOfRange(cipherData, 16, cipherData.length);
Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
aesCBC.init(Cipher.DECRYPT_MODE, key, iv);
byte[] decryptedData = aesCBC.doFinal(encrypted);
String decryptedText = new String(decryptedData, StandardCharsets.UTF_8);
System.out.println(decryptedText);
结果是:
The quick brown fox jumps over the lazy dog. ???? ????
这就是我们开始的内容。表情符号,口音和变音符号也可以使用。
GenerateKeyAndIV
是一个辅助函数,可重新实现OpenSSL的密钥派生功能EVP_BytesToKey
(请参阅https://github.com/openssl/openssl/blob/master/crypto/evp/evp_key.c)。
/** * Generates a key and an initialization vector (IV) with the given salt and password.
* <p>
* This method is equivalent to OpenSSL's EVP_BytesToKey function
* (see https://github.com/openssl/openssl/blob/master/crypto/evp/evp_key.c).
* By default, OpenSSL uses a single iteration, MD5 as the algorithm and UTF-8 encoded password data.
* </p>
* @param keyLength the length of the generated key (in bytes)
* @param ivLength the length of the generated IV (in bytes)
* @param iterations the number of digestion rounds
* @param salt the salt data (8 bytes of data or <code>null</code>)
* @param password the password data (optional)
* @param md the message digest algorithm to use
* @return an two-element array with the generated key and IV
*/
public static byte[][] GenerateKeyAndIV(int keyLength, int ivLength, int iterations, byte[] salt, byte[] password, MessageDigest md) {
int digestLength = md.getDigestLength();
int requiredLength = (keyLength + ivLength + digestLength - 1) / digestLength * digestLength;
byte[] generatedData = new byte[requiredLength];
int generatedLength = 0;
try {
md.reset();
// Repeat process until sufficient data has been generated
while (generatedLength < keyLength + ivLength) {
// Digest data (last digest if available, password data, salt if available)
if (generatedLength > 0)
md.update(generatedData, generatedLength - digestLength, digestLength);
md.update(password);
if (salt != null)
md.update(salt, 0, 8);
md.digest(generatedData, generatedLength, digestLength);
// additional rounds
for (int i = 1; i < iterations; i++) {
md.update(generatedData, generatedLength, digestLength);
md.digest(generatedData, generatedLength, digestLength);
}
generatedLength += digestLength;
}
// Copy key and IV into separate byte arrays
byte[][] result = new byte[2][];
result[0] = Arrays.copyOfRange(generatedData, 0, keyLength);
if (ivLength > 0)
result[1] = Arrays.copyOfRange(generatedData, keyLength, keyLength + ivLength);
return result;
} catch (DigestException e) {
throw new RuntimeException(e);
} finally {
// Clean out temporary data
Arrays.fill(generatedData, (byte)0);
}
}
请注意,您必须安装Java密码学扩展(JCE)无限强度管辖权策略。否则,密钥大小为256的AES将无法工作并引发异常:
java.security.InvalidKeyException: Illegal key size
我已经取代奥拉·比尼的Java代码的EVP_BytesToKey
,我在我的答案的第一个版本,搭配出更地道,更容易理解Java代码(见上文)。
以上是 CryptoJS AES加密和Java AES解密 的全部内容, 来源链接: utcz.com/qa/433177.html