QNimate

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

Passphrase Based Encryption using Web Cryptography API

This post is a part 5 of Web Cryptography API Tutorial post series.
⎗ Previous: Digital Signature using Web Cryptography API.

In this tutorial I will show you how create a symmetric key using a passphrase and then encrypt or decrypt data using that generated key.

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 Symmetric Public Key from Passphrase

Here is the code to generate key for encryption and decryption using a passphrase

var password = "password";

var key = null;

crypto.subtle.digest({name: "SHA-256"}, convertStringToArrayBufferView(password)).then(function(result){

    window.crypto.subtle.importKey("raw", result, {name: "AES-CBC"}, false, ["encrypt", "decrypt"]).then(function(e){
        key = e;
    }, function(e){
            console.log(e);
    });

});

Here I am first generating 256 bit hash of the passphrase because AES-CBC algorithm’s key size has to be 128 bit, 192 bit or 256 bit. This hash value is the symmetric encryption key now.

Then I am using importKey to create a key object from the hash value. importKey is actually meant to be used to import a key which was exported using exportKey. Here I am pretending the hash value was exported using exportKey

Encrypting String

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

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

var data  = "narayan prusty";

var encrypted_data = null;

function encrypt_data()
{
    crypto.subtle.encrypt({name: "AES-CBC", iv: vector}, key, convertStringToArrayBufferView(data)).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

var decrypted_data = null;


function decrypt_data()
{
    crypto.subtle.decrypt({name: "AES-CBC", iv: vector}, key, encrypted_data).then(
        function(result){
            decrypted_data = new Uint8Array(result);
            console.log(convertArrayBufferViewtoString(decrypted_data));
        },
        function(e){
            console.log(e.message);
        }
    );
}

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 password = "password";

var key = null;

crypto.subtle.digest({name: "SHA-256"}, convertStringToArrayBufferView(password)).then(function(result){

    window.crypto.subtle.importKey("raw", result, {name: "AES-CBC"}, false, ["encrypt", "decrypt"]).then(function(e){
        key = e;

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

});



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

var data  = "narayan prusty";

var encrypted_data = null;

function encrypt_data()
{
    crypto.subtle.encrypt({name: "AES-CBC", iv: vector}, key, convertStringToArrayBufferView(data)).then(
        function(result){
            encrypted_data = new Uint8Array(result);
            decrypt_data();
        },
        function(e){
            console.log(e.message);
        }
    );
}      

var decrypted_data = null;


function decrypt_data()
{
    crypto.subtle.decrypt({name: "AES-CBC", iv: vector}, key, encrypted_data).then(
        function(result){
            decrypted_data = new Uint8Array(result);
            console.log(convertArrayBufferViewtoString(decrypted_data));
        },
        function(e){
            console.log(e.message);
        }
    );
}
Feb 19, 2015Narayan Prusty
Track Adblock Users with Google AnalyticsJavaScript "0o" Literal
Comments: 6
  1. Manuel
    5 years ago

    The correct way to derivate a key from a password is using PBKDF2
    Unfortunately by now does not work in Safari
    The method you are showing here achieves very low security.

    ReplyCancel
  2. Massimo
    5 years ago

    Is there a way to save the passphrase key in local storage?

    ReplyCancel
  3. Massimo Cassandro
    5 years ago

    Very very interesting

    ReplyCancel
  4. simplyencrypt
    5 years ago

    Nice Blog!!.

    ReplyCancel
  5. *There are certainly a lot of details like that to take into consideration. That is a great point to bring up. I offer the thoughts above as general inspiration but clearly there are questions like the one you bring up where the most important thing will
    5 years ago

    *It?s hard to find knowledgeable people on this topic, but you sound like you know what you?re talking about! Thanks

    ReplyCancel
  6. sergeyt
    7 years ago

    convertStringToArrayBufferView() doesn’t support non-ascii characters.

    It is better to use TextEncoder:

    var buffer = new TextEncoder("utf-8").encode(str);

    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.

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

2014 - 2015 © QNimate
All tutorials MIT license