DEV Community

Cover image for Encrypt Data With AES256: Complete Process with Sample JavaScript
raddevus
raddevus

Posted on

Encrypt Data With AES256: Complete Process with Sample JavaScript

Authenticated Encryption

If you're going to use a symmetric encryption algorithm like AES256 then it is necessary to insure that the encrypted data has not been tampered with.

High-Level View

This can be done by

  1. Generating a random IV (Initialization Vector) -- clearText sent to decrypting party.
  2. encrypting your data
  3. generating a MAC (Message Authentication Code) over your IV and encrypted data (using a secret key).
  4. Sending the MAC to the decrypting party so they can test for the same result.

Exact Process Is a Bit Confusing

The process is a bit confusing so here are the things I learned while encrypting a user's data properly.
You can read more about authenticated encryption at wikipedia.

Not Difficult, But A Challenge to Find Information

It's not difficult to do, but it was difficult to find all the information in one place so I decided to write this up.

What We Need For Authenticated Encryption

Authenticated encryption requires a few things:

  1. ClearText data (data to be encypted)
  2. Random IV (initialization vector) which will be passed in the clear -- AES256 needs 16 bytes of random data
  3. MAC key - A secret key used to generate the MAC (Message Authentication Code) which is 16-32 bytes of data, kept secret between you & the receiver who will decrypt the data
  4. MAC The final Message Authentication Code - generated over the IV & encrypted data, using the MAC key (secret key) - This code will be passed to the receiver (decrypting party) in the clear. This MAC must be known so the receiver can compare it to the value they calculate to insure the IV & encrypted data have not been tampered with.

Which Items Do You Supply to Decrypting Party?

One of the main points of confusion is created by not knowing which items should be supplied to the decrypting party.
If you aren't sure, you may feel like you are exposing data that a cracker could use to steal or corrupt the encrypted data.

Here's the exact list of what you must provide to the decrypting party and in what format (clearText or encrypted) they should be supplied.
Note: When I say something is clearText it means that the item can be exposed to anyone. IE - the data element does not have to be encrypted.

  1. Encrypted Data -- obviously this is the secret data you don't want exposed. Note: Our encryptedData will be base64 encoded (after encryption) to make it easier to transmit over HTTP).
  2. IV (initialization vector) -- This is a clearText value and in our case we generate a random value (using the CryptoJS library). This will be 16 random bytes (128 bits) and will be used when encrypting the data to randomize the output so the encrypted data is more random and more secure. The format of the data you provide to the decrypting party will be 2-byte hex values like: 137b276b3975612498e225657140c5a1
  3. MAC -- This is the clearText Message Authentication Code which is clearText which will be used by the decrypting party to validate that the IV & Encrypted Data that you sent has not be altered or corrupted. It will look like: 57bfeffc96a32402266abe2035801e8f65cbd58fc9d88dceb591572acb1dca74

Example Data Transfer Object (DTO)

If you were to load all that data into a DTO (JSON Object) it might look something like the following:

{MAC:"57bfeffc96a32402266abe2035801e8f65cbd58fc9d88dceb591572acb1dca74", IV:"137b276b3975612498e225657140c5a1", enryptedData:"dGhpcyBpc24ndCByZWFsbHkgZW5jcnlwdGVkLCBidXQgaXMganVzdCBhbiBleGFtcGxl"}

We send the MAC first (as a human-readable convenience) because the decrypting party will take the IV and Encrypted data, apply the MAC secret key and attempt to generate the MAC again. If it matches the decrypting party knows that the encrypted data and IV have not been altered or corrupted.

Ok, finally let's see it in action with some code.

Sample Code

There's a lot to this so I have posted some sample code so you can try it at via JSFiddle.

Please click the Result tab and try encrypting some data.

Point Out a Few Items of Interest

I will just point out a few items of interest.

Generate The IV Every Time We Encrypt

Every time the user clicks the Encrypt button, we generate a new Random IV. This insures that the data is randomized and more secure.

These are the two lines of code we use to do that:

let randomBytes   = CryptoJS.lib.WordArray.random(128/8).toString();
iv = CryptoJS.enc.Hex.parse(randomBytes);

Enter fullscreen mode Exit fullscreen mode

That means, even if you leave your password & clear text data the same, that the output encrypted text (base64 encoded) will change every time. This is all part of the randomization of the data to keep it secure.

See That In Action

To see that in action:

  1. Type in a password
  2. Type in some clear text data (to be encrypted)
  3. Just button-mash the Encrypt button and you'll see the output encrypted data changes every time.

Encrypting the Data

We use the following code to encrypt the data using our password.
CryptoJS is the library we are using to implement AES256.
Note: You can see the resources (come from CDN) in the JSFiddle tab above.

message = CryptoJS.AES.encrypt(clearTextData, CryptoJS.enc.Hex.parse(hashedPwd),{iv: iv});
Enter fullscreen mode Exit fullscreen mode

We call the encrypt() function and pass in:
clearTextData - our original message we want to encrypt.
Bytes of our password - our password was SHA256 hashed to keep it safe, now we parse it into hex bytes.
iv object - an object containing a param named iv and our randomly generated iv bytes.

That's It & RFC

That's it. Check it out and post any questions or comments you have about anything in the article.

I've used this to encrypt data on browser client, ElectronJS client and more & post data to my WebAPI. Later, I have decrypted the data using my Android app (Kotlin-based app) and other web clients.

Top comments (0)