Javascript example that shows how to use the forge package to encrypt/decrypt objects

This example shows how to use the forge package to encrypt and decrypt objects. It also shows how to define a number of useful prototypes and other utility functions.

// ================================================================
// This example shows how to use the forge package to encrypt
// and decrypt a simple object.
//
// In addition shows how to define a number of useful prototypes
// and other utility functions.
// ================================================================

// You need this declaration if you are using nodejs.
// CITATION: https://github.com/digitalbazaar/forge
var forge = require('./forge/js/forge.js');

// ================================================================
// basename of a file
// ================================================================
function basename(str)
{
   var base = new String(str).substring(str.lastIndexOf('/') + 1); 
    if(base.lastIndexOf(".") != -1)       
        base = base.substring(0, base.lastIndexOf("."));
   return base;
}

// ================================================================
// Convert a string to bytes.
// http://stackoverflow.com/questions/6226189/how-to-convert-a-string-to-bytearray
// ================================================================
String.prototype.getBytes = function() {
    var bytes = [];
    for (var i = 0; i < this.length; i++) {
        var charCode = this.charCodeAt(i);
        var cLen = Math.ceil(Math.log(charCode)/Math.log(256));
        for (var j = 0; j < cLen; j++) {
            bytes.push((charCode << (j*8)) & 0xFF);
        }
    }
    return bytes;
}

// ================================================================
// Get the stack information for __line and __file (below).
// CITATION: http://stackoverflow.com/questions/11386492/accessing-line-number-in-v8-javascript-chrome-node-js
// ================================================================
Object.defineProperty(global, '__stack', {
    get: function() {
        var orig = Error.prepareStackTrace;
        Error.prepareStackTrace = function(_, stack){ return stack; };
        var err = new Error;
        Error.captureStackTrace(err, arguments.callee);
        var stack = err.stack;
        Error.prepareStackTrace = orig;
        return stack;
    }
});

// ================================================================
// The current source line number. Like __LINE__ in C++.
// ================================================================
Object.defineProperty(global, '__line', {
  get: function(){
    return __stack[1].getLineNumber();
  }
});

// ================================================================
// The current source file name. Like __FILE__ in C++.
// ================================================================
Object.defineProperty(global, '__file', {
    get: function(){
        return basename(__stack[1].getFileName());
    }
});

// ================================================================
// Info function that prints out the current line number.
// ================================================================
Object.defineProperty(global, '__line2', {
  get: function(){
    return __stack[2].getLineNumber();
  }
});

Object.defineProperty(global, '__file2', {
    get: function(){
        return basename(__stack[2].getFileName());
    }
});

function info(text) {
    console.log('INFO:' + __file2 + ':' + __line2 + ': ' + text);
}

// ================================================================
// Local assert, surprisingly useful.
// ================================================================
function Assert(result, message) {
    if (!result) {
        message = message || 'Assertion failed!';
        if (typeof Error != 'undefined') {
            throw new Error('ERROR:' + __file + ':' + __line + ': ' + message);
        }
        throw message; // if Error not defined
    }
}

// ================================================================
// Utility function to generate the passwords in a canonical way.
// ================================================================
function make_password_bytes(password) {
    Assert(typeof password != 'undefined', 'Password not specified!');
    Assert(password.length >= 8, 'Password length must be greater than 7 characters!');
    
    var bytes = password.getBytes();
    
    // Round to the nearest power of 2 larger than the password size and
    // append bytes from the password. This allows us to regenerate it at
    // will from the original.
    var nearest_power_of_2 = Math.pow( 2, Math.ceil( Math.log( bytes.length ) / Math.log( 2 ) ) );
    if (bytes.length != nearest_power_of_2) {
        var remainder = nearest_power_of_2 - bytes.length;
        for(var i=0; i

When it is run using nodejs, the output looks something like this:

$ NODE_PATH=/to/my/nodejs node example.js
INFO:example:170: testing encryption and decryption
INFO:example:175: encrypted data: 248 {"iv":"b4ad952831578149e43a206bda938740","encrypted":"ec3ecaf6533fe3ac9f25ddc6f7c05ca0b0a789425f8a70607a11dcfb27802c2631e4ad38df0354c5efd059b29297b3e6082856284889e569c3934f43c42effed409d96dcb9d1a202dc8c4f5ac7807dd45490dcbe23a7596139a017af7970125f"}
INFO:example:178: decrypted data: {
    "id": 123,
    "text": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, ..."
}
INFO:example:180: checking the results
INFO:example:183: PASSED
INFO:example:185: done

Enjoy!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.