What are the AES parameters used and the steps taken inside crypto-js to encrypt a password message?

Background: The application I'm working on should work offline. I have to encrypt some text data using a password as a key on the java server side. The encrypted data is transmitted to the HTML5 page and on the client side, using the crypto-js library, the encrypted server data must be decrypted.

My problem: To encrypt my message in such a way that the client can decrypt it using crypt-js (using a user-entered password), I need to know the exact steps that crypto-js expects when encrypting the message.

What I need to know: I have the following encryption code that encrypts the message on the client side using crypto-js.

var message = "my message text"; var password = "user password"; var encrypted = CryptoJS.AES.encrypt( message ,password ); console.log(encrypted.toString()); 

I need to know the AES settings used by CryptoJS when encrypting a message (not sure what it is, but it sounds like this: key size (256), padding (pkcs5), mode (CBC), PBE algorithm (PBKDF2), salt (random) , iteration counter (100)). It would be very helpful if anyone could confirm this ... I tried to solve this secret in the last few days?

I need to know the various steps CryptoJS takes while AES encrypts the message

+2
javascript security encryption cryptojs
source share
2 answers

CryptoJS uses the non-standardized OpenSSL KDF for key derivation ( EvpKDF ) with MD5 as a hash algorithm and 1 . IV is also derived from a password, which means that only the actual encrypted text, password, and salt are needed to decrypt this on the Java side.

In other words, PBKDF2 is not used for key derivation in CryptoJS password mode. By default, AES-256 is used in CBC mode with the PKCS5 add-on (which is the same as the PKCS7 add-on ). Keep in mind that you may need the JCE Unlimited Strength Jurisdiction Policy Files . See Also. Why are there restrictions on the use of encryption with keys for a certain length?

