-1

I am looking for a way, to encrypt a password in CryptoJS and then decrypt it in php. I have looked at other posts concerning the same subject, but I need someone to explain all that IV and key stuff.

My CryptoJS encryption code:

password = document.getElementById("usrp").value;
password = CryptoJS.AES.encrypt(password, <?php echo '"'.$_SESSION['adk'].'"'; ?>);
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
Jojo01
  • 1,269
  • 4
  • 14
  • 35
  • 1
    What is the problem exactly? *"explain all that iv and key stuff"* is really not a specific answerable statement. – Artjom B. Jul 27 '15 at 10:29
  • Do you have any question? What’s your problem with *all that iv and key* stuff? AES encrypts data with a key (password), you will get the same data back if you use the same key. – idmean Jul 27 '15 at 10:30
  • In the other posts they had some kind of iv string that had random numbers in it, does the iv need to be generated or can i just put random numbers? – Jojo01 Jul 27 '15 at 10:30
  • You don’t need an iv string at all with CrypoJS. – idmean Jul 27 '15 at 10:31
  • http://stackoverflow.com/questions/29509934/encrypt-with-cryptojs-and-decrypt-with-php – Jojo01 Jul 27 '15 at 10:31
  • Ah yes. That is because the PHP and CryptoJS implementation are slightly different. So do what the answer says? Or is there any problem? But that does not concern AES, does it? – idmean Jul 27 '15 at 10:33
  • There is no problem, i just need to know if the iv can be random, or needs to be generated. – Jojo01 Jul 27 '15 at 10:34
  • In my code i use this custom technique: adk(Aes decryption key). Which is a random string containing 100 letters and characters, and that gets regenerated often. So i need to know can the IV be random like adk, or does it need to be generated using a cryptoJs function. – Jojo01 Jul 27 '15 at 10:38

1 Answers1

3

IV

You're using the CBC mode of operation which requires an IV. If you use a static IV for all your ciphertexts then you miss out on an important property of encryption which is semantic security. If you use the same IV, attackers may observe your ciphertext and determine whether you sent the same plaintext with the same key, because the ciphertext will be the same.

To prevent that, you can generate a random IV for each encryption you do. The IV doesn't have to be secret, but it has to be unpredictable. Since it doesn't have to be secret, you can simply prepend it to the ciphertext and slice it off before decryption or send it otherwise in a structured fashion. You need to use IV during decryption. Otherwise, the first block will be different from the original plaintext.

Keep in mind that CryptoJS' WordArray.random() uses Math.random() internally which is not cryptographically secure. It would be better to use a better randomness source. You can use this drop in replacement from my project of that function for semi-modern browsers which uses the WebCrypto API:

(function(C){
    var WordArray = C.lib.WordArray;
    var crypto = window.crypto;
    var TypedArray = Int32Array;
    if (TypedArray && crypto && crypto.getRandomValues) {
        WordArray.random = function(nBytes){
            var array = new TypedArray(Math.ceil(nBytes / 4));
            crypto.getRandomValues(array);
            return new WordArray.init(
                    [].map.call(array, function(word){
                        return word
                    }),
                    nBytes
            );
        };
    } else {
        console.log("No cryptographically secure randomness source available");
    }
})(CryptoJS);

and use it like this:

var iv = CryptoJS.lib.WordArray.random(128/8);

Key

The key is trickier, because it needs to be kept confidential. The basic way is:

Let the user type in the password that is also present on the server and derive the key from the password by for example using PBKDF2 which CryptoJS also provides. Perfectly secure as long as you use TLS and the developers don't change the code.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • you explained all that IV and key stuff very well ;-) I just want to add, that the IV is _not only_ needed in CBC mode and that choosing an adequate mode for a specific application is something one should spend some time with. – Sebastian S Jul 27 '15 at 11:16
  • Ok, but how to implement your more secure randomisation API? Do i put it in the cryptojs aes file or what? – Jojo01 Jul 28 '15 at 06:37
  • Put it in a script block before you use it. It can go at the beginning of your own code. – Artjom B. Jul 28 '15 at 07:35
  • So if i put it in a script block the javascript function `CryptoJS.lib.WordArray.random(128/8);` will use your script instead? – Jojo01 Jul 28 '15 at 07:36
  • @Jojo01 Yes, it will. – Artjom B. Jul 28 '15 at 07:41
  • I have tried to see if your script is being used, by putting an `alert('artjomb is being used');` inside the if in your script, but the alert triggers even if i am not randomising anything. – Jojo01 Jul 28 '15 at 07:52
  • @Jojo01 Yes, that's expected because the code snippet replaces the word array random function. That has to be done before it is used.. – Artjom B. Jul 28 '15 at 07:55
  • Ok, thank you, i have noticed that the random numbers become more complex when your script is used. – Jojo01 Jul 28 '15 at 07:58
  • On last question, is the iv var declared like this: `var iv = CryptoJS.enc.Hex.parse(CryptoJS.lib.WordArray.random(128/8));` or like this: `var iv = CryptoJS.lib.WordArray.random(128/8);` ? – Jojo01 Jul 28 '15 at 08:04
  • @Jojo01 The latter. The first case couldn't work because parse works on strings and not on word arrays. – Artjom B. Jul 28 '15 at 08:09