Implement AES Strength Encryption With JavaScript

I recently started playing around with the Dropbox Datastore JavaScript API and decided that I wanted an extra layer of security in the data I store on the Dropbox server.  I figured the best way to accomplish this would be to encrypt all data in my application before syncing.

It took me a while to find an encryption library that I liked, but in the end, I chose the JavaScript library Forge.  This library has plenty of cryptography tools that extend beyond just AES encryption, thus making it very worthy to check out.

To use Forge, I highly recommend you install NPM because it is one of the only ways to get a minified browser compatible version of the project.  With NPM installed, run the following to install Forge:

If you’re using Mac or Linux, you may need to include a sudo to install as a privileged user.

The next step is to download the full Forge Git repository so that we can run some scripts for minification.  Using a terminal or command prompt, navigate to the root directory of the Forge project and run:

The above two commands will produce a minified js/forge.min.js file that we can include in any HTML based project.

When working with cryptography, there are a few things you should familiarize yourself with.

Salts via Wikipedia

In cryptography, a salt is random data that is used as an additional input to a one-way function that hashes a password or passphrase.  The primary function of salts is to defend against dictionary attacks versus a list of password hashes and against pre-computed rainbow table attacks.

Initialization Vectors (IV) via Wikipedia

In cryptography, an initialization vector (IV) or starting variable (SV) is a fixed-size input to a cryptographic primitive that is typically required to be random or pseudorandom.  Randomization is crucial for encryption schemes to achieve semantic security, a property whereby repeated usage of the scheme under the same key does not allow an attacker to infer relationships between segments of the encrypted message.

With this in mind, we are going to make use of AES-CBC 128 bit encryption ciphers.  To start things off, lets go ahead and create a key based upon a password phrase and a salt:

With our cipher key generated, we now need to create a random initialization vector.

The salt, pass phrase, and initialization vector will be required for both encryption and decryption.  They must remain consistent for a successful conversion, so it is best to store the salt and iv alongside the encrypted cipher text.

Now for the fun stuff.  We are now going to encrypt a string of text with the purpose of storing it in a database.

The above code will use our salted key and initialization vector to encrypt a string of text.  By default, the cipher text will be randomness that we probably shouldn’t store in a datastore.  Instead we are using forge.util.encode64 to make it Base64 encoded.  This Base64 encoded cipher text along with a Base64 version of the salt and iv, should be stored in your datastore.  If you’re using AngularJS, you can do something like this to store the encrypted string in local storage:

Now that we have our encrypted item stored in a database, it is time to decipher it for use.  The steps are going to be similar, with the exception we are going to re-use the salt and iv.

If you include some kind of remote data storage in your application, now you can add peace of mind that the data will be protected.

The following is an example service you can use if you’re operating with AngularJS:

The best part of this, is you can use it in mobile hybrid applications.  I for example, am using Forge with Ionic Framework for Android and iOS.

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.

  • Karan

    Thanks a ton for this informative article.
    However could you help me understand how would the user decry-pt data if he/she installs the app on a new phone.
    Since the salt and iv were stored in previous phone (and we had just the cipherText stored in remote db and that is not sufficient to decrypt)?

    How do we incorporate disaster recovery in case user’s device that had iv and salt stored gets destroyed?

    • Hi Karan,

      If you use a salt to hash your pass phrase, you’ll need it to decrypt. Otherwise the whole point is forgotten. The salt is to turn your pass phrase into a secret key. It protects your cipher text from dictionary attacks.

      The IV depends on what operation mode you decided to use. I believe certain modes ignore the IV.

      I recommend you store the salt and IV remotely if you’re storing the cipher text remotely. If you don’t want to store it together, store it elsewhere.

      Does this help?

      • Karan

        Thanks for your reply.
        I guess it a necessary load one has to live with, just so the wire readers don’t get to read English but junk !

  • Henry H

    Hey Nic,

    Thanks for sharing. How did you inject forge into your AngularJS application? I’ve installed it using bower and forge.js is showing up in the sources but not of the methods on forge are available. Any direction would be appreciated! Thanks!

    • You might want to take a look at this:

      https://www.airpair.com/ionic-framework/posts/ionic-firebase-password-manager

      I added Forge to my Ionic project which uses AngularJS.

      Regards,

      • Very handy. Just one thing I dont get, you just point in your html to the forge.min.js to set it up and running? No need to include ‘Forge’ as a dependency in the app.js?

        • Forge lets you use it as a browser library, so all you need to do is include forge.min.js in your HTML file.

          You might check out this tutorial I made for creating a password manager using Forge:

          https://www.airpair.com/ionic-framework/posts/ionic-firebase-password-manager

          Regards,

          • Thanks for that. I tried as you explained in the other tutorial with forge.min.js, and that worls fine on my server with nodejs, but not on my actual device when installed. It seems to me that it requires node? Are there other ways to include the dependecy injections?

          • Did you look at the GitHub project that went with that article?:

            https://github.com/nraboy/ionic-cipher-safe-app

            It is a 100% working example with Forge in a hybrid app. You just need to include forge.min.js like you would any other HTML project.

            Regards,

          • Thanks for that, very useful, going to have a look in the upcoming hours!!

          • Thanks Nic, once again. Having that sample really helped. Basically I didnt get that you only needed the the forge.min.js file. I tried to include the whole forge library, and had not correctly specified the bower components – so when I pushed it to github it did not take into account the forge folder. Copying the file forge.min.js to a seperate folder (js) solved the issue. Have a nice day!

          • Awesome, I’m glad it worked out 🙂

  • Hello Nic, thanks for this tutorial. Can you clarify a bit more on where the Salt and IV should be stored? Should I perhaps encrypt them as well?

    • The Salt and IV are not sensitive and should be stored with your encrypted cipher text.

      Salts and IVs are used to prevent brute force attacks by adding an extra layer of randomness.

      Regards,

  • castillobg

    This was very helpful. Thanks, Nic!

  • Douglas Mak

    Correct me if I misunderstood, so you’re implementing some kind of encryption before syncing it with Dropbox. Why would you want to do this in the browser or Angular? Especially if you are storing the salt and IV in the localStorage. That’s not secure at all. The better way would be to do this on the server-side.

    • Yes, server side would be ideal, but explain to me why local storage is a bad idea? It is one more level of security on the data that you store remotely. Last I checked the only way to obtain data from browser storage is to have access to the machine it resides on.

      If you know something I don’t, please share it. Always open to feedback regarding improvement.

      Best,

      • Prince Lamba

        Hi @[email protected]:disqus The key to decrypt and encrypt is salt and IV which we are storing in localstorage ,so anybody can use that to decrypt our senstive data on Localstorage so how its safe now .

        • Yes, if they had your cipher text, iv, and salt, as well as your pass key, they could decrypt your data. This is really no different than what would happen if you had server side encryption. If your remote database is hacked, they will have all the appropriate pieces as well.

          https://stackoverflow.com/a/13915596/498479

          The purpose of using salts and iv values is to prevent rainbow table attacks. They are not sensitive pieces of information like pass keys.

          The big ticket item here is that iv and salt values are not user defined pass keys which should never be stored in the database.

  • True Nigerian

    Hi Nic, upon encryption on the client (in this case, ionic), how do I decrypt it on a php server?

    • It’s been many years since I worked with PHP, but as long as you have the salt, IV, and cipher text, you should be able to find a PHP library that will accept it.

      Best,