QNimate

  • CoursesVideos
  • WP PremiumPlugins
  • DemosLab
  • Home
  • QIdea
  • QTrack
Home Carbon Ads Symmetric Encryption using Web Cryptography API

Symmetric Encryption using Web Cryptography API

This post is a part 2 of Web Cryptography API Tutorial post series.
⎘ Next post in the series is Asymmetric Encryption using Web Cryptography API.
⎗ Previous post in the series is Hashing using Web Cryptography API.

In this tutorial I will show you code example of how to generate public key of symmetric encryption and encrypt & decrypt data using the public key.

What is Symmetric Key Cryptography?

Symmetric-key encryption are algorithms for cryptography that use the same cryptographic keys(or public keys) for both encryption of plaintext and decryption of ciphertext(encrypted unreadable text).

Converting String to Array Buffer and Array Buffer to String

To encrypt text or binary data you first need to convert it to an array buffer type so that Web Cryptography API can encrypt it.

Here is code to convert a string to an array buffer

function convertStringToArrayBufferView(str)
{
    var bytes = new Uint8Array(str.length);
    for (var iii = 0; iii < str.length; iii++)
    {
        bytes[iii] = str.charCodeAt(iii);
    }

    return bytes;
}

After decrypting, Web Cryptography API returns original string as an array buffer. So we need to convert the array buffer to an string.

function convertArrayBufferViewtoString(buffer)
{
    var str = "";
    for (var iii = 0; iii < buffer.byteLength; iii++)
    {
        str += String.fromCharCode(buffer[iii]);
    }

    return str;
}

Generating Public Key

Here is the code to generate key for encryption and decryption

var crypto = window.crypto || window.msCrypto;

var key_object = null;

var promise_key = null;


if(crypto.subtle)
{
    alert("Cryptography API Supported");
   
    //Parameters:
    //1. Symmetric Encryption algorithm name and its requirements
    //2. Boolean indicating extractable. which indicates whether or not the raw keying material may be exported by the application (http://www.w3.org/TR/WebCryptoAPI/#dfn-CryptoKey-slot-extractable)
    //3. Usage of the key. (http://www.w3.org/TR/WebCryptoAPI/#cryptokey-interface-types)
    promise_key = crypto.subtle.generateKey({name: "AES-CBC", length: 128}, false, ["encrypt", "decrypt"]);

    promise_key.then(function(key){
        key_object = key;
    });

    promise_key.catch = function(e){
        console.log(e.message);
    }
}
else
{
    alert("Cryptography API not Supported");
}

Encrypting String

Here is the code to encrypt an JavaScript string using the retrieved key

var data = "QNimate";

var encrypted_data = null;
var encrypt_promise = null;

//iv: Is initialization vector. It must be 16 bytes
var vector = crypto.getRandomValues(new Uint8Array(16));           

function encrypt_data()
{
    encrypt_promise = crypto.subtle.encrypt({name: "AES-CBC", iv: vector}, key_object, convertStringToArrayBufferView(data));

    encrypt_promise.then(
        function(result){
            encrypted_data = new Uint8Array(result);
        },
        function(e){
            console.log(e.message);
        }
    );
}

Decrypting String

Here is the code to decrypt an encrypt array buffer using the same key which was used for encryption

function decrypt_data()
{
    decrypt_promise = crypto.subtle.decrypt({name: "AES-CBC", iv: vector}, key_object, encrypted_data);

    decrypt_promise.then(
        function(result){
            decrypted_data = new Uint8Array(result);
            console.log(convertArrayBufferViewtoString(decrypted_data));
        },
        function(e){
            console.log(e.message);
        }
    );
}

Importing and Exporting Keys

Sometimes you may need to send the key to the server. And also import key from server and use it in browser.

You can use crypto.subtle.exportKey to convert the key into many different exportable formats and then export it.

Similarly you can use crypto.subtle.importKey to convert the exported key into an key object for use.

Here is an sample code showing how to import and export the generated key

var json_key = null;
var string_key = null;

