fcoin/lib/crypto/backend-browser.js
2016-11-20 13:12:35 -08:00

117 lines
2.5 KiB
JavaScript

/*!
* backend-browser.js - browser crypto backend for bcoin
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
/* jshint worker: true */
'use strict';
var assert = require('assert');
var hashjs = require('hash.js');
var aes = require('./aes');
var backend = exports;
var global, crypto, subtle;
global = (function() {
if (typeof window !== 'undefined')
return window;
if (typeof self !== 'undefined')
return self;
throw new Error('No global found.');
})();
crypto = global.crypto || global.msCrypto;
subtle = crypto ? crypto.subtle : null;
backend.hash = function hash(alg, data) {
return new Buffer(hashjs[alg]().update(data).digest());
};
backend.hmac = function hmac(alg, data, salt) {
var hash = hashjs[alg];
var hmac;
assert(hash != null, 'Unknown algorithm.');
hmac = hashjs.hmac(hash, salt);
return new Buffer(hmac.update(data).digest());
};
backend.pbkdf2 = null;
backend.pbkdf2Async = function pbkdf2Async(key, salt, iter, len, alg) {
var algo = { name: 'PBKDF2' };
var use = ['deriveBits'];
var length = len * 8;
var options, promise;
options = {
name: 'PBKDF2',
salt: salt,
iterations: iter,
hash: getHash(alg)
};
promise = subtle.importKey('raw', key, algo, false, use);
return promise.then(function(key) {
return subtle.deriveBits(options, key, length);
}).then(function(result) {
return new Buffer(result);
});
};
if (!subtle || !subtle.importKey || !subtle.deriveBits)
backend.pbkdf2Async = null;
backend.encipher = function encipher(data, key, iv) {
return aes.cbc.encrypt(data, key, iv);
};
backend.decipher = function decipher(data, key, iv) {
try {
return aes.cbc.decrypt(data, key, iv);
} catch (e) {
throw new Error('Bad key for decryption.');
}
};
backend.randomBytes = function randomBytes(n) {
var data = new Uint8Array(n);
crypto.getRandomValues(data);
return new Buffer(data.buffer);
};
if (!crypto || !crypto.getRandomValues) {
// Out of luck here. Use bad randomness for now.
backend.randomBytes = function randomBytes(n) {
var data = new Buffer(n);
var i;
for (i = 0; i < data.length; i++)
data[i] = Math.floor(Math.random() * 256);
return data;
};
}
function getHash(name) {
switch (name) {
case 'sha1':
return 'SHA-1';
case 'sha256':
return 'SHA-256';
case 'sha384':
return 'SHA-384';
case 'sha512':
return 'SHA-512';
default:
throw new Error('Unknown hash.');
}
}