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

回到顶部