Encrypting data with Crypto-JS in JavaScript


I have been working intermittently on a HTML5 mobile application for some time now. This application stores some sensitive date locally (it is a standalone mobile application) and I did not want to store the data in clear text. I wanted to make retrieval of data difficult to some extent, if the device ends up in the wrong hands. So the data had to be encrypted. The application code is in JavaScript, so I started looking for a JS library that can encrypt data. I found that Crypto-JS met my requirements and it was easy to use too.

Before I proceed further, I must confess that my knowledge of encryption and digital security in general is very basic. So the solutions discussed in this post may not be the best in terms of protecting the data.

As I said, Crypto-JS is very simple to use. You can use different cipher algorithms like AES. DES etc. and APIs are simple. e.g. to encrypt using AES , you would call –

encryptedData = CryptoJS.AES.encrypt(textToEncrypt, secretPhrase); //include aes.js script

In the above API, the first argument to encrypt function is text data you want to encrypt, e.g. password. The second argument is a secret phrase (also called passPhrase). This could be any text. Secret phrase is the key that is used to encrypt the data. However you will have to use the same key (secret phrase) when decrypting the data.

The decision I had to make was how to select a secret phrase/key. Most server-side applications generate a key and store it in a secure location on the server and use that key to encrypt data. However my application is a mobile application written in JavaScript, so it would be very easy to find the secret key if someone really wants to – by looking at the JS source code. So I decided to ask user to enter secret key along with password at the time of registration and subsequent login attempts.
When user registers for the first time, she enters password and secret key/phrase. Using the secret key I encrypt the password and store it in the local database. I don’t save the secret key entered by the user. Subsequently login operation requires user to enter password as well as the same secret key she had entered at the time of registration. The problem with this approach is that user has to remember secret key along with the password.

If I did not want to retrieve password in clear text in the application and if I did not want to encrypt any other data in the application, I could have used hashing algorithm, instead of encryption e.g.

hashedPassword = CryptoJS.SHA256(password); //include sha256.js  script

Once the data is hashed, you cannot retrieve it in its original form. For the password example above, I could hash the password that user entered at the time of registration and store in the database. When user enters password at the time of login, I would hash it and compare the hashed value with the one stored in the database.

Coming back to the encrypt function, the value it returns is not a string, but an object. If you log the value to console, this is what you get –

20140913RetObjFromEncrypt

However you can store string representation of this object (by calling toString()) and use it in decrypt function. Interesting thing about the encrypt function is that the result of encryption is not the same each time you call the function with the same data and secret key. If you log the object returned by encrypt function above, you will see three fields – iv (initialization vector) , key and salt. Together they are used to encrypt the data. And these values change each time you call encrypt function with the same arguments (see demo at the end of this post).

Decrypt function is also very easy to use. You pass encrypted object/string and secret key to the function –

decryptedData = CryptoJS.AES.decrypt(encryptedData, secretPhrase);

The returned value is not a string, but a JS Object that contains array of words –

20140913RetObjFromDecrypt

To get back the original string, you need to call toString with proper encoding –

originalData = decryptedData.toString(CryptoJS.enc.Utf8);

Try out following demo. Enter data to be encrypted and secret key and click Encrypt button. The data would be encrypted and displayed next to the Encrypted Data label. To get back original text from the encrypted data, click Decrypt without changing the secret key. The original text would be displayed next to Decrypted Data label.

Data :
Secret Key :

Encrypted Data :
Decrypted Data :

-Ram Kulkarni

8 Replies to “Encrypting data with Crypto-JS in JavaScript”

    1. If you don’t need to retrieve the data and use it only for verification, for example, to verify the password, then you can use hashing. However I don’t think there would be many situations where you won’t need to get back the original data (even in the case of password you may want to retrieve and email it if user forgets the password). So in most cases you might want to use encryption.

  1. > even in the case of password you may want to retrieve and email it if user forgets the password

    NO NO NO NO NO!

    You *never* email passwords. And you neither encrypt them nor just hash them!

    You use an expensive one-way process using a known and tested algorithm (i.e. bcrypt/pbkdf2/scrypt) for authenticating a user’s secret value.
    If it has been forgotten and needs resetting, you send them a temporary single-use non-predictable token which is unrelated to their password.

  2. is it possible to decrypt javascript code without having secret key? i have seen people who do it and wondering how. i have the encrypted javascirpt file.

  3. var CryptoJS = require(“crypto-js”);
    var passphrase = “bymfqp92rs8iu52jxuf0g0klxozutrve8vv5bbikr”;
    var thingname = CryptoJS.AES.encrypt(req.body.name, passphrase);
    var thingtype = CryptoJS.AES.encrypt(req.body.type, passphrase);
    var resultn = mydevicename.toString();
    var resultt = mydevicetype.toString();
    var EJSONObject = {“name”: resultn, “type”:resultt };
    collection.insert(EJSONObject, function(err, result){ // Some code )};

    but when i decrypt :

    collection.find({},{},function(e,docs){
    decryptedName = CryptoJS.AES.decrypt(docs.name, passphrase);
    Console.log(decryptedName);

    I am getting error : TypeError: Cannot read property ‘salt’ of undefined

    How can I store SALT and IV for above example ?

Leave a Reply to Anonymous Cancel reply