BIP39 in browser

This commit is contained in:
Devrandom 2014-04-23 13:29:51 -04:00
parent f2472e691b
commit 79d50e92d4
7 changed files with 100 additions and 50 deletions

View File

@ -43,7 +43,7 @@ Object.defineProperty(module.exports, 'BIP32', {get: function() {
return require('./lib/HierarchicalKey');
}});
requireWhenAccessed('BIP39', './lib/BIP39');
requireWhenAccessed('BIP39WordlistEn', './BIP39WordlistEn');
requireWhenAccessed('BIP39WordlistEn', './lib/BIP39WordlistEn');
requireWhenAccessed('Point', './lib/Point');
requireWhenAccessed('Opcode', './lib/Opcode');
requireWhenAccessed('Script', './lib/Script');

View File

@ -27,6 +27,9 @@ var modules = [
'lib/Armory',
'lib/Base58',
'lib/HierarchicalKey',
'lib/BIP39',
'lib/BIP39WordlistEn',
'lib/cryptox',
'lib/Block',
'lib/Bloom',
'lib/Connection',

41
lib/browser/cryptox.js Normal file
View File

@ -0,0 +1,41 @@
// Crypto extensions
//
// PBKDF2 with SHA512 - browser version
var jssha = require('jssha')
var pbkdf2_sha512 = function (password, salt, keylen, options) {
password = new Buffer(password);
salt = new Buffer(salt);
// Defaults
var iterations = options && options.iterations || 1;
// Pseudo-random function
function PRF(password, salt) {
var j = new jssha(salt.toString('hex'), 'HEX');
var hash = j.getHMAC(password.toString('hex'), "HEX", "SHA-512", "HEX");
return new Buffer(hash, 'hex');
}
// Generate key
var derivedKeyBytes = new Buffer([]),
blockindex = 1;
while (derivedKeyBytes.length < keylen) {
var block = PRF(password, salt.concat([0, 0, 0, blockindex]));
for (var u = block, i = 1; i < iterations; i++) {
u = PRF(password, u);
for (var j = 0; j < block.length; j++) block[j] ^= u[j];
}
derivedKeyBytes = derivedKeyBytes.concat(block);
blockindex++;
}
// Truncate excess bytes - TODO
//derivedKeyBytes.length = keylen;
return new Buffer(derivedKeyBytes);
};
exports.pbkdf2Sync_sha512 = function(password, salt, iterations, keylen) {
return pbkdf2_sha512(password, salt, keylen, {iterations: iterations});
};

View File

@ -1,49 +1,5 @@
// Crypto extensions
//
// PBKDF2 with SHA512
var binding = require('bindings')('cryptox');
exports.pbkdf2_sha512 = function(password, salt, iterations, keylen, callback) {
if (typeof callback !== 'function')
throw new Error('No callback provided to pbkdf2');
return pbkdf2_sha512(password, salt, iterations, keylen, callback);
};
exports.pbkdf2Sync_sha512 = function(password, salt, iterations, keylen) {
return pbkdf2_sha512(password, salt, iterations, keylen);
};
function toBuf(str, encoding) {
encoding = encoding || 'binary';
if (typeof str === 'string') {
if (encoding === 'buffer')
encoding = 'binary';
str = new Buffer(str, encoding);
}
return str;
}
function pbkdf2_sha512(password, salt, iterations, keylen, callback) {
password = toBuf(password);
salt = toBuf(salt);
if (exports.DEFAULT_ENCODING === 'buffer')
return binding.PBKDF2(password, salt, iterations, keylen, callback);
// at this point, we need to handle encodings.
var encoding = exports.DEFAULT_ENCODING;
if (callback) {
binding.PBKDF2_sha512(password, salt, iterations, keylen, function(er, ret) {
if (ret)
ret = ret.toString(encoding);
callback(er, ret);
});
} else {
var ret = binding.PBKDF2_sha512(password, salt, iterations, keylen);
//return ret.toString(encoding);
return ret;
}
if (process.versions) {
module.exports = require('./node/cryptox');
return;
}
module.exports = require('./browser/cryptox');

49
lib/node/cryptox.js Normal file
View File

@ -0,0 +1,49 @@
// Crypto extensions
//
// PBKDF2 with SHA512
var binding = require('bindings')('cryptox');
exports.pbkdf2_sha512 = function(password, salt, iterations, keylen, callback) {
if (typeof callback !== 'function')
throw new Error('No callback provided to pbkdf2');
return pbkdf2_sha512(password, salt, iterations, keylen, callback);
};
exports.pbkdf2Sync_sha512 = function(password, salt, iterations, keylen) {
return pbkdf2_sha512(password, salt, iterations, keylen);
};
function toBuf(str, encoding) {
encoding = encoding || 'binary';
if (typeof str === 'string') {
if (encoding === 'buffer')
encoding = 'binary';
str = new Buffer(str, encoding);
}
return str;
}
function pbkdf2_sha512(password, salt, iterations, keylen, callback) {
password = toBuf(password);
salt = toBuf(salt);
if (exports.DEFAULT_ENCODING === 'buffer')
return binding.PBKDF2(password, salt, iterations, keylen, callback);
// at this point, we need to handle encodings.
var encoding = exports.DEFAULT_ENCODING;
if (callback) {
binding.PBKDF2_sha512(password, salt, iterations, keylen, function(er, ret) {
if (ret)
ret = ret.toString(encoding);
callback(er, ret);
});
} else {
var ret = binding.PBKDF2_sha512(password, salt, iterations, keylen);
//return ret.toString(encoding);
return ret;
}
}

View File

@ -20,6 +20,7 @@
<script src="test.basic.js"></script>
<script src="test.Bignum.browser.js"></script>
<script src="test.BIP32.js"></script>
<script src="test.BIP39.js"></script>
<script src="test.Block.js"></script>
<script src="test.Bloom.js"></script>
<script src="test.Connection.js"></script>

View File

@ -154,7 +154,7 @@ describe('BIP39', function() {
var mnemonic1 = BIP39.to_mnemonic(BIP39WordlistEn, new Buffer(code, 'hex'));
var seed1 = BIP39.mnemonic_to_seed(mnemonic, 'TREZOR');
mnemonic1.should.equal(mnemonic);
seed1.toString().should.equal(new Buffer(seed, 'hex').toString());
seed1.toString('hex').should.equal(seed)
}
});
});