The following code recreates KDF in Java ( keySize and ivSize are respectively 8 for AES-256 and appear).

 public static byte[] evpKDF(byte[] password, int keySize, int ivSize, byte[] salt, int iterations, String hashAlgorithm, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException { int targetKeySize = keySize + ivSize; byte[] derivedBytes = new byte[targetKeySize * 4]; int numberOfDerivedWords = 0; byte[] block = null; MessageDigest hasher = MessageDigest.getInstance(hashAlgorithm); while (numberOfDerivedWords < targetKeySize) { if (block != null) { hasher.update(block); } hasher.update(password); block = hasher.digest(salt); hasher.reset(); // Iterations for (int i = 1; i < iterations; i++) { block = hasher.digest(block); hasher.reset(); } System.arraycopy(block, 0, derivedBytes, numberOfDerivedWords * 4, Math.min(block.length, (targetKeySize - numberOfDerivedWords) * 4)); numberOfDerivedWords += block.length/4; } System.arraycopy(derivedBytes, 0, resultKey, 0, keySize * 4); System.arraycopy(derivedBytes, keySize * 4, resultIv, 0, ivSize * 4); return derivedBytes; // key + iv } 

Here is the complete class for reference:

 public class RecreateEVPkdfFromCryptoJS { public static void main(String[] args) throws UnsupportedEncodingException, GeneralSecurityException { String msg = "hello"; String password = "mypassword"; String ivHex = "aab7d6aca0cc6ffc18f9f5909753aa5f"; int keySize = 8; // 8 words = 256-bit int ivSize = 4; // 4 words = 128-bit String keyHex = "844a86d27d96acf3147aa460f535e20e989d1f8b5d79c0403b4a0f34cebb093b"; String saltHex = "ca35168ed6b82778"; String openSslFormattedCipherTextString = "U2FsdGVkX1/KNRaO1rgneK9S3zuYaYZcdXmVKJGqVqk="; String cipherTextHex = "af52df3b9869865c7579952891aa56a9"; String padding = "PKCS5Padding"; byte[] key = hexStringToByteArray(keyHex); byte[] iv = hexStringToByteArray(ivHex); byte[] salt = hexStringToByteArray(saltHex); byte[] cipherText = hexStringToByteArray(cipherTextHex); byte[] javaKey = new byte[keySize * 4]; byte[] javaIv = new byte[ivSize * 4]; evpKDF(password.getBytes("UTF-8"), keySize, ivSize, salt, javaKey, javaIv); System.out.println(Arrays.equals(key, javaKey) + " " + Arrays.equals(iv, javaIv)); Cipher aesCipherForEncryption = Cipher.getInstance("AES/CBC/PKCS5Padding"); // Must specify the mode explicitly as most JCE providers default to ECB mode!! IvParameterSpec ivSpec = new IvParameterSpec(javaIv); aesCipherForEncryption.init(Cipher.DECRYPT_MODE, new SecretKeySpec(javaKey, "AES"), ivSpec); byte[] byteMsg = aesCipherForEncryption.doFinal(cipherText); System.out.println(Arrays.equals(byteMsg, msg.getBytes("UTF-8"))); } public static byte[] evpKDF(byte[] password, int keySize, int ivSize, byte[] salt, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException { return evpKDF(password, keySize, ivSize, salt, 1, "MD5", resultKey, resultIv); } public static byte[] evpKDF(byte[] password, int keySize, int ivSize, byte[] salt, int iterations, String hashAlgorithm, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException { int targetKeySize = keySize + ivSize; byte[] derivedBytes = new byte[targetKeySize * 4]; int numberOfDerivedWords = 0; byte[] block = null; MessageDigest hasher = MessageDigest.getInstance(hashAlgorithm); while (numberOfDerivedWords < targetKeySize) { if (block != null) { hasher.update(block); } hasher.update(password); block = hasher.digest(salt); hasher.reset(); // Iterations for (int i = 1; i < iterations; i++) { block = hasher.digest(block); hasher.reset(); } System.arraycopy(block, 0, derivedBytes, numberOfDerivedWords * 4, Math.min(block.length, (targetKeySize - numberOfDerivedWords) * 4)); numberOfDerivedWords += block.length/4; } System.arraycopy(derivedBytes, 0, resultKey, 0, keySize * 4); System.arraycopy(derivedBytes, keySize * 4, resultIv, 0, ivSize * 4); return derivedBytes; // key + iv } /** * Copied from http://stackoverflow.com/a/140861 * */ public static byte[] hexStringToByteArray(String s) { int len = s.length(); byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16)); } return data; } } 

and the JavaScript code that was used to generate the values ​​in the Java code:

 var msg = "hello"; var password = "mypassword"; // must be present on the server var encrypted = CryptoJS.AES.encrypt( msg, password ); var ivHex = encrypted.iv.toString(); var ivSize = encrypted.algorithm.ivSize; // same as the blockSize var keySize = encrypted.algorithm.keySize; var keyHex = encrypted.key.toString(); var saltHex = encrypted.salt.toString(); // must be sent as well var openSslFormattedCipherTextString = encrypted.toString(); // not used var cipherTextHex = encrypted.ciphertext.toString(); // must be sent 
+7
source share

I look in the documentation here:

  • key size: "If you use a passphrase, it will generate a 256-bit key."
  • padding: Pkcs7 (default)
  • : CBC (default)
  • iv: generated and stored in the encryption text object: use with "encrypted.iv"

Key Generation Material:

  • salt: generated and stored in an encryption text object: use with "encrypted.salt" (although this is actually not the case, so I assume here)
  • pbe algorithm: Unclear. It is not documented.
  • number of iterations: I cannot find this documented. The code examples seem to use 1000.

You can set the parameters manually, which is probably safer than relying on the default values, for example. some pseudo code based on examples in the documentation:

 var salt = CryptoJS.lib.WordArray.random(128/8); var iv = CryptoJS.lib.WordArray.random(128); var key256Bits10000Iterations = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 256/32, iterations: 10000 }); //I don't know this is dividing by 32 var encrypted = CryptoJS.AES.encrypt("Message", key, { mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7, iv:iv }); 

You may have to experiment. I would do it step by step. Get the keys based on the password to match, mixing up these parameters, and then secure the ciphertext, then determine the decryption. Avoid trying to simplify things like skip IV or use the ECB.

0
source share

All Articles