2014-10-21 20:14:48 -07:00
|
|
|
/**
|
2014-10-24 05:36:28 -07:00
|
|
|
* Small module for some helpers that wrap sjcl with some good practices.
|
2014-10-21 20:14:48 -07:00
|
|
|
*/
|
2014-10-28 11:57:49 -07:00
|
|
|
var sjcl = require('sjcl');
|
2014-10-25 15:57:12 -07:00
|
|
|
var _ = require('lodash');
|
2014-12-02 06:17:03 -08:00
|
|
|
|
|
|
|
var log = require('../util/log.js');
|
2014-11-07 12:35:32 -08:00
|
|
|
var config = require('../../config');
|
2014-10-21 20:14:48 -07:00
|
|
|
|
2014-11-07 12:35:32 -08:00
|
|
|
var defaultSalt = (config && config.passphraseConfig && config.passphraseConfig.storageSalt) || 'mjuBtGybi/4=';
|
|
|
|
var defaultIterations = (config && config.passphraseConfig && config.passphraseConfig.iterations) || 1000;
|
2014-10-27 13:23:01 -07:00
|
|
|
|
2014-10-21 20:14:48 -07:00
|
|
|
module.exports = {
|
|
|
|
|
2014-10-27 18:15:23 -07:00
|
|
|
/**
|
|
|
|
* @param {string} password
|
|
|
|
* @param {string} salt - base64 encoded, defaults to 'mjuBtGybi/4='
|
|
|
|
* @param {number} iterations - defaults to 100
|
|
|
|
* @param {number} length - bits, defaults to 512 bits
|
|
|
|
* @returns {string} base64 encoded pbkdf2 derivation using sha1 for hmac
|
|
|
|
*/
|
|
|
|
kdf: function(password, salt, iterations, length) {
|
|
|
|
return sjcl.codec.base64.fromBits(
|
|
|
|
this.kdfbinary(password, salt, iterations, length)
|
|
|
|
);
|
|
|
|
},
|
|
|
|
|
2014-11-04 06:47:38 -08:00
|
|
|
/**
|
|
|
|
* @param {string} key
|
|
|
|
* @param {string} data
|
|
|
|
* @return {string} base64 encoded hmac
|
|
|
|
*/
|
|
|
|
hmac: function(key, data) {
|
|
|
|
return sjcl.codec.base64.fromBits(
|
|
|
|
new sjcl.misc.hmac(key, sjcl.hash.sha256).encrypt(data)
|
|
|
|
);
|
|
|
|
},
|
|
|
|
|
2014-10-27 18:15:23 -07:00
|
|
|
/**
|
|
|
|
* @param {string} password
|
|
|
|
* @param {string} salt - base64 encoded, defaults to 'mjuBtGybi/4='
|
|
|
|
* @param {number} iterations - defaults to 100
|
|
|
|
* @param {number} length - bits, defaults to 512 bits
|
|
|
|
* @returns {string} base64 encoded pbkdf2 derivation using sha1 for hmac
|
|
|
|
*/
|
|
|
|
kdfbinary: function(password, salt, iterations, length) {
|
2014-10-27 13:23:01 -07:00
|
|
|
iterations = iterations || defaultIterations;
|
2014-10-27 18:15:23 -07:00
|
|
|
length = length || 512;
|
|
|
|
salt = sjcl.codec.base64.toBits(salt || defaultSalt);
|
2014-10-27 15:26:21 -07:00
|
|
|
|
|
|
|
var hash = sjcl.hash.sha256.hash(sjcl.hash.sha256.hash(password));
|
|
|
|
var prff = function(key) {
|
|
|
|
return new sjcl.misc.hmac(hash, sjcl.hash.sha1);
|
|
|
|
};
|
|
|
|
|
2014-10-27 18:15:23 -07:00
|
|
|
return sjcl.misc.pbkdf2(hash, salt, iterations, length, prff);
|
2014-10-21 20:14:48 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Encrypts symmetrically using a passphrase
|
|
|
|
*/
|
2014-12-02 17:38:33 -08:00
|
|
|
encrypt: function(key, message, salt, iter) {
|
2014-10-24 08:24:44 -07:00
|
|
|
if (!_.isString(message)) {
|
|
|
|
message = JSON.stringify(message);
|
|
|
|
}
|
2014-12-02 17:38:33 -08:00
|
|
|
sjcl.json.defaults.salt = salt || defaultSalt;
|
|
|
|
sjcl.json.defaults.iter = iter || defaultIterations;
|
2014-10-21 20:14:48 -07:00
|
|
|
return sjcl.encrypt(key, message);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Decrypts symmetrically using a passphrase
|
|
|
|
*/
|
2014-12-02 17:38:33 -08:00
|
|
|
decrypt: function(key, sjclEncryptedJson) {
|
2014-10-21 20:14:48 -07:00
|
|
|
var output = {};
|
|
|
|
try {
|
2014-12-02 17:38:33 -08:00
|
|
|
return sjcl.decrypt(key, sjclEncryptedJson);
|
2014-10-21 20:14:48 -07:00
|
|
|
} catch (e) {
|
2014-12-06 14:16:50 -08:00
|
|
|
log.debug('Decryption failed due to error: ' + e.message);
|
2014-10-21 20:14:48 -07:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|