Craig Bruce

JavaScript Crypto

We all know that JavaScript Crypto is inherently unsafe, but adding layers of security to your web application to make an attackers life harder is certainly not a bad thing.

Following is an example where the client retrieves some encrypted data from the server and decrypts it in the browser.

The library we will use for client side crypto is CryptoJS.

Browser Crypto is still an experimental technology and not supported by all browsers yet, so let's get cracking with an established alternative:

yarn add crypto-js

For crypto, the application uses the AES algorithm with CBC mode of operation. We need to import the following modules:

import { aes, bitArray, codecBase64 }, CryptoJS from 'crypto-js';

The first thing to ensure is that both server and client are talking the same language, by this I mean encoding.

In our case the key, initialization vector and content are all encoded with Base64. The client makes a HTTP request for the data and the content is sent back down the wire using something like this:

outputStream = new Base64OutputStream(outputStream)  

It is worth noting that the cryptographic key and iv in this case are retrieved by a separate api call and assigned to the variable key.

Please make sure your iv and key are not the same thing and also follow general security good practices.

A separate call is then made to retrieve the encrypted content. The overall security architecture of your application may be different and should be researched carefully. This will be further explored in a future post.

// simplified for readability:

const data = await api.getEncryptedData();  
const key = await api.getKey(); 

const decrypted = aes.decrypt(  
    data, 
    CryptoJS.enc.Base64.parse(key.value),
    {
         iv: CryptoJS.enc.Base64.parse(key.initializationVector)
    });

We can then transform the decrypted data to a string or bytes as needed:

 const bytes = decrypted.toArrayBuffer();
 const string = decrypted.toString(enc.Utf8);

The important take-away for getting server and client crypto to work is to ensure your encoding is the same for content, key and initialization vector.