crypto.subtle.exportKey("jwk", key_object).then(function(result){
   
    json_key = result;
    string_key = JSON.stringify(json_key);

    crypto.subtle.importKey("jwk", JSON.parse(string_key), {name: "AES-CBC", iv: vector}, true, ["encrypt", "decrypt"]).then(function(e){
        console.log(e);
    }, function(e){
        console.log(e);
    });

}, function(e){
    console.log(e.message);
});

Here we first converted the key to JWK format and then to an string. You can send the string_key to server which is the string representation of the key.

Complete Code

Here is complete code together for testing or to play with

function convertStringToArrayBufferView(str)
{
    var bytes = new Uint8Array(str.length);
    for (var iii = 0; iii < str.length; iii++)
    {
        bytes[iii] = str.charCodeAt(iii);
    }

    return bytes;
}  

function convertArrayBufferViewtoString(buffer)
{
    var str = "";
    for (var iii = 0; iii < buffer.byteLength; iii++)
    {
        str += String.fromCharCode(buffer[iii]);
    }

    return str;
}

var crypto = window.crypto || window.msCrypto;

var key_object = null;

var promise_key = null;

var data = "QNimate";

var encrypted_data = null;
var encrypt_promise = null;

var vector = crypto.getRandomValues(new Uint8Array(16));           

var decrypt_promise = null;
var decrypted_data = null;

if(crypto.subtle)
{
    alert("Cryptography API Supported");
   
    promise_key = crypto.subtle.generateKey({name: "AES-CBC", length: 128}, false, ["encrypt", "decrypt"]);

    promise_key.then(function(key){
        key_object = key;
        encrypt_data();
    });

    promise_key.catch = function(e){
        console.log(e.message);
    }
}
else
{
    alert("Cryptography API not Supported");
}

function encrypt_data()
{
    encrypt_promise = crypto.subtle.encrypt({name: "AES-CBC", iv: vector}, key_object, convertStringToArrayBufferView(data));

    encrypt_promise.then(
        function(result){
            encrypted_data = new Uint8Array(result);
            decrypt_data();
        },
        function(e){
            console.log(e.message);
        }
    );
}

function decrypt_data()
{
    decrypt_promise = crypto.subtle.decrypt({name: "AES-CBC", iv: vector}, key_object, encrypted_data);

    decrypt_promise.then(
        function(result){
            decrypted_data = new Uint8Array(result);
            console.log(convertArrayBufferViewtoString(decrypted_data));
        },
        function(e){
            console.log(e.message);
        }
    );
}
Feb 10, 2015Narayan Prusty
Hashing using Web Cryptography APIAsymmetric Encryption using Web Cryptography API
Comments: 2
  1. Simon
    7 years ago

    Your stringToBytes routine assumes 1 byte per character, so will not deal with multibyte characters common in utf8. You should use TextEncoder.

    ReplyCancel
  2. Simon
    7 years ago

    There’s no such thing as a public key in symmetric encryption. There are no key pairs. If your key is not private (known only to sender and receiver), you’ve lost the battle.

    ReplyCancel

Leave a Reply Cancel reply

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

Narayan Prusty

I am a software engineer specialising in Blockchain, DevOps and Go/JavaScript. This is my personal blog where I write about things that I learn and feel interesting to share.

7 years ago 3 Comments Web Security
Share this
0
GooglePlus
0
Facebook
0
Twitter
0
Linkedin
  • What is Symmetric Key Cryptography?
  • Converting String to Array Buffer and Array Buffer to String
  • Generating Public Key
  • Encrypting String
  • Decrypting String
  • Importing and Exporting Keys
  • Complete Code
Related Articles
  • Asymmetric Encryption using Web Cryptography API
  • Passphrase Based Encryption using Web Cryptography API
  • Hashing using Web Cryptography API
  • Digital Signature using Web Cryptography API
  • Javascript Create File Object From URL
Our Sponsor
My Books

2014 - 2015 © QNimate
All tutorials MIT license