CryptoJS AES Encryption and Java AES Decryption

I only ask about it because I read a lot of messages over 2 days about AES encryption for cryptography, and when I thought I was receiving it, I realized that I wasnโ€™t receiving it at all.

This post is the closest to my problem, I have exactly the same problem, but it does not answer:

CryptoJS AES Encryption and JAVA AES Decryption Value Mismatch

I tried to do it in many ways, but I did not get it right.

First off

I get an already encrypted string (I just got the code to see how they do it), so changing the encryption method is not an option. That is why all such questions are not very useful to me.

Second

I have access to the secret key and I can change it (so setting the length is an option if necessary).

Encryption is performed on CryptoJS and they send the encrypted string as a GET parameter.

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();
 });
};

I can easily decrypt this into javascript using CryptoJS using

var decrypted = CryptoJS.AES.decrypt(encrypted_string, secret);
    console.log(decrypted.toString(CryptoJS.enc.Utf8)); 

But I don't want to do this in Javascript for security reasons, so I am trying to decrypt this in 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);

Before I had an idea of โ€‹โ€‹what I was doing, I tried to decode base64, adding a little IV and a lot of material that I read, of course, none of this worked.

But after I began to understand what I was doing, I wrote this simple script above and received the same error in the message: Invalid AES key length

, . , , , .

, , , , , , , .

, , ( javascript, , script) , ( Java)? , ?

+4
2

CryptoJS , OpenSSL, , IV . , Java, OpenSSL.

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. ๐Ÿ‘ป ๐Ÿ‘ป

, . emojis, .

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 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 Cryptography Extension (JCE) . AES 256 :

java.security.InvalidKeyException: Illegal key size

Ola Bini Java EVP_BytesToKey, , Java (. ).

. Java, openssl, AES?.

+9

. - ( ), .

. , . , . .

, IV, , . , . (KDF) , , , .

" AES" . getBytes(). , . , : ANSI, UTF-8, EBCDIC, . . , . , , .

Crypto , . , .

+2

Source: https://habr.com/ru/post/1665547/


All Articles