RackHD/on-core

View on GitHub
lib/common/encryption.js

Summary

Maintainability
A
3 hrs
Test Coverage
// Copyright 2015, EMC, Inc.

'use strict';

module.exports = encryptionFactory;

encryptionFactory.$provide = 'Encryption';
encryptionFactory.$inject = [
    'crypto',
    'Constants',
    'crypt'
];

function encryptionFactory(
    crypto,
    Constants,
    crypt
) {
    function Encryption () {
    }

    Encryption.prototype.key = function () {
        return crypto.randomBytes(32).toString('base64');
    };

    Encryption.prototype.iv = function () {
        return crypto.randomBytes(16).toString('base64');
    };

    Encryption.prototype.encrypt = function (data, key, iv) {
        iv = iv || this.iv();

        var cipher = crypto.createCipheriv(
            'aes-256-cbc',
            new Buffer(key, 'base64'),
            new Buffer(iv, 'base64')
        );

        var encrypted = Buffer.concat([
            cipher.update(data),
            cipher.final()
        ]);

        return '%s.%s'.format(
            iv.toString('base64'),
            encrypted.toString('base64')
        );
    };

    Encryption.prototype.decrypt = function (data, key) {
        var parts = data.split('.');

        var cipher = crypto.createDecipheriv(
            'aes-256-cbc',
            new Buffer(key, 'base64'),
            new Buffer(parts[0], 'base64')
        );

        var decrypted = Buffer.concat([
            cipher.update(new Buffer(parts[1], 'base64')),
            cipher.final()
        ]);

        return decrypted.toString();
    };

    Encryption.prototype.isEncrypted = function (data) {
        return Constants.Regex.Encrypted.test(data);
    };

    /**
     * Calculate the hash for input data
     * @param {String} data - The input data
     * @param {String} [algorithm='sha512'] - The hash algorithm, it should be one of
     * ['sha512', 'sha256','md5'], the default is 'sha512'
     * @param {String} [salt] - The salt feed to hash algorithm, if not specified, the function will
     * generate a random salt.
     * @return {String} the hashed data
     */
    Encryption.prototype.createHash = function (data, algorithm, salt) {
        return crypt(data, this.createSalt(algorithm, salt));
    };

    /**
     * Create a salt to be used with crypt().
     * @param {String} [algorithm='sha512'] - The hash algorithm, it should be one of
     * ['sha512', 'sha256','md5'], the default is 'sha512'
     * @param {String} [salt] - The salt feed to hash algorithm, if not specified, the function will
     * generate a random salt.
     * @return {String} the salt
     */
    Encryption.prototype.createSalt = function (algorithm, salt) {
        algorithm = algorithm || 'sha512';
        var signatures = {
            sha256: '$5$',
            sha512: '$6$'
        };
        if(!signatures[algorithm]) {
            throw new TypeError('Unknown salt algorithm: ' + algorithm);
        }

        if (salt && salt.charAt(0) === '$') {
            salt = signatures[algorithm] + salt.split('$')[2];
        } else if (salt) {
            salt = signatures[algorithm] + salt;
        } else{
            salt = crypt.createSalt(algorithm);
        }
        
        return salt;
    };

    return Encryption;
}