I believe that because the key passed to AES.encrypt is a string, the function will automatically generate an IV. So is the code below producing a well secured encrypted version of string_to_encrypt?
pass = document.getElementById('pass').value; // user entered pwrd salt = 'some system determined salt';
its = 9000 + getKeyIterationModifier(pass); // iterations depend on pass
key = CryptoJS.PBKDF2(pass, salt, { keySize: 512/32, iterations: its });
encrypted = CryptoJS.AES.encrypt(string_to_encrypt, key.toString());
Or should I be adding 'mode' and 'padding' values to harden it further? If so, what are the current industry standard values?
In other words, should I ideally be using something like the following (perhaps without the iv if that's done automatically) and if so what's ideal:
key = CryptoJS.enc.Base64.parse(key);
encrypted = CryptoJS.AES.encrypt(string_to_encrypt, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
CryptoJS.AES.encrypt
uses EVP_BytesToKey to expand the passed "key" (considered a password) to an actual AES-256 key and IV if the "key" was a string. It uses a random salt for that, so the ciphertext is randomized. In your second snippet, you need to handle the IV yourself.
What you're essentially asking is whether EVP_BytesToKey is a secure password expansion function. That's not something that can be easily answered. The fact that it uses MD5 means that the first snippet has at least the security of AES-128 which should be good.
The other issue is that the IV should be unpredictable (read: random) for absolutely every encryption. Don't use a static IV, because that makes the cipher deterministic and therefore not semantically secure. An attacker who observes ciphertexts can determine when the same message prefix was sent before. This suggestion is a given in the first snippet, but you would have to work for that realization in the second snippet which might introduce other issues.
If you're not comfortable with CryptoJS and cryptography, go with the first snippet. Otherwise, try to improve the second snippet.
If you're using only symmetric encryption in the browser you need the exact same key at the server and the client. If you send the encryption key from the server to the client or the other way around you need to encrypt your symmetric encryption key. The easiest way to do this would be to use TLS. If you use TLS, then the data as well as key are encrypted, so you don't need to encrypt it yourself. This doesn't provide any security, just a little bit of obfuscation. You should read: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/
You should think about integrating authenticated encryption through an authenticated mode like GCM or EAX, or through the use of an encrypt-then-MAC scheme with a strong MAC like HMAC-SHA256.