modules: remove all conditional requires. see #105.

This commit is contained in:
Christopher Jeffrey 2016-11-18 23:04:37 -08:00
parent 9f522c5ca4
commit 67a00bfe50
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
55 changed files with 1615 additions and 1306 deletions

View File

@ -1,3 +1,2 @@
// Empty module for browserify. // Empty module for browserify.
module.exports = null; exports.empty = true;
throw new Error('Module not available.');

View File

@ -10,6 +10,5 @@ exports.PaymentRequest = require('./paymentrequest');
exports.PaymentDetails = require('./paymentdetails'); exports.PaymentDetails = require('./paymentdetails');
exports.Payment = require('./payment'); exports.Payment = require('./payment');
exports.PaymentACK = require('./paymentack'); exports.PaymentACK = require('./paymentack');
exports.asn1 = require('./asn1');
exports.x509 = require('./x509'); exports.x509 = require('./x509');
exports.pk = require('./pk'); exports.pk = require('./pk');

View File

@ -10,7 +10,7 @@ var assert = require('assert');
var Output = require('../primitives/output'); var Output = require('../primitives/output');
var TX = require('../primitives/tx'); var TX = require('../primitives/tx');
var Script = require('../script/script'); var Script = require('../script/script');
var protobuf = require('./protobuf'); var protobuf = require('../utils/protobuf');
var PaymentDetails = require('./paymentdetails'); var PaymentDetails = require('./paymentdetails');
var ProtoReader = protobuf.ProtoReader; var ProtoReader = protobuf.ProtoReader;
var ProtoWriter = protobuf.ProtoWriter; var ProtoWriter = protobuf.ProtoWriter;

View File

@ -7,7 +7,7 @@
'use strict'; 'use strict';
var assert = require('assert'); var assert = require('assert');
var protobuf = require('./protobuf'); var protobuf = require('../utils/protobuf');
var Payment = require('./payment'); var Payment = require('./payment');
var ProtoReader = protobuf.ProtoReader; var ProtoReader = protobuf.ProtoReader;
var ProtoWriter = protobuf.ProtoWriter; var ProtoWriter = protobuf.ProtoWriter;

View File

@ -9,7 +9,7 @@
var assert = require('assert'); var assert = require('assert');
var utils = require('../utils/utils'); var utils = require('../utils/utils');
var Output = require('../primitives/output'); var Output = require('../primitives/output');
var protobuf = require('./protobuf'); var protobuf = require('../utils/protobuf');
var ProtoReader = protobuf.ProtoReader; var ProtoReader = protobuf.ProtoReader;
var ProtoWriter = protobuf.ProtoWriter; var ProtoWriter = protobuf.ProtoWriter;

View File

@ -10,8 +10,8 @@ var assert = require('assert');
var utils = require('../utils/utils'); var utils = require('../utils/utils');
var crypto = require('../crypto/crypto'); var crypto = require('../crypto/crypto');
var x509 = require('./x509'); var x509 = require('./x509');
var asn1 = require('./asn1'); var PEM = require('../utils/pem');
var protobuf = require('./protobuf'); var protobuf = require('../utils/protobuf');
var PaymentDetails = require('./paymentdetails'); var PaymentDetails = require('./paymentdetails');
var ProtoReader = protobuf.ProtoReader; var ProtoReader = protobuf.ProtoReader;
var ProtoWriter = protobuf.ProtoWriter; var ProtoWriter = protobuf.ProtoWriter;
@ -154,7 +154,7 @@ PaymentRequest.prototype.setChain = function setChain(chain) {
for (i = 0; i < chain.length; i++) { for (i = 0; i < chain.length; i++) {
cert = chain[i]; cert = chain[i];
if (typeof cert === 'string') { if (typeof cert === 'string') {
pem = asn1.fromPEM(cert); pem = PEM.decode(cert);
assert(pem.type === 'certificate', 'Bad certificate PEM.'); assert(pem.type === 'certificate', 'Bad certificate PEM.');
cert = pem.data; cert = pem.data;
} }

View File

@ -6,248 +6,38 @@
'use strict'; 'use strict';
var BN = require('bn.js'); var pk = require('../crypto/pk');
var asn1 = require('./asn1');
var elliptic = require('elliptic');
var crypto = require('../crypto/crypto');
var nativeCrypto; exports._verify = function verify(hash, msg, sig, key) {
try {
nativeCrypto = require('crypto');
} catch (e) {
;
}
var pk = exports;
var rsa = {};
var ecdsa = {};
var native = {};
rsa.prefixes = {
md5: new Buffer('3020300c06082a864886f70d020505000410', 'hex'),
sha1: new Buffer('3021300906052b0e03021a05000414', 'hex'),
sha224: new Buffer('302d300d06096086480165030402040500041c', 'hex'),
sha256: new Buffer('3031300d060960864801650304020105000420', 'hex'),
sha384: new Buffer('3041300d060960864801650304020205000430', 'hex'),
sha512: new Buffer('3051300d060960864801650304020305000440', 'hex'),
md5sha1: new Buffer(0),
ripemd160: new Buffer('30203008060628cf060300310414', 'hex')
};
// Ported from:
// https://github.com/golang/go/blob/master/src/crypto/rsa/pkcs1v15.go
rsa.verify = function verify(hashAlg, msg, sig, key) {
var hash = crypto.hash(hashAlg, msg);
var prefix = rsa.prefixes[hashAlg];
var len = prefix.length + hash.length;
var pub = asn1.parseRSAPublic(key);
var N = new BN(pub.modulus);
var e = new BN(pub.publicExponent);
var k = Math.ceil(N.bitLength() / 8);
var m, em, ok, i;
if (k < len + 11)
throw new Error('Message too long.');
m = rsa.encrypt(N, e, sig);
em = leftpad(m, k);
ok = crypto.ceq(em[0], 0x00);
ok &= crypto.ceq(em[1], 0x01);
ok &= crypto.ccmp(em.slice(k - hash.length, k), hash);
ok &= crypto.ccmp(em.slice(k - len, k - hash.length), prefix);
ok &= crypto.ceq(em[k - len - 1], 0x00);
for (i = 2; i < k - len - 1; i++)
ok &= crypto.ceq(em[i], 0xff);
return ok === 1;
};
rsa.sign = function sign(hashAlg, msg, key) {
var hash = crypto.hash(hashAlg, msg);
var prefix = rsa.prefixes[hashAlg];
var len = prefix.length + hash.length;
var priv = asn1.parseRSAPrivate(key);
var N = new BN(priv.modulus);
var D = new BN(priv.privateExponent);
var k = Math.ceil(N.bitLength() / 8);
var i, em;
if (k < len + 11)
throw new Error('Message too long.');
em = new Buffer(k);
em.fill(0);
em[1] = 0x01;
for (i = 2; i < k - len - 1; i++)
em[i] = 0xff;
prefix.copy(em, k - len);
hash.copy(em, k - hash.length);
return rsa.decrypt(N, D, em);
};
rsa.decrypt = function decrypt(N, D, m) {
var c = new BN(m);
if (c.cmp(N) > 0)
throw new Error('Cannot decrypt.');
return c
.toRed(BN.red(N))
.redPow(D)
.fromRed()
.toArrayLike(Buffer, 'be');
};
rsa.encrypt = function encrypt(N, e, m) {
return new BN(m)
.toRed(BN.red(N))
.redPow(e)
.fromRed()
.toArrayLike(Buffer, 'be');
};
ecdsa.verify = function verify(curve, msg, hashAlg, key, sig) {
var hash = crypto.hash(hashAlg, msg);
var ec = elliptic.ec(curve);
return ec.verify(hash, sig, key);
};
ecdsa.sign = function sign(curve, msg, hashAlg, key) {
var hash = crypto.hash(hashAlg, msg);
var ec = elliptic.ec(curve);
return new Buffer(ec.sign(hash, key));
};
native.verify = function verify(alg, hash, msg, sig, key) {
var algo, verify;
if (!nativeCrypto)
return false;
algo = normalizeAlg(alg, hash);
verify = nativeCrypto.createVerify(algo);
verify.update(msg);
return verify.verify(key, sig);
};
native.sign = function _sign(alg, hash, msg, key) {
var algo, sig;
if (!nativeCrypto)
return false;
algo = normalizeAlg(alg, hash);
sig = nativeCrypto.createSign(algo);
sig.update(msg);
return sig.sign(key);
};
pk.pemTag = {
dsa: 'DSA',
rsa: 'RSA',
ecdsa: 'EC'
};
pk.toPEM = function toPEM(key, type) {
var tag = pk.pemTag[key.alg];
var pem = asn1.toPEM(key.data, tag, type);
// Key parameters, usually present
// if selecting an EC curve.
if (key.params)
pem += asn1.toPEM(key.params, tag, 'parameters');
return pem;
};
pk._verify = function verify(hash, msg, sig, key) {
var pem;
switch (key.alg) { switch (key.alg) {
case 'dsa': case 'dsa':
pem = pk.toPEM(key, 'public key'); return pk.dsa.verify(hash, msg, sig, key.data, key.params);
return native.verify(key.alg, hash, msg, sig, pem);
case 'rsa': case 'rsa':
if (nativeCrypto) { return pk.rsa.verify(hash, msg, sig, key.data);
pem = pk.toPEM(key, 'public key');
return native.verify(key.alg, hash, msg, sig, pem);
}
return rsa.verify(hash, msg, sig, key.data);
case 'ecdsa': case 'ecdsa':
if (!key.curve) return pk.ecdsa.verify(key.curve, hash, msg, sig, key.data);
throw new Error('No curve present.');
return ecdsa.verify(key.curve, hash, msg, sig, key.data);
default: default:
throw new Error('Unsupported algorithm.'); throw new Error('Unsupported algorithm.');
} }
}; };
pk.verify = function verify(hash, msg, sig, key) { exports.verify = function verify(hash, msg, sig, key) {
try { try {
return pk._verify(hash, msg, sig, key); return exports._verify(hash, msg, sig, key);
} catch (e) { } catch (e) {
return false; return false;
} }
}; };
pk.sign = function sign(hash, msg, key) { exports.sign = function sign(hash, msg, key) {
var pem;
switch (key.alg) { switch (key.alg) {
case 'dsa': case 'dsa':
pem = pk.toPEM(key, 'private key'); return pk.dsa.sign(hash, msg, key.data, key.params);
return native.sign(key.alg, hash, msg, pem);
case 'rsa': case 'rsa':
if (nativeCrypto) { return pk.rsa.sign(hash, msg, key.data);
pem = pk.toPEM(key, 'private key');
return native.sign(key.alg, hash, msg, pem);
}
return rsa.sign(hash, msg, key.data);
case 'ecdsa': case 'ecdsa':
if (!key.curve) return pk.ecdsa.sign(key.curve, hash, msg, key.data);
throw new Error('No curve present.');
return ecdsa.sign(key.curve, hash, msg, key.data);
default: default:
throw new Error('Unsupported algorithm.'); throw new Error('Unsupported algorithm.');
} }
}; };
function leftpad(input, size) {
var n = input.length;
var out;
if (n > size)
n = size;
out = new Buffer(size);
out.fill(0);
input.copy(out, out.length - n);
return out;
}
function normalizeAlg(alg, hash) {
var name = alg.toUpperCase() + '-' + hash.toUpperCase();
switch (name) {
case 'ECDSA-SHA1':
name = 'ecdsa-with-SHA1';
break;
case 'ECDSA-SHA256':
name = 'ecdsa-with-SHA256';
break;
}
return name;
}
pk.rsa = rsa;
pk.ecdsa = ecdsa;
pk.native = native;

View File

@ -7,7 +7,8 @@
'use strict'; 'use strict';
var assert = require('assert'); var assert = require('assert');
var asn1 = require('./asn1'); var ASN1 = require('../utils/asn1');
var PEM = require('../utils/pem');
var utils = require('../utils/utils'); var utils = require('../utils/utils');
var crypto = require('../crypto/crypto'); var crypto = require('../crypto/crypto');
var pk = require('./pk'); var pk = require('./pk');
@ -69,7 +70,7 @@ x509.setTrust = function setTrust(certs) {
} }
if (typeof cert === 'string') { if (typeof cert === 'string') {
pem = asn1.fromPEM(cert); pem = PEM.decode(cert);
assert(pem.type === 'certificate', 'Must add certificates to trust.'); assert(pem.type === 'certificate', 'Must add certificates to trust.');
cert = pem.data; cert = pem.data;
} }
@ -137,7 +138,7 @@ x509.getCurve = function getCurve(params) {
return; return;
try { try {
oid = asn1.parseOID(params); oid = ASN1.parseOID(params);
} catch (e) { } catch (e) {
return; return;
} }
@ -147,7 +148,7 @@ x509.getCurve = function getCurve(params) {
x509.parse = function parse(der) { x509.parse = function parse(der) {
try { try {
return asn1.parseCert(der); return ASN1.parseCert(der);
} catch (e) { } catch (e) {
; ;
} }
@ -189,7 +190,7 @@ x509.signSubject = function signSubject(hash, msg, key, chain) {
assert(cert, 'Could not parse certificate.'); assert(cert, 'Could not parse certificate.');
if (typeof key === 'string') { if (typeof key === 'string') {
key = asn1.fromPEM(key); key = PEM.decode(key);
if (key.alg === 'ecdsa') if (key.alg === 'ecdsa')
curve = x509.getCurve(key.params); curve = x509.getCurve(key.params);
key = { key = {
@ -291,8 +292,6 @@ x509.verifyChain = function verifyChain(chain) {
return false; return false;
}; };
x509.asn1 = asn1;
function isHash(data) { function isHash(data) {
if (typeof data === 'string') if (typeof data === 'string')
return utils.isHex(data) && data.length === 64; return utils.isHex(data) && data.length === 64;

View File

@ -0,0 +1,73 @@
/*!
* 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 crypto, global;
if (typeof window !== 'undefined')
global = window;
else if (typeof self !== 'undefined')
global = self;
if (global)
crypto = global.crypto || global.msCrypto;
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 = 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;
};
}

50
lib/crypto/backend.js Normal file
View File

@ -0,0 +1,50 @@
/*!
* backend.js - crypto backend for bcoin
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var utils = require('../utils/utils');
var crypto = require('crypto');
var backend = exports;
backend.hash = function hash(alg, data) {
return crypto.createHash(alg).update(data).digest();
};
backend.hmac = function hmac(alg, data, salt) {
var hmac = crypto.createHmac(alg, salt);
return hmac.update(data).digest();
};
backend.pbkdf2 = function pbkdf2(key, salt, iter, len, alg) {
return crypto.pbkdf2Sync(key, salt, iter, len, alg);
};
if (!crypto.pbkdf2Sync)
backend.pbkdf2 = null;
backend.pbkdf2Async = function pbkdf2Async(key, salt, iter, len, alg, callback) {
return crypto.pbkdf2(key, salt, iter, len, alg, callback);
};
if (!crypto.pbkdf2)
backend.pbkdf2Async = null;
backend.encipher = function encipher(data, key, iv) {
var cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
return utils.concat(cipher.update(data), cipher.final());
};
backend.decipher = function decipher(data, key, iv) {
var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
try {
return utils.concat(decipher.update(data), decipher.final());
} catch (e) {
throw new Error('Bad key for decryption.');
}
};
backend.randomBytes = crypto.randomBytes;

View File

@ -7,7 +7,7 @@
'use strict'; 'use strict';
var assert = require('assert'); var assert = require('assert');
var native = require('../utils/native'); var native = require('../utils/native').binding;
var BIG_ENDIAN = new Int8Array(new Int16Array([1]).buffer)[0] === 0; var BIG_ENDIAN = new Int8Array(new Int16Array([1]).buffer)[0] === 0;

View File

@ -8,25 +8,13 @@
'use strict'; 'use strict';
var assert = require('assert'); var assert = require('assert');
var random = require('./random');
var scrypt = require('./scrypt'); var scrypt = require('./scrypt');
var scryptAsync = require('./scrypt-async'); var scryptAsync = require('./scrypt-async');
var utils = require('../utils/utils'); var utils = require('../utils/utils');
var co = require('../utils/co'); var co = require('../utils/co');
var native = require('../utils/native'); var native = require('../utils/native').binding;
var backend = require('./backend');
var lazy = require('../utils/lazy')(require, exports); var lazy = require('../utils/lazy')(require, exports);
var nodeCrypto, hash, aes;
var isBrowser =
(typeof process !== 'undefined' && process.browser)
|| typeof window !== 'undefined';
if (!isBrowser) {
nodeCrypto = require('crypto');
} else {
hash = require('hash.js');
aes = require('./aes');
}
/** /**
* @exports crypto * @exports crypto
@ -42,10 +30,7 @@ var crypto = exports;
*/ */
crypto.hash = function _hash(alg, data) { crypto.hash = function _hash(alg, data) {
if (!nodeCrypto) return backend.hash(alg, data);
return new Buffer(hash[alg]().update(data).digest());
return nodeCrypto.createHash(alg).update(data).digest();
}; };
if (native) if (native)
@ -129,15 +114,7 @@ crypto.checksum = function checksum(data) {
*/ */
crypto.hmac = function hmac(alg, data, salt) { crypto.hmac = function hmac(alg, data, salt) {
var hmac; return backend.hmac(alg, data, salt);
if (!nodeCrypto) {
hmac = hash.hmac(hash[alg], salt);
return new Buffer(hmac.update(data).digest());
}
hmac = nodeCrypto.createHmac(alg, salt);
return hmac.update(data).digest();
}; };
if (native) if (native)
@ -160,8 +137,8 @@ crypto.pbkdf2 = function pbkdf2(key, salt, iter, len, alg) {
if (typeof salt === 'string') if (typeof salt === 'string')
salt = new Buffer(salt, 'utf8'); salt = new Buffer(salt, 'utf8');
if (nodeCrypto && nodeCrypto.pbkdf2Sync) if (backend.pbkdf2)
return nodeCrypto.pbkdf2Sync(key, salt, iter, len, alg); return backend.pbkdf2(key, salt, iter, len, alg);
return crypto._pbkdf2(key, salt, iter, len, alg); return crypto._pbkdf2(key, salt, iter, len, alg);
}; };
@ -185,9 +162,9 @@ crypto.pbkdf2Async = function pbkdf2Async(key, salt, iter, len, alg) {
if (typeof salt === 'string') if (typeof salt === 'string')
salt = new Buffer(salt, 'utf8'); salt = new Buffer(salt, 'utf8');
if (nodeCrypto && nodeCrypto.pbkdf2) { if (backend.pbkdf2Async) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
nodeCrypto.pbkdf2(key, salt, iter, len, alg, co.wrap(resolve, reject)); backend.pbkdf2Async(key, salt, iter, len, alg, co.wrap(resolve, reject));
}); });
} }
@ -292,20 +269,13 @@ crypto.encrypt = co(function* encrypt(data, passphrase, iv) {
*/ */
crypto.encipher = function encipher(data, key, iv) { crypto.encipher = function encipher(data, key, iv) {
var cipher;
assert(Buffer.isBuffer(data)); assert(Buffer.isBuffer(data));
assert(Buffer.isBuffer(key)); assert(Buffer.isBuffer(key));
assert(Buffer.isBuffer(iv)); assert(Buffer.isBuffer(iv));
assert(key.length === 32); assert(key.length === 32);
assert(iv.length === 16); assert(iv.length === 16);
if (!nodeCrypto) return backend.encipher(data, key, iv);
return aes.cbc.encrypt(data, key, iv);
cipher = nodeCrypto.createCipheriv('aes-256-cbc', key, iv);
return utils.concat(cipher.update(data), cipher.final());
}; };
/** /**
@ -351,31 +321,7 @@ crypto.decipher = function decipher(data, key, iv) {
assert(Buffer.isBuffer(iv)); assert(Buffer.isBuffer(iv));
assert(key.length === 32); assert(key.length === 32);
assert(iv.length === 16); assert(iv.length === 16);
try { return backend.decipher(data, key, iv);
return crypto._decipher(data, key, iv);
} catch (e) {
throw new Error('Bad key for decryption.');
}
};
/**
* Decrypt with aes-256-cbc.
* @private
* @param {Buffer} data
* @param {Buffer} key
* @param {Buffer} iv
* @returns {Buffer}
*/
crypto._decipher = function decipher(data, key, iv) {
var decipher;
if (!nodeCrypto)
return aes.cbc.decrypt(data, key, iv);
decipher = nodeCrypto.createDecipheriv('aes-256-cbc', key, iv);
return utils.concat(decipher.update(data), decipher.final());
}; };
/** /**
@ -661,7 +607,19 @@ if (native)
* @returns {Buffer} * @returns {Buffer}
*/ */
crypto.randomBytes = random.randomBytes; crypto.randomBytes = backend.randomBytes;
/**
* Generate a random uint32.
* Probably more cryptographically sound than
* `Math.random()`.
* @function
* @returns {Number}
*/
crypto.randomInt = function randomInt() {
return crypto.randomBytes(4).readUInt32LE(0, true);
};
/** /**
* Generate a random number within a range. * Generate a random number within a range.
@ -673,17 +631,10 @@ crypto.randomBytes = random.randomBytes;
* @returns {Number} * @returns {Number}
*/ */
crypto.randomRange = random.randomRange; crypto.randomRange = function randomRange(min, max) {
var num = crypto.randomInt();
/** return Math.floor((num / 0x100000000) * (max - min) + min);
* Generate a random uint32. };
* Probably more cryptographically sound than
* `Math.random()`.
* @function
* @returns {Number}
*/
crypto.randomInt = random.randomInt;
/* /*
* Expose other objects. * Expose other objects.
@ -694,3 +645,4 @@ lazy('chachapoly', './chachapoly');
lazy('ec', './ec'); lazy('ec', './ec');
lazy('schnorr', './schnorr'); lazy('schnorr', './schnorr');
lazy('siphash', './siphash'); lazy('siphash', './siphash');
lazy('pk', './pk');

347
lib/crypto/ec-elliptic.js Normal file
View File

@ -0,0 +1,347 @@
/*!
* ec.js - ecdsa wrapper for elliptic
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var assert = require('assert');
var elliptic = require('elliptic');
var secp256k1 = elliptic.ec('secp256k1');
var Signature = require('elliptic/lib/elliptic/ec/signature');
var curve = elliptic.curve;
var BN = require('bn.js');
/**
* @exports ec
*/
var ec = exports;
/**
* Generate a private key.
* @returns {Buffer} Private key.
*/
ec.generatePrivateKey = function generatePrivateKey() {
var key = secp256k1.genKeyPair();
var priv = key.getPrivate().toArrayLike(Buffer, 'be', 32);
return priv;
};
/**
* Create a public key from a private key.
* @param {Buffer} priv
* @param {Boolean?} compressed
* @returns {Buffer}
*/
ec.publicKeyCreate = function publicKeyCreate(priv, compressed) {
var key;
assert(Buffer.isBuffer(priv));
key = secp256k1.keyPair({ priv: priv });
key = key.getPublic(compressed !== false, 'array');
return new Buffer(key);
};
/**
* Compress or decompress public key.
* @param {Buffer} pub
* @returns {Buffer}
*/
ec.publicKeyConvert = function publicKeyConvert(key, compressed) {
var point = curve.decodePoint(key);
return new Buffer(point.encode('array', compressed !== false));
};
/**
* ((tweak + key) % n)
* @param {Buffer} privateKey
* @param {Buffer} tweak
* @returns {Buffer} privateKey
*/
ec.privateKeyTweakAdd = function privateKeyTweakAdd(privateKey, tweak) {
var key = new BN(tweak)
.add(new BN(privateKey))
.mod(curve.n)
.toArrayLike(Buffer, 'be', 32);
// Only a 1 in 2^127 chance of happening.
if (!ec.privateKeyVerify(key))
throw new Error('Private key is invalid.');
return key;
};
/**
* ((g * tweak) + key)
* @param {Buffer} publicKey
* @param {Buffer} tweak
* @returns {Buffer} publicKey
*/
ec.publicKeyTweakAdd = function publicKeyTweakAdd(publicKey, tweak, compressed) {
var key = curve.decodePoint(publicKey);
var point = curve.g.mul(new BN(tweak)).add(key);
var pub = new Buffer(point.encode('array', compressed !== false));
if (!ec.publicKeyVerify(pub))
throw new Error('Public key is invalid.');
return pub;
};
/**
* Create an ecdh.
* @param {Buffer} pub
* @param {Buffer} priv
* @returns {Buffer}
*/
ec.ecdh = function ecdh(pub, priv) {
priv = secp256k1.keyPair({ priv: priv });
pub = secp256k1.keyPair({ pub: pub });
return priv.derive(pub.getPublic()).toArrayLike(Buffer, 'be', 32);
};
/**
* Recover a public key.
* @param {Buffer} msg
* @param {Buffer} sig
* @param {Number?} j
* @param {Boolean?} compressed
* @returns {Buffer[]|Buffer|null}
*/
ec.recover = function recover(msg, sig, j, compressed) {
var point, key;
if (!j)
j = 0;
try {
point = secp256k1.recoverPubKey(msg, sig, j);
} catch (e) {
return;
}
key = point.encode('array', compressed !== false);
return new Buffer(key);
};
/**
* Verify a signature.
* @param {Buffer} msg
* @param {Buffer} sig - DER formatted.
* @param {Buffer} key
* @param {Boolean?} - Whether this should be treated as a
* "historical" signature. This allows signatures to be of
* odd lengths.
* @param {Boolean?} high - Allow high S value.
* @returns {Boolean}
*/
ec.verify = function verify(msg, sig, key, historical, high) {
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert(Buffer.isBuffer(key));
if (sig.length === 0)
return false;
if (key.length === 0)
return false;
// Attempt to normalize the signature
// length before passing to elliptic.
// Note: We only do this for historical data!
// https://github.com/indutny/elliptic/issues/78
if (historical)
sig = normalizeLength(sig);
// Make elliptic mimic secp256k1's
// failure with high S values.
if (!high && !ec.isLowS(sig))
return false;
try {
return secp256k1.verify(msg, sig, key);
} catch (e) {
return false;
}
};
/**
* Validate a public key.
* @param {Buffer} key
* @returns {Boolean} True if buffer is a valid public key.
*/
ec.publicKeyVerify = function publicKeyVerify(key) {
try {
return secp256k1.keyPair({ pub: key }).validate();
} catch (e) {
return false;
}
};
/**
* Validate a private key.
* @param {Buffer} key
* @returns {Boolean} True if buffer is a valid private key.
*/
ec.privateKeyVerify = function privateKeyVerify(key) {
if (key.length !== 32)
return false;
key = new BN(key);
return key.cmpn(0) !== 0 && key.cmp(curve.n) < 0;
};
/**
* Sign a message.
* @param {Buffer} msg
* @param {Buffer} key - Private key.
* @returns {Buffer} DER-formatted signature.
*/
ec.sign = function sign(msg, key) {
var sig;
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(key));
// Sign message and ensure low S value
sig = secp256k1.sign(msg, key, { canonical: true });
// Convert to DER array
sig = new Buffer(sig.toDER());
return sig;
};
/**
* Convert DER signature to R/S.
* @param {Buffer} sig
* @returns {Buffer} R/S-formatted signature.
*/
ec.fromDER = function fromDER(sig) {
var out;
assert(Buffer.isBuffer(sig));
sig = new Signature(sig);
out = new Buffer(64);
sig.r.toArrayLike(Buffer, 'be', 32).copy(out, 0);
sig.s.toArrayLike(Buffer, 'be', 32).copy(out, 32);
return out;
};
/**
* Convert R/S signature to DER.
* @param {Buffer} sig
* @returns {Buffer} DER-formatted signature.
*/
ec.toDER = function toDER(sig) {
var out;
assert(Buffer.isBuffer(sig));
out = new Signature({
r: new BN(sig.slice(0, 32), 'be'),
s: new BN(sig.slice(32, 64), 'be')
});
return new Buffer(out.toDER());
};
/**
* Test whether a signature has a low S value.
* @param {Buffer} sig
* @returns {Boolean}
*/
ec.isLowS = function isLowS(sig) {
try {
sig = new Signature(sig);
} catch (e) {
return false;
}
if (sig.s.cmpn(0) === 0)
return false;
// If S is greater than half the order,
// it's too high.
if (sig.s.cmp(secp256k1.nh) > 0)
return false;
return true;
};
/*
* Helpers
*/
function normalizeLength(sig) {
var data = sig;
var p = { place: 0 };
var len, rlen, slen;
if (data[p.place++] !== 0x30)
return sig;
len = getLength(data, p);
if (data.length > len + p.place)
data = data.slice(0, len + p.place);
if (data[p.place++] !== 0x02)
return sig;
rlen = getLength(data, p);
p.place += rlen;
if (data[p.place++] !== 0x02)
return sig;
slen = getLength(data, p);
if (data.length > slen + p.place)
data = data.slice(0, slen + p.place);
return data;
}
function getLength(buf, p) {
var initial = buf[p.place++];
var octetLen, val, i, off;
if (!(initial & 0x80))
return initial;
octetLen = initial & 0xf;
val = 0;
for (i = 0, off = p.place; i < octetLen; i++, off++) {
val <<= 8;
val |= buf[off];
}
p.place = off;
return val;
}

263
lib/crypto/ec-secp256k1.js Normal file
View File

@ -0,0 +1,263 @@
/*!
* ec-secp256k1.js - ecdsa wrapper for secp256k1
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var assert = require('assert');
var utils = require('../utils/utils');
var crypto = require('./crypto');
var secp256k1 = require('secp256k1');
/*
* Constants
*/
var ZERO_S = new Buffer(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'
);
var HALF_ORDER = new Buffer(
'7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0',
'hex');
/**
* @exports ec
*/
var ec = exports;
/**
* Generate a private key.
* @returns {Buffer} Private key.
*/
ec.generatePrivateKey = function generatePrivateKey() {
var priv;
do {
priv = crypto.randomBytes(32);
} while (!secp256k1.privateKeyVerify(priv));
return priv;
};
/**
* Create a public key from a private key.
* @param {Buffer} priv
* @param {Boolean?} compressed
* @returns {Buffer}
*/
ec.publicKeyCreate = function publicKeyCreate(priv, compressed) {
assert(Buffer.isBuffer(priv));
return secp256k1.publicKeyCreate(priv, compressed);
};
/**
* Compress or decompress public key.
* @param {Buffer} pub
* @returns {Buffer}
*/
ec.publicKeyConvert = function publicKeyConvert(key, compressed) {
return secp256k1.publicKeyConvert(key, compressed);
};
/**
* ((tweak + key) % n)
* @param {Buffer} privateKey
* @param {Buffer} tweak
* @returns {Buffer} privateKey
*/
ec.privateKeyTweakAdd = function privateKeyTweakAdd(privateKey, tweak) {
return secp256k1.privateKeyTweakAdd(privateKey, tweak);
};
/**
* ((g * tweak) + key)
* @param {Buffer} publicKey
* @param {Buffer} tweak
* @returns {Buffer} publicKey
*/
ec.publicKeyTweakAdd = function publicKeyTweakAdd(publicKey, tweak, compressed) {
return secp256k1.publicKeyTweakAdd(publicKey, tweak, compressed);
};
/**
* Create an ecdh.
* @param {Buffer} pub
* @param {Buffer} priv
* @returns {Buffer}
*/
ec.ecdh = function ecdh(pub, priv) {
var point = secp256k1.ecdhUnsafe(pub, priv, true);
return point.slice(1, 33);
};
/**
* Recover a public key.
* @param {Buffer} msg
* @param {Buffer} sig
* @param {Number?} j
* @param {Boolean?} compressed
* @returns {Buffer[]|Buffer|null}
*/
ec.recover = function recover(msg, sig, j, compressed) {
var key;
if (!j)
j = 0;
try {
sig = secp256k1.signatureImport(sig);
} catch (e) {
return;
}
try {
key = secp256k1.recover(msg, sig, j, compressed);
} catch (e) {
return;
}
return key;
};
/**
* Verify a signature.
* @param {Buffer} msg
* @param {Buffer} sig - DER formatted.
* @param {Buffer} key
* @param {Boolean?} - Whether this should be treated as a
* "historical" signature. This allows signatures to be of
* odd lengths.
* @param {Boolean?} high - Allow high S value.
* @returns {Boolean}
*/
ec.verify = function verify(msg, sig, key, historical, high) {
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert(Buffer.isBuffer(key));
if (sig.length === 0)
return false;
if (key.length === 0)
return false;
try {
if (historical)
sig = secp256k1.signatureImportLax(sig);
else
sig = secp256k1.signatureImport(sig);
if (high)
sig = secp256k1.signatureNormalize(sig);
return secp256k1.verify(msg, sig, key);
} catch (e) {
return false;
}
};
/**
* Validate a public key.
* @param {Buffer} key
* @returns {Boolean} True if buffer is a valid public key.
*/
ec.publicKeyVerify = function publicKeyVerify(key) {
return secp256k1.publicKeyVerify(key);
};
/**
* Validate a private key.
* @param {Buffer} key
* @returns {Boolean} True if buffer is a valid private key.
*/
ec.privateKeyVerify = function privateKeyVerify(key) {
return secp256k1.privateKeyVerify(key);
};
/**
* Sign a message.
* @param {Buffer} msg
* @param {Buffer} key - Private key.
* @returns {Buffer} DER-formatted signature.
*/
ec.sign = function sign(msg, key) {
var sig;
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(key));
// Sign message
sig = secp256k1.sign(msg, key);
// Ensure low S value
sig = secp256k1.signatureNormalize(sig.signature);
// Convert to DER array
return secp256k1.signatureExport(sig);
};
/**
* Convert DER signature to R/S.
* @param {Buffer} sig
* @returns {Buffer} R/S-formatted signature.
*/
ec.fromDER = function fromDER(sig) {
assert(Buffer.isBuffer(sig));
return secp256k1.signatureImport(sig);
};
/**
* Convert R/S signature to DER.
* @param {Buffer} sig
* @returns {Buffer} DER-formatted signature.
*/
ec.toDER = function toDER(sig) {
assert(Buffer.isBuffer(sig));
return secp256k1.signatureExport(sig);
};
/**
* Test whether a signature has a low S value.
* @param {Buffer} sig
* @returns {Boolean}
*/
ec.isLowS = function isLowS(sig) {
var rs, s;
try {
rs = secp256k1.signatureImport(sig);
s = rs.slice(32, 64);
} catch (e) {
return false;
}
if (utils.equal(s, ZERO_S))
return false;
// If S is greater than half the order,
// it's too high.
if (utils.cmp(s, HALF_ORDER) > 0)
return false;
return true;
};

View File

@ -1,524 +1,21 @@
/*! /*!
* ec.js - ecdsa wrapper for secp256k1 and elliptic * ec.js - ecdsa wrapper for secp256k1 and elliptic
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License). * Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin * https://github.com/bcoin-org/bcoin
*/ */
'use strict'; 'use strict';
var elliptic = require('elliptic');
var BN = require('bn.js');
var utils = require('../utils/utils');
var crypto = require('./crypto');
var assert = require('assert');
var secp256k1; var secp256k1;
try { if (+process.env.BCOIN_USE_ELLIPTIC !== 1) {
if (+process.env.BCOIN_USE_ELLIPTIC !== 1) try {
secp256k1 = require('secp256k1'); secp256k1 = require('secp256k1');
} catch (e) { } catch (e) {
; ;
}
} }
/* module.exports = secp256k1
* Constants ? require('./ec-secp256k1')
*/ : require('./ec-elliptic');
var ZERO_S = new Buffer(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'
);
var HALF_ORDER = new Buffer(
'7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0',
'hex');
/**
* @exports ec
*/
var ec = exports;
/**
* elliptic.js secp256k1 curve.
* @type {Object}
*/
ec.elliptic = elliptic.ec('secp256k1');
/**
* elliptic.js signature constructor.
* @static
* @type {Function}
*/
ec.signature = require('elliptic/lib/elliptic/ec/signature');
/**
* elliptic.js keypair constructor.
* @static
* @type {Function}
*/
ec.keypair = require('elliptic/lib/elliptic/ec/key');
/**
* A reference to the secp256k1 curve.
* @const {Object}
*/
ec.curve = ec.elliptic.curve;
/**
* Generate a private key.
* @returns {Buffer} Private key.
*/
ec.generatePrivateKey = function generatePrivateKey() {
var key, priv;
if (secp256k1) {
do {
priv = crypto.randomBytes(32);
} while (!secp256k1.privateKeyVerify(priv));
} else {
key = ec.elliptic.genKeyPair();
priv = key.getPrivate().toArrayLike(Buffer, 'be', 32);
}
return priv;
};
/**
* Create a public key from a private key.
* @param {Buffer} priv
* @param {Boolean?} compressed
* @returns {Buffer}
*/
ec.publicKeyCreate = function publicKeyCreate(priv, compressed) {
assert(Buffer.isBuffer(priv));
if (secp256k1)
return secp256k1.publicKeyCreate(priv, compressed);
priv = ec.elliptic.keyPair({ priv: priv });
priv = priv.getPublic(compressed !== false, 'array');
return new Buffer(priv);
};
/**
* Compress or decompress public key.
* @param {Buffer} pub
* @returns {Buffer}
*/
ec.publicKeyConvert = function publicKeyConvert(key, compressed) {
var point;
if (secp256k1)
return secp256k1.publicKeyConvert(key, compressed);
point = ec.curve.decodePoint(key);
return new Buffer(point.encode('array', compressed !== false));
};
/**
* ((tweak + key) % n)
* @param {Buffer} privateKey
* @param {Buffer} tweak
* @returns {Buffer} privateKey
*/
ec.privateKeyTweakAdd = function privateKeyTweakAdd(privateKey, tweak) {
var key;
if (secp256k1)
return secp256k1.privateKeyTweakAdd(privateKey, tweak);
key = new BN(tweak)
.add(new BN(privateKey))
.mod(ec.curve.n)
.toArrayLike(Buffer, 'be', 32);
// Only a 1 in 2^127 chance of happening.
if (!ec.privateKeyVerify(key))
throw new Error('Private key is invalid.');
return key;
};
/**
* ((g * tweak) + key)
* @param {Buffer} publicKey
* @param {Buffer} tweak
* @returns {Buffer} publicKey
*/
ec.publicKeyTweakAdd = function publicKeyTweakAdd(publicKey, tweak, compressed) {
var point, key;
if (secp256k1)
return secp256k1.publicKeyTweakAdd(publicKey, tweak, compressed);
point = ec.curve.decodePoint(publicKey);
point = ec.curve.g.mul(new BN(tweak)).add(point);
key = new Buffer(point.encode('array', compressed !== false));
if (!ec.publicKeyVerify(key))
throw new Error('Public key is invalid.');
return key;
};
/**
* Create an ecdh.
* @param {Buffer} pub
* @param {Buffer} priv
* @returns {Buffer}
*/
ec.ecdh = function ecdh(pub, priv) {
var point;
if (secp256k1) {
point = secp256k1.ecdhUnsafe(pub, priv, true);
return point.slice(1, 33);
}
priv = ec.elliptic.keyPair({ priv: priv });
pub = ec.elliptic.keyPair({ pub: pub });
return priv.derive(pub.getPublic()).toArrayLike(Buffer, 'be', 32);
};
/**
* Recover a public key.
* @param {Buffer} msg
* @param {Buffer} sig
* @param {Number?} j
* @param {Boolean?} compressed
* @returns {Buffer[]|Buffer|null}
*/
ec.recover = function recover(msg, sig, j, compressed) {
var point, key;
if (!j)
j = 0;
if (secp256k1) {
try {
sig = secp256k1.signatureImport(sig);
} catch (e) {
return;
}
try {
key = secp256k1.recover(msg, sig, j, compressed);
} catch (e) {
return;
}
return key;
}
try {
point = ec.elliptic.recoverPubKey(msg, sig, j);
} catch (e) {
return;
}
key = point.encode('array', compressed !== false);
return new Buffer(key);
};
/**
* Verify a signature.
* @param {Buffer} msg
* @param {Buffer} sig - DER formatted.
* @param {Buffer} key
* @param {Boolean?} - Whether this should be treated as a
* "historical" signature. This allows signatures to be of
* odd lengths.
* @param {Boolean?} high - Allow high S value.
* @returns {Boolean}
*/
ec.verify = function verify(msg, sig, key, historical, high) {
var result;
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert(Buffer.isBuffer(key));
if (sig.length === 0)
return false;
if (key.length === 0)
return false;
if (secp256k1) {
try {
if (historical)
sig = secp256k1.signatureImportLax(sig);
else
sig = secp256k1.signatureImport(sig);
if (high)
sig = secp256k1.signatureNormalize(sig);
result = secp256k1.verify(msg, sig, key);
} catch (e) {
result = false;
}
return result;
}
// Attempt to normalize the signature
// length before passing to elliptic.
// Note: We only do this for historical data!
// https://github.com/indutny/elliptic/issues/78
if (historical)
sig = ec.normalizeLength(sig);
// Make elliptic mimic secp256k1's
// failure with high S values.
if (!high && !ec.isLowS(sig))
return false;
try {
result = ec.elliptic.verify(msg, sig, key);
} catch (e) {
result = false;
}
return result;
};
/**
* Validate a public key.
* @param {Buffer} key
* @returns {Boolean} True if buffer is a valid public key.
*/
ec.publicKeyVerify = function publicKeyVerify(key) {
var result;
if (secp256k1)
return secp256k1.publicKeyVerify(key);
try {
result = ec.elliptic.keyPair({ pub: key }).validate();
} catch (e) {
result = false;
}
return result;
};
/**
* Validate a private key.
* @param {Buffer} key
* @returns {Boolean} True if buffer is a valid private key.
*/
ec.privateKeyVerify = function privateKeyVerify(key) {
if (secp256k1)
return secp256k1.privateKeyVerify(key);
if (key.length !== 32)
return false;
key = new BN(key);
return key.cmpn(0) !== 0 && key.cmp(ec.curve.n) < 0;
};
/**
* Sign a message.
* @param {Buffer} msg
* @param {Buffer} key - Private key.
* @returns {Buffer} DER-formatted signature.
*/
ec.sign = function sign(msg, key) {
var sig;
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(key));
if (secp256k1) {
// Sign message
sig = secp256k1.sign(msg, key);
// Ensure low S value
sig = secp256k1.signatureNormalize(sig.signature);
// Convert to DER array
sig = secp256k1.signatureExport(sig);
} else {
// Sign message and ensure low S value
sig = ec.elliptic.sign(msg, key, { canonical: true });
// Convert to DER array
sig = new Buffer(sig.toDER());
}
return sig;
};
/**
* Convert DER signature to R/S.
* @param {Buffer} sig
* @returns {Buffer} R/S-formatted signature.
*/
ec.fromDER = function fromDER(sig) {
var out;
assert(Buffer.isBuffer(sig));
if (secp256k1)
return secp256k1.signatureImport(sig);
sig = new ec.signature(sig);
out = new Buffer(64);
sig.r.toArrayLike(Buffer, 'be', 32).copy(out, 0);
sig.s.toArrayLike(Buffer, 'be', 32).copy(out, 32);
return out;
};
/**
* Convert R/S signature to DER.
* @param {Buffer} sig
* @returns {Buffer} DER-formatted signature.
*/
ec.toDER = function toDER(sig) {
var out;
assert(Buffer.isBuffer(sig));
if (secp256k1)
return secp256k1.signatureExport(sig);
out = new ec.signature({
r: new BN(sig.slice(0, 32), 'be'),
s: new BN(sig.slice(32, 64), 'be')
});
return new Buffer(out.toDER());
};
/**
* Normalize the length of a signature
* (only done for historical data).
* @param {Buffer} sig - DER formatted signature.
* @returns {Buffer} Signature.
*/
ec.normalizeLength = function normalizeLength(sig) {
var data = sig;
var p = { place: 0 };
var len, rlen, slen;
if (data[p.place++] !== 0x30)
return sig;
len = getLength(data, p);
if (data.length > len + p.place)
data = data.slice(0, len + p.place);
if (data[p.place++] !== 0x02)
return sig;
rlen = getLength(data, p);
p.place += rlen;
if (data[p.place++] !== 0x02)
return sig;
slen = getLength(data, p);
if (data.length > slen + p.place)
data = data.slice(0, slen + p.place);
return data;
};
/**
* Test whether a signature has a low S value.
* @param {Buffer} sig
* @returns {Boolean}
*/
ec.isLowS = function isLowS(sig) {
var rs, s;
if (secp256k1) {
try {
rs = secp256k1.signatureImport(sig);
s = rs.slice(32, 64);
} catch (e) {
return false;
}
if (utils.equal(s, ZERO_S))
return false;
// If S is greater than half the order,
// it's too high.
if (utils.cmp(s, HALF_ORDER) > 0)
return false;
return true;
}
try {
sig = new ec.signature(sig);
} catch (e) {
return false;
}
if (sig.s.cmpn(0) === 0)
return false;
// If S is greater than half the order,
// it's too high.
if (sig.s.cmp(ec.elliptic.nh) > 0)
return false;
return true;
};
/*
* Helpers
*/
function getLength(buf, p) {
var initial = buf[p.place++];
var octetLen, val, i, off;
if (!(initial & 0x80))
return initial;
octetLen = initial & 0xf;
val = 0;
for (i = 0, off = p.place; i < octetLen; i++, off++) {
val <<= 8;
val |= buf[off];
}
p.place = off;
return val;
}

187
lib/crypto/pk-browser.js Normal file
View File

@ -0,0 +1,187 @@
/*!
* pk-browser.js - public key algorithms for bcoin
* Copyright (c) 2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var assert = require('assert');
var BN = require('bn.js');
var ASN1 = require('../utils/asn1');
var elliptic = require('elliptic');
var crypto = require('../crypto/crypto');
var dsa, rsa, ecdsa;
/*
* DSA
*/
dsa = {};
dsa.verify = function verify(alg, msg, sig, key, params) {
throw new Error('DSA not implemented.');
};
dsa.sign = function sign(alg, msg, key, params) {
throw new Error('DSA not implemented.');
};
/*
* RSA
*/
rsa = {};
rsa.prefixes = {
md5: new Buffer('3020300c06082a864886f70d020505000410', 'hex'),
sha1: new Buffer('3021300906052b0e03021a05000414', 'hex'),
sha224: new Buffer('302d300d06096086480165030402040500041c', 'hex'),
sha256: new Buffer('3031300d060960864801650304020105000420', 'hex'),
sha384: new Buffer('3041300d060960864801650304020205000430', 'hex'),
sha512: new Buffer('3051300d060960864801650304020305000440', 'hex'),
md5sha1: new Buffer(0),
ripemd160: new Buffer('30203008060628cf060300310414', 'hex')
};
rsa.verify = function verify(alg, msg, sig, key) {
var prefix = rsa.prefixes[alg];
var hash, len, pub;
var N, e, k, m, em, ok, i;
if (!prefix)
throw new Error('Unknown PKCS prefix.');
hash = crypto.hash(alg, msg);
len = prefix.length + hash.length;
pub = ASN1.parseRSAPublic(key);
N = new BN(pub.modulus);
e = new BN(pub.publicExponent);
k = Math.ceil(N.bitLength() / 8);
if (k < len + 11)
throw new Error('Message too long.');
m = rsa.encrypt(N, e, sig);
em = leftpad(m, k);
ok = crypto.ceq(em[0], 0x00);
ok &= crypto.ceq(em[1], 0x01);
ok &= crypto.ccmp(em.slice(k - hash.length, k), hash);
ok &= crypto.ccmp(em.slice(k - len, k - hash.length), prefix);
ok &= crypto.ceq(em[k - len - 1], 0x00);
for (i = 2; i < k - len - 1; i++)
ok &= crypto.ceq(em[i], 0xff);
return ok === 1;
};
rsa.sign = function sign(alg, msg, key) {
var prefix = rsa.prefixes[alg];
var hash, len, priv;
var N, D, k, i, em;
if (!prefix)
throw new Error('Unknown PKCS prefix.');
hash = crypto.hash(alg, msg);
len = prefix.length + hash.length;
priv = ASN1.parseRSAPrivate(key);
N = new BN(priv.modulus);
D = new BN(priv.privateExponent);
k = Math.ceil(N.bitLength() / 8);
if (k < len + 11)
throw new Error('Message too long.');
em = new Buffer(k);
em.fill(0);
em[1] = 0x01;
for (i = 2; i < k - len - 1; i++)
em[i] = 0xff;
prefix.copy(em, k - len);
hash.copy(em, k - hash.length);
return rsa.decrypt(N, D, em);
};
rsa.decrypt = function decrypt(N, D, m) {
var c = new BN(m);
if (c.cmp(N) > 0)
throw new Error('Cannot decrypt.');
return c
.toRed(BN.red(N))
.redPow(D)
.fromRed()
.toArrayLike(Buffer, 'be');
};
rsa.encrypt = function encrypt(N, e, m) {
return new BN(m)
.toRed(BN.red(N))
.redPow(e)
.fromRed()
.toArrayLike(Buffer, 'be');
};
/*
* ECDSA
*/
ecdsa = {};
ecdsa.verify = function verify(curve, msg, alg, key, sig) {
var ec, hash;
assert(curve, 'No curve selected.');
ec = elliptic.ec(curve);
hash = crypto.hash(alg, msg);
return ec.verify(hash, sig, key);
};
ecdsa.sign = function sign(curve, msg, alg, key) {
var ec, hash;
assert(curve, 'No curve selected.');
ec = elliptic.ec(curve);
hash = crypto.hash(alg, msg);
return new Buffer(ec.sign(hash, key));
};
/*
* Helpers
*/
function leftpad(input, size) {
var n = input.length;
var out;
if (n > size)
n = size;
out = new Buffer(size);
out.fill(0);
input.copy(out, out.length - n);
return out;
}
/*
* Expose
*/
exports.dsa = dsa;
exports.rsa = rsa;
exports.ecdsa = ecdsa;

142
lib/crypto/pk.js Normal file
View File

@ -0,0 +1,142 @@
/*!
* pk.js - public key algorithms for bcoin
* Copyright (c) 2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var assert = require('assert');
var PEM = require('../utils/pem');
var elliptic = require('elliptic');
var crypto = require('../crypto/crypto');
var nodeCrypto = require('crypto');
var dsa, rsa, ecdsa;
/*
* DSA
*/
dsa = {};
dsa.verify = function _verify(alg, msg, sig, key, params) {
var pem = toPEM('dsa', key, params, 'public key');
return verify('dsa', alg, msg, sig, pem);
};
dsa.sign = function _sign(alg, msg, key, params) {
var pem = toPEM('dsa', key, params, 'private key');
return sign('dsa', alg, msg, pem);
};
/*
* RSA
*/
rsa = {};
rsa.verify = function _verify(alg, msg, sig, key) {
var pem = toPEM('rsa', key, null, 'public key');
return verify('rsa', alg, msg, sig, pem);
};
rsa.sign = function _sign(alg, msg, key) {
var pem = toPEM('rsa', key, null, 'private key');
return sign('rsa', alg, msg, pem);
};
/*
* ECDSA
*/
ecdsa = {};
ecdsa.verify = function verify(curve, msg, alg, key, sig) {
var ec, hash;
assert(curve, 'No curve selected.');
ec = elliptic.ec(curve);
hash = crypto.hash(alg, msg);
return ec.verify(hash, sig, key);
};
ecdsa.sign = function sign(curve, msg, alg, key) {
var ec, hash;
assert(curve, 'No curve selected.');
ec = elliptic.ec(curve);
hash = crypto.hash(alg, msg);
return new Buffer(ec.sign(hash, key));
};
/*
* Helpers
*/
function verify(alg, hash, msg, sig, key) {
var algo = normalizeAlg(alg, hash);
var verifier = nodeCrypto.createVerify(algo);
verifier.update(msg);
return verifier.verify(key, sig);
}
function sign(alg, hash, msg, key) {
var algo = normalizeAlg(alg, hash);
var sig = nodeCrypto.createSign(algo);
sig.update(msg);
return sig.sign(key);
}
function toPEM(alg, key, params, type) {
var tag, pem;
switch (alg) {
case 'dsa':
tag = 'DSA';
break;
case 'rsa':
tag = 'RSA';
break;
case 'ecdsa':
tag = 'EC';
break;
default:
throw new Error('Unsupported algorithm.');
}
pem = PEM.encode(key, tag, type);
// Key parameters, usually present
// if selecting an EC curve.
if (params)
pem += PEM.encode(params, tag, 'parameters');
return pem;
}
function normalizeAlg(alg, hash) {
var name = alg.toUpperCase() + '-' + hash.toUpperCase();
switch (name) {
case 'ECDSA-SHA1':
name = 'ecdsa-with-SHA1';
break;
case 'ECDSA-SHA256':
name = 'ecdsa-with-SHA256';
break;
}
return name;
}
/*
* Expose
*/
exports.dsa = dsa;
exports.rsa = rsa;
exports.ecdsa = ecdsa;

View File

@ -1,76 +0,0 @@
/*!
* random.js - pseudorandom byte generation for bcoin.
* Copyright (c) 2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*
* Parts of this software are based on brorand:
* https://github.com/indutny/brorand
* Copyright (c) 2014, Fedor Indutny (MIT License).
*/
/* jshint worker: true */
var randomBytes, crypto, global;
try {
crypto = require('crypto');
} catch (e) {
;
}
if (crypto) {
randomBytes = function randomBytes(n) {
return crypto.randomBytes(n);
};
} else {
if (typeof window !== 'undefined')
global = window;
else if (typeof self !== 'undefined')
global = self;
if (!global)
throw new Error('Unknown global.');
crypto = global.crypto || global.msCrypto;
if (crypto && crypto.getRandomValues) {
randomBytes = function randomBytes(n) {
var data = new Uint8Array(n);
crypto.getRandomValues(data);
return new Buffer(data.buffer);
};
} else {
// Out of luck here. Use bad randomness for now.
// Possibly fall back to randy in the future:
// https://github.com/deestan/randy
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 randomInt() {
return randomBytes(4).readUInt32LE(0, true);
}
function randomRange(min, max) {
var num = randomInt();
return Math.floor((num / 0x100000000) * (max - min) + min);
}
/*
* Expose
*/
exports = randomBytes;
exports.randomBytes = randomBytes;
exports.randomInt = randomInt;
exports.randomRange = randomRange;
module.exports = randomBytes;

View File

@ -10,9 +10,11 @@ var BN = require('bn.js');
var elliptic = require('elliptic'); var elliptic = require('elliptic');
var Signature = require('elliptic/lib/elliptic/ec/signature'); var Signature = require('elliptic/lib/elliptic/ec/signature');
var hmacDRBG = require('elliptic/lib/elliptic/hmac-drbg'); var hmacDRBG = require('elliptic/lib/elliptic/hmac-drbg');
var curves = elliptic.curves;
var curve = elliptic.ec('secp256k1').curve;
var sha256 = require('./crypto').sha256; var sha256 = require('./crypto').sha256;
var secp256k1 = elliptic.ec('secp256k1');
var curve = secp256k1.curve;
var curves = elliptic.curves;
var hash = curves.secp256k1.hash;
/** /**
* @exports schnorr * @exports schnorr
@ -335,7 +337,7 @@ schnorr.drbg = function drbg(msg, priv, data) {
pers = toArray(kdata.slice(64)); pers = toArray(kdata.slice(64));
return new hmacDRBG({ return new hmacDRBG({
hash: curves.secp256k1.hash, hash: hash,
entropy: prv, entropy: prv,
nonce: msg, nonce: msg,
pers: pers pers: pers

View File

@ -35,7 +35,7 @@
var utils = require('../utils/utils'); var utils = require('../utils/utils');
var crypto = require('./crypto'); var crypto = require('./crypto');
var native = require('../utils/native'); var native = require('../utils/native').binding;
var U32Array = typeof Uint32Array === 'function' ? Uint32Array : Array; var U32Array = typeof Uint32Array === 'function' ? Uint32Array : Array;
/** /**

View File

@ -34,7 +34,7 @@
'use strict'; 'use strict';
var crypto = require('./crypto'); var crypto = require('./crypto');
var native = require('../utils/native'); var native = require('../utils/native').binding;
var U32Array = typeof Uint32Array === 'function' ? Uint32Array : Array; var U32Array = typeof Uint32Array === 'function' ? Uint32Array : Array;
/** /**

View File

@ -9,7 +9,7 @@
'use strict'; 'use strict';
var native = require('../utils/native'); var native = require('../utils/native').binding;
/** /**
* Javascript siphash implementation. Used for compact block relay. * Javascript siphash implementation. Used for compact block relay.

View File

@ -0,0 +1,16 @@
/**
* backends-browser.js - database backends for bcoin
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var level = require('./level');
var RBT = require('./rbt');
exports.get = function get(name) {
if (name === 'rbt')
return RBT;
return level;
};

18
lib/db/backends.js Normal file
View File

@ -0,0 +1,18 @@
/**
* backends.js - database backends for bcoin
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
exports.get = function get(name) {
if (name === 'rbt')
return require('./rbt');
try {
return require(name);
} catch (e) {
throw new Error('Database backend "' + name + '" not found.');
}
};

View File

@ -1,7 +1,5 @@
/** /**
* global ldb tracker * ldb.js - database backend for bcoin
* @module ldb
* @license
* Copyright (c) 2014-2015, Fedor Indutny (MIT License) * Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License). * Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin * https://github.com/bcoin-org/bcoin
@ -9,9 +7,10 @@
'use strict'; 'use strict';
var assert = require('assert');
var LowlevelUp = require('./lowlevelup'); var LowlevelUp = require('./lowlevelup');
var utils = require('../utils/utils'); var utils = require('../utils/utils');
var assert = require('assert'); var backends = require('./backends');
/** /**
* @param {Object} options * @param {Object} options
@ -28,8 +27,8 @@ var assert = require('assert');
* @returns {LowlevelUp} * @returns {LowlevelUp}
*/ */
function ldb(options) { function LDB(options) {
var target = ldb.getTarget(options); var target = LDB.getTarget(options);
if (target.backend !== 'rbt') if (target.backend !== 'rbt')
utils.mkdir(target.location, true); utils.mkdir(target.location, true);
@ -66,7 +65,7 @@ function ldb(options) {
* @returns {Object} * @returns {Object}
*/ */
ldb.getBackend = function getBackend(db) { LDB.getBackend = function getBackend(db) {
var name, ext; var name, ext;
if (!db) if (!db)
@ -111,17 +110,10 @@ ldb.getBackend = function getBackend(db) {
* @returns {Object} * @returns {Object}
*/ */
ldb.getTarget = function getTarget(options) { LDB.getTarget = function getTarget(options) {
var backend = ldb.getBackend(options.db); var backend = LDB.getBackend(options.db);
var location = options.location; var location = options.location;
var db; var db = backends.get(backend.name);
if (backend.name === 'rbt')
db = require('./rbt');
else if (utils.isBrowser)
db = require('./level');
else
db = require(backend.name);
if (typeof location !== 'string') { if (typeof location !== 'string') {
assert(backend.name === 'rbt', 'Location required.'); assert(backend.name === 'rbt', 'Location required.');
@ -139,4 +131,4 @@ ldb.getTarget = function getTarget(options) {
* Expose * Expose
*/ */
module.exports = ldb; module.exports = LDB;

View File

@ -13,7 +13,8 @@ var constants = require('../protocol/constants');
var BufferWriter = require('../utils/writer'); var BufferWriter = require('../utils/writer');
var BufferReader = require('../utils/reader'); var BufferReader = require('../utils/reader');
var HD = require('./hd'); var HD = require('./hd');
var unorm; var wordlist = require('./wordlist');
var nfkd = require('../utils/nfkd');
/** /**
* HD Mnemonic * HD Mnemonic
@ -368,22 +369,7 @@ Mnemonic.getLanguage = function getLanguage(word) {
*/ */
Mnemonic.getWordlist = function getWordlist(language) { Mnemonic.getWordlist = function getWordlist(language) {
switch (language) { return wordlist.get(language);
case 'simplified chinese':
return require('./words/chinese-simplified.js');
case 'traditional chinese':
return require('./words/chinese-traditional.js');
case 'english':
return require('./words/english.js');
case 'french':
return require('./words/french.js');
case 'italian':
return require('./words/italian.js');
case 'japanese':
return require('./words/japanese.js');
default:
throw new Error('Unknown language: ' + language);
}
}; };
/** /**
@ -523,20 +509,6 @@ Mnemonic.isMnemonic = function isMnemonic(obj) {
&& typeof obj.toSeed === 'function'; && typeof obj.toSeed === 'function';
}; };
/*
* Helpers
*/
function nfkd(str) {
if (str.normalize)
return str.normalize('NFKD');
if (!unorm)
unorm = require('../../vendor/unorm');
return unorm.nfkd(str);
}
/* /*
* Expose * Expose
*/ */

View File

@ -0,0 +1,28 @@
/*!
* wordlist.js - wordlists for bcoin
* Copyright (c) 2015-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var words = require('./words');
exports.get = function get(name) {
switch (name) {
case 'simplified chinese':
return words.chinese.simplified;
case 'traditional chinese':
return words.chinese.traditional;
case 'english':
return words.english;
case 'french':
return words.french;
case 'italian':
return words.italian;
case 'japanese':
return words.japanese;
default:
throw new Error('Unknown language: ' + name);
}
};

26
lib/hd/wordlist.js Normal file
View File

@ -0,0 +1,26 @@
/*!
* wordlist.js - wordlists for bcoin
* Copyright (c) 2015-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
exports.get = function get(name) {
switch (name) {
case 'simplified chinese':
return require('./words/chinese-simplified.js');
case 'traditional chinese':
return require('./words/chinese-traditional.js');
case 'english':
return require('./words/english.js');
case 'french':
return require('./words/french.js');
case 'italian':
return require('./words/italian.js');
case 'japanese':
return require('./words/japanese.js');
default:
throw new Error('Unknown language: ' + name);
}
};

17
lib/hd/words/index.js Normal file
View File

@ -0,0 +1,17 @@
/*!
* index.js - wordlists for bcoin
* Copyright (c) 2015-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
exports.chinese = {
simplified: require('./chinese-simplified.js'),
traditional: require('./chinese-traditional.js')
};
exports.english = require('./english.js');
exports.french = require('./french.js');
exports.italian = require('./italian.js');
exports.japanese = require('./japanese.js');

View File

@ -7,16 +7,10 @@
'use strict'; 'use strict';
var utils = require('../utils/utils'); exports.request = require('./request');
exports.Client = require('./client');
if (!utils.isBrowser) { exports.RPCClient = require('./rpcclient');
exports.request = require('./request'); exports.Wallet = require('./wallet');
exports.Client = require('./client'); exports.Base = require('./base');
exports.RPCClient = require('./rpcclient'); exports.RPC = require('./rpc');
exports.Wallet = require('./wallet'); exports.Server = require('./server');
exports.Base = require('./base');
exports.RPC = require('./rpc');
exports.Server = require('./server');
} else {
exports.RPC = require('./rpc');
}

View File

@ -31,13 +31,7 @@ var BufferReader = require('../utils/reader');
var TX = require('../primitives/tx'); var TX = require('../primitives/tx');
var Logger = require('../node/logger'); var Logger = require('../node/logger');
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter;
var fs; var fs = require('fs');
try {
fs = require('fs');
} catch (e) {
;
}
function RPC(node) { function RPC(node) {
if (!(this instanceof RPC)) if (!(this instanceof RPC))
@ -2794,7 +2788,7 @@ RPC.prototype.dumpwallet = co(function* dumpwallet(args) {
out = out.join('\n'); out = out.join('\n');
if (!fs) if (fs.unsupported)
return out; return out;
yield writeFile(file, out); yield writeFile(file, out);
@ -3216,7 +3210,7 @@ RPC.prototype.importwallet = co(function* importwallet(args) {
file = toString(args[0]); file = toString(args[0]);
if (!fs) if (fs.unsupported)
throw new RPCError('FS not available.'); throw new RPCError('FS not available.');
data = yield readFile(file, 'utf8'); data = yield readFile(file, 'utf8');

View File

@ -7,7 +7,9 @@
'use strict'; 'use strict';
var assert = require('assert');
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter;
var tcp = require('./tcp');
var utils = require('../utils/utils'); var utils = require('../utils/utils');
var co = require('../utils/co'); var co = require('../utils/co');
var Parser = require('./parser'); var Parser = require('./parser');
@ -15,7 +17,6 @@ var Framer = require('./framer');
var packets = require('./packets'); var packets = require('./packets');
var packetTypes = packets.types; var packetTypes = packets.types;
var NetworkAddress = require('../primitives/netaddress'); var NetworkAddress = require('../primitives/netaddress');
var assert = require('assert');
var constants = require('../protocol/constants'); var constants = require('../protocol/constants');
var InvItem = require('../primitives/invitem'); var InvItem = require('../primitives/invitem');
var Locker = require('../utils/locker'); var Locker = require('../utils/locker');
@ -249,21 +250,15 @@ Peer.prototype._init = function init() {
Peer.prototype.connect = function connect(port, host) { Peer.prototype.connect = function connect(port, host) {
var self = this; var self = this;
var socket, proxy, net; var proxy = this.pool.proxyServer;
var socket;
assert(!this.socket); assert(!this.socket);
if (this.createSocket) { if (this.createSocket)
socket = this.createSocket(port, host); socket = this.createSocket(port, host, proxy);
} else { else
if (utils.isBrowser) { socket = tcp.connect(port, host, proxy);
proxy = require('./proxysocket');
socket = proxy.connect(this.pool.proxyServer, port, host);
} else {
net = require('net');
socket = net.connect(port, host);
}
}
this.logger.debug('Connecting to %s.', this.hostname); this.logger.debug('Connecting to %s.', this.hostname);

View File

@ -7,12 +7,12 @@
'use strict'; 'use strict';
var AsyncObject = require('../utils/async'); var assert = require('assert');
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter;
var AsyncObject = require('../utils/async');
var utils = require('../utils/utils'); var utils = require('../utils/utils');
var IP = require('../utils/ip'); var IP = require('../utils/ip');
var co = require('../utils/co'); var co = require('../utils/co');
var assert = require('assert');
var constants = require('../protocol/constants'); var constants = require('../protocol/constants');
var VerifyError = require('../utils/errors').VerifyError; var VerifyError = require('../utils/errors').VerifyError;
var NetworkAddress = require('../primitives/netaddress'); var NetworkAddress = require('../primitives/netaddress');
@ -27,6 +27,8 @@ var Network = require('../protocol/network');
var time = require('./timedata'); var time = require('./timedata');
var Peer = require('./peer'); var Peer = require('./peer');
var TX = require('../primitives/tx'); var TX = require('../primitives/tx');
var tcp = require('./tcp');
var request = require('../http/request');
/** /**
* A pool of peers for handling all network activity. * A pool of peers for handling all network activity.
@ -396,7 +398,6 @@ Pool.prototype.connect = function connect() {
Pool.prototype.listen = function listen() { Pool.prototype.listen = function listen() {
var self = this; var self = this;
var net;
if (this.server) if (this.server)
return Promise.resolve(); return Promise.resolve();
@ -404,10 +405,9 @@ Pool.prototype.listen = function listen() {
if (this.createServer) { if (this.createServer) {
this.server = this.createServer(); this.server = this.createServer();
} else { } else {
if (utils.isBrowser) if (!tcp.Server)
return; return;
net = require('net'); this.server = new tcp.Server();
this.server = new net.Server();
} }
this.server.on('connection', function(socket) { this.server.on('connection', function(socket) {
@ -1871,13 +1871,11 @@ Pool.prototype.isIgnored = function isIgnored(addr) {
*/ */
Pool.prototype.getIP = co(function* getIP() { Pool.prototype.getIP = co(function* getIP() {
var request, res, ip; var res, ip;
if (utils.isBrowser) if (request.unsupported)
throw new Error('Could not find IP.'); throw new Error('Could not find IP.');
request = require('../http/request');
try { try {
res = yield request.promise({ res = yield request.promise({
method: 'GET', method: 'GET',
@ -1903,13 +1901,11 @@ Pool.prototype.getIP = co(function* getIP() {
*/ */
Pool.prototype.getIP2 = co(function* getIP2() { Pool.prototype.getIP2 = co(function* getIP2() {
var request, res, ip; var res, ip;
if (utils.isBrowser) if (request.unsupported)
throw new Error('Could not find IP.'); throw new Error('Could not find IP.');
request = require('../http/request');
res = yield request.promise({ res = yield request.promise({
method: 'GET', method: 'GET',
uri: 'http://checkip.dyndns.org', uri: 'http://checkip.dyndns.org',

16
lib/net/tcp-browser.js Normal file
View File

@ -0,0 +1,16 @@
/*!
* tcp.js - tcp backend for bcoin
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var ProxySocket = require('./proxysocket');
var tcp = exports;
tcp.connect = function connect(port, host, uri) {
return ProxySocket.connect(uri, port, host);
};
tcp.Server = null;

16
lib/net/tcp.js Normal file
View File

@ -0,0 +1,16 @@
/*!
* tcp.js - tcp backend for bcoin
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var net = require('net');
var tcp = exports;
tcp.connect = function connect(port, host) {
return net.connect(port, host);
};
tcp.Server = net.Server;

View File

@ -9,10 +9,7 @@
var Network = require('../protocol/network'); var Network = require('../protocol/network');
var utils = require('../utils/utils'); var utils = require('../utils/utils');
var assert = require('assert'); var assert = require('assert');
var fs; var fs = require('fs');
if (!utils.isBrowser)
fs = require('fs');
/** /**
* @exports config * @exports config
@ -660,7 +657,7 @@ function boolpath(value, prefix, dirname) {
} }
function file(value, prefix, dirname, enc) { function file(value, prefix, dirname, enc) {
if (!fs) if (fs.unsupported)
return null; return null;
value = path(value, prefix, dirname); value = path(value, prefix, dirname);
@ -684,7 +681,7 @@ function resolve(a, b) {
} }
function readFile(file) { function readFile(file) {
if (!fs) if (fs.unsupported)
return ''; return '';
if (!file) if (!file)

View File

@ -17,13 +17,7 @@ var Mempool = require('../mempool/mempool');
var Pool = require('../net/pool'); var Pool = require('../net/pool');
var Miner = require('../miner/miner'); var Miner = require('../miner/miner');
var WalletDB = require('../wallet/walletdb'); var WalletDB = require('../wallet/walletdb');
var HTTPServer; var HTTPServer = require('../http/server');
try {
HTTPServer = require('../http/server');
} catch (e) {
;
}
/** /**
* Create a fullnode complete with a chain, * Create a fullnode complete with a chain,
@ -155,7 +149,7 @@ function FullNode(options) {
}); });
// HTTP needs access to the node. // HTTP needs access to the node.
if (!utils.isBrowser) { if (!HTTPServer.unsupported) {
this.http = new HTTPServer({ this.http = new HTTPServer({
network: this.network, network: this.network,
logger: this.logger, logger: this.logger,

View File

@ -8,10 +8,7 @@
var utils = require('../utils/utils'); var utils = require('../utils/utils');
var assert = require('assert'); var assert = require('assert');
var fs; var fs = require('fs');
if (!utils.isBrowser)
fs = require('fs');
/** /**
* Basic stdout and file logger. * Basic stdout and file logger.
@ -287,9 +284,12 @@ Logger.prototype.writeStream = function writeStream(level, args) {
if (!this.stream) { if (!this.stream) {
if (!this.file) if (!this.file)
return; return;
if (utils.isBrowser)
if (fs.unsupported)
return; return;
utils.mkdir(this.file, true); utils.mkdir(this.file, true);
this.stream = fs.createWriteStream(this.file, { flags: 'a' }); this.stream = fs.createWriteStream(this.file, { flags: 'a' });
this.stream.on('error', function() {}); this.stream.on('error', function() {});
} }

View File

@ -13,13 +13,7 @@ var Node = require('./node');
var Chain = require('../chain/chain'); var Chain = require('../chain/chain');
var Pool = require('../net/pool'); var Pool = require('../net/pool');
var WalletDB = require('../wallet/walletdb'); var WalletDB = require('../wallet/walletdb');
var HTTPServer; var HTTPServer = require('../http/server');
try {
HTTPServer = require('../http/server');
} catch (e) {
;
}
/** /**
* Create an spv node which only maintains * Create an spv node which only maintains
@ -95,7 +89,7 @@ function SPVNode(options) {
verify: true verify: true
}); });
if (!utils.isBrowser) { if (!HTTPServer.unsupported) {
this.http = new HTTPServer({ this.http = new HTTPServer({
network: this.network, network: this.network,
logger: this.logger, logger: this.logger,

View File

@ -31,9 +31,9 @@
var assert = require('assert'); var assert = require('assert');
var BufferReader = require('../utils/reader'); var BufferReader = require('../utils/reader');
var asn1 = exports; var ASN1 = exports;
asn1.parseTag = function parseTag(p) { ASN1.parseTag = function parseTag(p) {
var tag = p.readU8(); var tag = p.readU8();
var primitive = (tag & 0x20) === 0; var primitive = (tag & 0x20) === 0;
var oct; var oct;
@ -53,11 +53,11 @@ asn1.parseTag = function parseTag(p) {
return { return {
primitive: primitive, primitive: primitive,
tag: tag, tag: tag,
len: asn1.parseLen(p, primitive) len: ASN1.parseLen(p, primitive)
}; };
}; };
asn1.parseLen = function parseLen(p, primitive) { ASN1.parseLen = function parseLen(p, primitive) {
var len = p.readU8(); var len = p.readU8();
var num, i, j; var num, i, j;
@ -85,52 +85,52 @@ asn1.parseLen = function parseLen(p, primitive) {
return len; return len;
}; };
asn1.parseCert = function parseCert(data) { ASN1.parseCert = function parseCert(data) {
var d = BufferReader(data); var d = BufferReader(data);
var p; var p;
d.start(); d.start();
p = BufferReader(asn1.parseSeq(d)); p = BufferReader(ASN1.parseSeq(d));
return { return {
tbs: asn1.parseTBS(p), tbs: ASN1.parseTBS(p),
sigAlg: asn1.parseAlgIdent(p), sigAlg: ASN1.parseAlgIdent(p),
sig: asn1.parseBitstr(p), sig: ASN1.parseBitstr(p),
raw: d.endData(true) raw: d.endData(true)
}; };
}; };
asn1.parseTBS = function parseTBS(data) { ASN1.parseTBS = function parseTBS(data) {
var d = BufferReader(data); var d = BufferReader(data);
var p; var p;
d.start(); d.start();
p = BufferReader(asn1.parseSeq(d)); p = BufferReader(ASN1.parseSeq(d));
return { return {
version: asn1.parseExplicitInt(p, 0, true), version: ASN1.parseExplicitInt(p, 0, true),
serial: asn1.parseInt(p), serial: ASN1.parseInt(p),
sig: asn1.parseAlgIdent(p), sig: ASN1.parseAlgIdent(p),
issuer: asn1.parseName(p), issuer: ASN1.parseName(p),
validity: asn1.parseValidity(p), validity: ASN1.parseValidity(p),
subject: asn1.parseName(p), subject: ASN1.parseName(p),
pubkey: asn1.parsePubkey(p), pubkey: ASN1.parsePubkey(p),
raw: d.endData(true) raw: d.endData(true)
}; };
}; };
asn1.parseSeq = function parseSeq(data) { ASN1.parseSeq = function parseSeq(data) {
var p = BufferReader(data); var p = BufferReader(data);
var tag = asn1.parseTag(p); var tag = ASN1.parseTag(p);
assert.equal(tag.tag, 0x10); // seq assert.equal(tag.tag, 0x10); // seq
return p.readBytes(tag.len, true); return p.readBytes(tag.len, true);
}; };
asn1.parseInt = function parseInt(data, readNum) { ASN1.parseInt = function parseInt(data, readNum) {
var p = BufferReader(data); var p = BufferReader(data);
var tag = asn1.parseTag(p); var tag = ASN1.parseTag(p);
var num; var num;
assert.equal(tag.tag, 0x02); // int assert.equal(tag.tag, 0x02); // int
@ -143,30 +143,30 @@ asn1.parseInt = function parseInt(data, readNum) {
return num; return num;
}; };
asn1.parseExplicitInt = function parseExplicitInt(data, i, readNum) { ASN1.parseExplicitInt = function parseExplicitInt(data, i, readNum) {
var p = BufferReader(data); var p = BufferReader(data);
var off = p.offset; var off = p.offset;
var tag = asn1.parseTag(p); var tag = ASN1.parseTag(p);
if (tag.tag !== i) { if (tag.tag !== i) {
p.seek(-(p.offset - off)); p.seek(-(p.offset - off));
return -1; return -1;
} }
return asn1.parseInt(p, readNum); return ASN1.parseInt(p, readNum);
}; };
asn1.parseBitstr = function parseBitstr(data) { ASN1.parseBitstr = function parseBitstr(data) {
var p = BufferReader(data); var p = BufferReader(data);
var tag = asn1.parseTag(p); var tag = ASN1.parseTag(p);
assert.equal(tag.tag, 0x03); // bitstr assert.equal(tag.tag, 0x03); // bitstr
return asn1.alignBitstr(p.readBytes(tag.len, true)); return ASN1.alignBitstr(p.readBytes(tag.len, true));
}; };
asn1.parseString = function parseString(data) { ASN1.parseString = function parseString(data) {
var p = BufferReader(data); var p = BufferReader(data);
var tag = asn1.parseTag(p); var tag = ASN1.parseTag(p);
switch (tag.tag) { switch (tag.tag) {
case 0x03: // bitstr case 0x03: // bitstr
return asn1.alignBitstr(p.readBytes(tag.len, true)); return ASN1.alignBitstr(p.readBytes(tag.len, true));
case 0x04: // octstr case 0x04: // octstr
case 0x12: // numstr case 0x12: // numstr
case 0x13: // prinstr case 0x13: // prinstr
@ -186,7 +186,7 @@ asn1.parseString = function parseString(data) {
} }
}; };
asn1.alignBitstr = function(data) { ASN1.alignBitstr = function(data) {
var padding = data[0]; var padding = data[0];
var bits = (data.length - 1) * 8 - padding; var bits = (data.length - 1) * 8 - padding;
var buf = data.slice(1); var buf = data.slice(1);
@ -207,48 +207,48 @@ asn1.alignBitstr = function(data) {
return out; return out;
}; };
asn1.parsePubkey = function parsePubkey(data) { ASN1.parsePubkey = function parsePubkey(data) {
var p = BufferReader(data); var p = BufferReader(data);
p = BufferReader(asn1.parseSeq(p)); p = BufferReader(ASN1.parseSeq(p));
return { return {
alg: asn1.parseAlgIdent(p), alg: ASN1.parseAlgIdent(p),
pubkey: asn1.parseBitstr(p) pubkey: ASN1.parseBitstr(p)
}; };
}; };
asn1.parseName = function parseName(data) { ASN1.parseName = function parseName(data) {
var p = BufferReader(data); var p = BufferReader(data);
var values = []; var values = [];
var tag; var tag;
p = BufferReader(asn1.parseSeq(p)); p = BufferReader(ASN1.parseSeq(p));
while (p.left()) { while (p.left()) {
tag = asn1.parseTag(p); tag = ASN1.parseTag(p);
assert.equal(tag.tag, 0x11); // set assert.equal(tag.tag, 0x11); // set
tag = asn1.parseTag(p); tag = ASN1.parseTag(p);
assert.equal(tag.tag, 0x10); // seq assert.equal(tag.tag, 0x10); // seq
values.push({ values.push({
type: asn1.parseOID(p), type: ASN1.parseOID(p),
value: asn1.parseString(p) value: ASN1.parseString(p)
}); });
} }
return values; return values;
}; };
asn1.parseValidity = function parseValidity(data) { ASN1.parseValidity = function parseValidity(data) {
var p = BufferReader(data); var p = BufferReader(data);
p = BufferReader(asn1.parseSeq(p)); p = BufferReader(ASN1.parseSeq(p));
return { return {
notBefore: asn1.parseTime(p), notBefore: ASN1.parseTime(p),
notAfter: asn1.parseTime(p) notAfter: ASN1.parseTime(p)
}; };
}; };
asn1.parseTime = function parseTime(data) { ASN1.parseTime = function parseTime(data) {
var p = BufferReader(data); var p = BufferReader(data);
var tag = asn1.parseTag(p); var tag = ASN1.parseTag(p);
var str = p.readString('ascii', tag.len); var str = p.readString('ascii', tag.len);
var year, mon, day, hour, min, sec; var year, mon, day, hour, min, sec;
@ -281,9 +281,9 @@ asn1.parseTime = function parseTime(data) {
return Date.UTC(year, mon - 1, day, hour, min, sec, 0) / 1000; return Date.UTC(year, mon - 1, day, hour, min, sec, 0) / 1000;
}; };
asn1.parseOID = function parseOID(data) { ASN1.parseOID = function parseOID(data) {
var p = BufferReader(data); var p = BufferReader(data);
var tag = asn1.parseTag(p); var tag = ASN1.parseTag(p);
var ids = []; var ids = [];
var ident = 0; var ident = 0;
var subident = 0; var subident = 0;
@ -314,17 +314,17 @@ asn1.parseOID = function parseOID(data) {
return result.join('.'); return result.join('.');
}; };
asn1.parseAlgIdent = function parseAlgIdent(data) { ASN1.parseAlgIdent = function parseAlgIdent(data) {
var p = BufferReader(data); var p = BufferReader(data);
var params = null; var params = null;
var alg; var alg;
p = BufferReader(asn1.parseSeq(p)); p = BufferReader(ASN1.parseSeq(p));
alg = asn1.parseOID(p); alg = ASN1.parseOID(p);
if (p.left() > 0) { if (p.left() > 0) {
params = p.readBytes(asn1.parseTag(p).len, true); params = p.readBytes(ASN1.parseTag(p).len, true);
if (params.length === 0) if (params.length === 0)
params = null; params = null;
} }
@ -335,117 +335,27 @@ asn1.parseAlgIdent = function parseAlgIdent(data) {
}; };
}; };
asn1.parseRSAPublic = function parseRSAPublic(data) { ASN1.parseRSAPublic = function parseRSAPublic(data) {
var p = BufferReader(data); var p = BufferReader(data);
p = BufferReader(asn1.parseSeq(p)); p = BufferReader(ASN1.parseSeq(p));
return { return {
modulus: asn1.parseInt(p), modulus: ASN1.parseInt(p),
publicExponent: asn1.parseInt(p) publicExponent: ASN1.parseInt(p)
}; };
}; };
asn1.parseRSAPrivate = function parseRSAPrivate(data) { ASN1.parseRSAPrivate = function parseRSAPrivate(data) {
var p = BufferReader(data); var p = BufferReader(data);
p = BufferReader(asn1.parseSeq(p)); p = BufferReader(ASN1.parseSeq(p));
return { return {
version: asn1.parseInt(p, true), version: ASN1.parseInt(p, true),
modulus: asn1.parseInt(p), modulus: ASN1.parseInt(p),
publicExponent: asn1.parseInt(p), publicExponent: ASN1.parseInt(p),
privateExponent: asn1.parseInt(p), privateExponent: ASN1.parseInt(p),
prime1: asn1.parseInt(p), prime1: ASN1.parseInt(p),
prime2: asn1.parseInt(p), prime2: ASN1.parseInt(p),
exponent1: asn1.parseInt(p), exponent1: ASN1.parseInt(p),
exponent2: asn1.parseInt(p), exponent2: ASN1.parseInt(p),
coefficient: asn1.parseInt(p) coefficient: ASN1.parseInt(p)
}; };
}; };
asn1.parsePEM = function parsePEM(pem) {
var buf = '';
var chunks = [];
var s, tag, type;
while (pem.length) {
if (s = /^-----BEGIN ([^\-]+)-----/.exec(pem)) {
pem = pem.substring(s[0].length);
tag = s[1];
continue;
}
if (s = /^-----END ([^\-]+)-----/.exec(pem)) {
pem = pem.substring(s[0].length);
assert(tag === s[1], 'Tag mismatch.');
buf = new Buffer(buf, 'base64');
type = tag.split(' ')[0].toLowerCase();
chunks.push({ tag: tag, type: type, data: buf });
buf = '';
tag = null;
continue;
}
if (s = /^[a-zA-Z0-9\+=\/]+/.exec(pem)) {
pem = pem.substring(s[0].length);
buf += s[0];
continue;
}
if (s = /^\s+/.exec(pem)) {
pem = pem.substring(s[0].length);
continue;
}
throw new Error('PEM parse error.');
}
assert(chunks.length !== 0, 'PEM parse error.');
assert(!tag, 'Un-ended tag.');
assert(buf.length === 0, 'Trailing data.');
return chunks;
};
asn1.fromPEM = function fromPEM(pem) {
var chunks = asn1.parsePEM(pem);
var body = chunks[0];
var extra = chunks[1];
var params, alg;
if (extra) {
if (extra.tag.indexOf('PARAMETERS') !== -1)
params = extra.data;
}
switch (body.type) {
case 'dsa':
alg = 'dsa';
break;
case 'rsa':
alg = 'rsa';
break;
case 'ec':
alg = 'ecdsa';
break;
}
return {
type: body.type,
alg: alg,
data: body.data,
params: params
};
};
asn1.toPEM = function toPEM(der, type, suffix) {
var pem = '';
var i;
if (suffix)
type += ' ' + suffix;
type = type.toUpperCase();
der = der.toString('base64');
for (i = 0; i < der.length; i += 64)
pem += der.slice(i, i + 64) + '\r\n';
return ''
+ '-----BEGIN ' + type + '-----\r\n'
+ pem
+ '-----END ' + type + '-----\r\n';
};

View File

@ -7,7 +7,7 @@
'use strict'; 'use strict';
var native = require('./native'); var native = require('./native').binding;
var assert = require('assert'); var assert = require('assert');
/* /*

View File

@ -7,7 +7,7 @@
'use strict'; 'use strict';
var native = require('./native'); var native = require('./native').binding;
/** /**
* Murmur3 hash. * Murmur3 hash.

View File

@ -6,15 +6,11 @@
'use strict'; 'use strict';
var isBrowser = exports.binding = null;
(typeof process !== 'undefined' && process.browser)
|| typeof window !== 'undefined';
module.exports = null; if (+process.env.BCOIN_NO_NATIVE !== 1) {
if (!isBrowser && +process.env.BCOIN_NO_NATIVE !== 1) {
try { try {
module.exports = require('bcoin-native'); exports.binding = require('bcoin-native');
} catch (e) { } catch (e) {
; ;
} }

View File

@ -0,0 +1,7 @@
/*!
* nexttick.js - setimmediate for bcoin
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
module.exports = require('../../vendor/setimmediate');

9
lib/utils/nexttick.js Normal file
View File

@ -0,0 +1,9 @@
/*!
* nexttick.js - setimmediate for bcoin
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
module.exports = typeof setImmediate !== 'function'
? process.nextTick
: setImmediate;

20
lib/utils/nfkd-browser.js Normal file
View File

@ -0,0 +1,20 @@
/**
* nfkd-browser.js - unicode normalization for bcoin
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
var unorm = require('../../vendor/unorm');
function nfkd(str) {
if (str.normalize)
return str.normalize('NFKD');
return unorm.nfkd(str);
}
/*
* Expose
*/
module.exports = nfkd;

23
lib/utils/nfkd.js Normal file
View File

@ -0,0 +1,23 @@
/**
* nfkd.js - unicode normalization for bcoin
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
var unorm;
function nfkd(str) {
if (str.normalize)
return str.normalize('NFKD');
if (!unorm)
unorm = require('../../vendor/unorm');
return unorm.nfkd(str);
}
/*
* Expose
*/
module.exports = nfkd;

100
lib/utils/pem.js Normal file
View File

@ -0,0 +1,100 @@
/*!
* pem.js - pem parsing for bcoin
* Copyright (c) 2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var assert = require('assert');
var PEM = exports;
PEM.parse = function parse(pem) {
var buf = '';
var chunks = [];
var s, tag, type;
while (pem.length) {
if (s = /^-----BEGIN ([^\-]+)-----/.exec(pem)) {
pem = pem.substring(s[0].length);
tag = s[1];
continue;
}
if (s = /^-----END ([^\-]+)-----/.exec(pem)) {
pem = pem.substring(s[0].length);
assert(tag === s[1], 'Tag mismatch.');
buf = new Buffer(buf, 'base64');
type = tag.split(' ')[0].toLowerCase();
chunks.push({ tag: tag, type: type, data: buf });
buf = '';
tag = null;
continue;
}
if (s = /^[a-zA-Z0-9\+=\/]+/.exec(pem)) {
pem = pem.substring(s[0].length);
buf += s[0];
continue;
}
if (s = /^\s+/.exec(pem)) {
pem = pem.substring(s[0].length);
continue;
}
throw new Error('PEM parse error.');
}
assert(chunks.length !== 0, 'PEM parse error.');
assert(!tag, 'Un-ended tag.');
assert(buf.length === 0, 'Trailing data.');
return chunks;
};
PEM.decode = function decode(pem) {
var chunks = PEM.parse(pem);
var body = chunks[0];
var extra = chunks[1];
var params, alg;
if (extra) {
if (extra.tag.indexOf('PARAMETERS') !== -1)
params = extra.data;
}
switch (body.type) {
case 'dsa':
alg = 'dsa';
break;
case 'rsa':
alg = 'rsa';
break;
case 'ec':
alg = 'ecdsa';
break;
}
return {
type: body.type,
alg: alg,
data: body.data,
params: params
};
};
PEM.encode = function encode(der, type, suffix) {
var pem = '';
var i;
if (suffix)
type += ' ' + suffix;
type = type.toUpperCase();
der = der.toString('base64');
for (i = 0; i < der.length; i += 64)
pem += der.slice(i, i + 64) + '\n';
return ''
+ '-----BEGIN ' + type + '-----\n'
+ pem
+ '-----END ' + type + '-----\n';
};

View File

@ -19,8 +19,10 @@ var assert = require('assert');
var base58 = require('./base58'); var base58 = require('./base58');
var BN = require('bn.js'); var BN = require('bn.js');
var util = require('util'); var util = require('util');
var fs = require('fs');
var os = require('os');
var Number, Math, Date; var Number, Math, Date;
var fs, lazy; var lazy;
/** /**
* Reference to the global object. * Reference to the global object.
@ -52,9 +54,6 @@ utils.isBrowser =
(typeof process !== 'undefined' && process.browser) (typeof process !== 'undefined' && process.browser)
|| typeof window !== 'undefined'; || typeof window !== 'undefined';
if (!utils.isBrowser)
fs = require('fs');
Number = utils.global.Number; Number = utils.global.Number;
Math = utils.global.Math; Math = utils.global.Math;
Date = utils.global.Date; Date = utils.global.Date;
@ -64,9 +63,9 @@ Date = utils.global.Date;
* @const {String} * @const {String}
*/ */
try { if (os.homedir) {
utils.HOME = require('os').homedir(); utils.HOME = os.homedir();
} catch (e) { } else {
utils.HOME = process.env.HOME utils.HOME = process.env.HOME
|| process.env.USERPROFILE || process.env.USERPROFILE
|| process.env.HOMEPATH || process.env.HOMEPATH
@ -149,6 +148,17 @@ utils.isBase58 = function isBase58(obj) {
return typeof obj === 'string' && /^[1-9a-zA-Z]+$/.test(obj); return typeof obj === 'string' && /^[1-9a-zA-Z]+$/.test(obj);
}; };
/**
* Return uptime (shim for browser).
* @returns {Number}
*/
utils.uptime = function uptime() {
if (!process.uptime)
return 0;
return process.uptime();
};
/** /**
* Return hrtime (shim for browser). * Return hrtime (shim for browser).
* @param {Array} time * @param {Array} time
@ -227,18 +237,7 @@ utils.equal = function equal(a, b) {
* @returns {Promise} * @returns {Promise}
*/ */
if (utils.isBrowser) utils.nextTick = require('./nexttick');
require('../../vendor/setimmediate');
if (typeof setImmediate === 'function') {
utils.nextTick = setImmediate;
} else if (!utils.isBrowser) {
utils.nextTick = process.nextTick;
} else {
utils.nextTick = function nextTick(fn) {
setTimeout(fn, 1);
};
}
/** /**
* Reverse a hex-string (used because of * Reverse a hex-string (used because of
@ -1826,7 +1825,7 @@ utils.normalize = function normalize(path, dirname) {
utils.mkdirp = function mkdirp(path) { utils.mkdirp = function mkdirp(path) {
var i, parts, stat; var i, parts, stat;
if (!fs) if (fs.unsupported)
return; return;
path = path.replace(/\\/g, '/'); path = path.replace(/\\/g, '/');
@ -1964,3 +1963,7 @@ lazy('co', './co');
lazy('uri', './uri'); lazy('uri', './uri');
lazy('BufferReader', './reader'); lazy('BufferReader', './reader');
lazy('BufferWriter', './writer'); lazy('BufferWriter', './writer');
lazy('protobuf', './protobuf');
lazy('pem', './pem');
lazy('asn1', './asn1');
lazy('nfkd', './nfkd');

View File

@ -15,6 +15,8 @@ var Network = require('../protocol/network');
var jobs = require('./jobs'); var jobs = require('./jobs');
var Parser = require('./parser'); var Parser = require('./parser');
var Framer = require('./framer'); var Framer = require('./framer');
var os = require('os');
var cp = require('child_process');
/** /**
* A worker pool. * A worker pool.
@ -396,7 +398,7 @@ utils.inherits(Worker, EventEmitter);
Worker.prototype._init = function _init() { Worker.prototype._init = function _init() {
var self = this; var self = this;
var penv, cp; var penv;
penv = { penv = {
BCOIN_WORKER_NETWORK: Network.type BCOIN_WORKER_NETWORK: Network.type
@ -423,8 +425,6 @@ Worker.prototype._init = function _init() {
this.child.postMessage(JSON.stringify(penv)); this.child.postMessage(JSON.stringify(penv));
} else { } else {
cp = require('child_process');
this.child = cp.spawn(process.argv[0], [__dirname + '/worker.js'], { this.child = cp.spawn(process.argv[0], [__dirname + '/worker.js'], {
stdio: 'pipe', stdio: 'pipe',
env: utils.merge({}, process.env, penv) env: utils.merge({}, process.env, penv)
@ -835,13 +835,8 @@ Master.listen = function listen() {
*/ */
function getCores() { function getCores() {
var os; if (os.unsupported)
if (utils.isBrowser)
return 2; return 2;
os = require('os');
return os.cpus().length; return os.cpus().length;
} }

View File

@ -67,6 +67,16 @@
"./lib/http/rpcclient": "./browser/empty.js", "./lib/http/rpcclient": "./browser/empty.js",
"./lib/http/server": "./browser/empty.js", "./lib/http/server": "./browser/empty.js",
"./lib/http/wallet": "./browser/empty.js", "./lib/http/wallet": "./browser/empty.js",
"./lib/utils/lazy": "./browser/empty.js",
"./lib/crypto/native": "./lib/crypto/empty.js",
"./lib/utils/nfkd": "./lib/utils/nfkd-browser.js",
"./lib/utils/nexttick": "./lib/utils/nexttick-browser.js",
"./lib/crypto/backend": "./lib/crypto/backend-browser.js",
"./lib/crypto/ec": "./lib/crypto/ec-elliptic.js",
"./lib/crypto/pk": "./lib/crypto/pk-browser.js",
"./lib/db/backends": "./lib/db/backends-browser.js",
"./lib/hd/wordlist": "./lib/hd/wordlist-browser.js",
"./lib/net/tcp": "./lib/net/tcp-browser.js",
"./lib/chain/layout": "./lib/chain/layout-browser.js", "./lib/chain/layout": "./lib/chain/layout-browser.js",
"./lib/wallet/layout": "./lib/wallet/layout-browser.js", "./lib/wallet/layout": "./lib/wallet/layout-browser.js",
"fs": "./browser/empty.js", "fs": "./browser/empty.js",

9
vendor/ip.js vendored
View File

@ -26,6 +26,7 @@
* IN THE SOFTWARE. * IN THE SOFTWARE.
*/ */
var os = require('os');
var ip = exports; var ip = exports;
ip.toBuffer = function(ip, buff, offset) { ip.toBuffer = function(ip, buff, offset) {
@ -374,16 +375,10 @@ ip.loopback = function(family) {
// * undefined: First address with `ipv4` or loopback address `127.0.0.1`. // * undefined: First address with `ipv4` or loopback address `127.0.0.1`.
// //
ip.address = function(name, family) { ip.address = function(name, family) {
var os; if (os.unsupported)
try {
os = require('os');
} catch (e) {
return '127.0.0.1'; return '127.0.0.1';
}
var interfaces = os.networkInterfaces(); var interfaces = os.networkInterfaces();
var all;
// //
// Default to `ipv4` // Default to `ipv4`

View File

@ -20,11 +20,24 @@
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
*/ */
(function (global, undefined) { (function(root, undefined) {
"use strict"; "use strict";
var global;
if (typeof window !== "undefined")
global = window;
else if (typeof self !== "undefined")
global = self;
else
global = root;
if (!global)
throw new Error("Global not found.");
function install() {
if (global.setImmediate) { if (global.setImmediate) {
return; return global.setImmediate;
} }
var nextHandle = 1; // Spec says greater than zero var nextHandle = 1; // Spec says greater than zero
@ -166,10 +179,6 @@
}; };
} }
// If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.
var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);
attachTo = attachTo && attachTo.setTimeout ? attachTo : global;
// Don't get fooled by e.g. browserify environments. // Don't get fooled by e.g. browserify environments.
if ({}.toString.call(global.process) === "[object process]") { if ({}.toString.call(global.process) === "[object process]") {
// For Node.js before 0.9 // For Node.js before 0.9
@ -192,6 +201,8 @@
installSetTimeoutImplementation(); installSetTimeoutImplementation();
} }
attachTo.setImmediate = setImmediate; return setImmediate;
attachTo.clearImmediate = clearImmediate; }
}(typeof self === "undefined" ? typeof global === "undefined" ? this : global : self));
module.exports = install();
})(this);

61
vendor/unorm.js vendored
View File

@ -425,64 +425,5 @@ UChar.udata={
nfkd: nfkd nfkd: nfkd
}; };
/*globals module:true,define:true*/ module.exports = unorm;
// CommonJS
if (typeof module === "object") {
module.exports = unorm;
// AMD
} else if (typeof define === "function" && define.amd) {
define("unorm", function () {
return unorm;
});
// Global
} else {
root.unorm = unorm;
}
/***** Export as shim for String::normalize method *****/
/*
http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts#november_8_2013_draft_rev_21
21.1.3.12 String.prototype.normalize(form="NFC")
When the normalize method is called with one argument form, the following steps are taken:
1. Let O be CheckObjectCoercible(this value).
2. Let S be ToString(O).
3. ReturnIfAbrupt(S).
4. If form is not provided or undefined let form be "NFC".
5. Let f be ToString(form).
6. ReturnIfAbrupt(f).
7. If f is not one of "NFC", "NFD", "NFKC", or "NFKD", then throw a RangeError Exception.
8. Let ns be the String value is the result of normalizing S into the normalization form named by f as specified in Unicode Standard Annex #15, UnicodeNormalizatoin Forms.
9. Return ns.
The length property of the normalize method is 0.
*NOTE* The normalize function is intentionally generic; it does not require that its this value be a String object. Therefore it can be transferred to other kinds of objects for use as a method.
*/
unorm.shimApplied = false;
if (!String.prototype.normalize) {
String.prototype.normalize = function(form) {
var str = "" + this;
form = form === undefined ? "NFC" : form;
if (form === "NFC") {
return unorm.nfc(str);
} else if (form === "NFD") {
return unorm.nfd(str);
} else if (form === "NFKC") {
return unorm.nfkc(str);
} else if (form === "NFKD") {
return unorm.nfkd(str);
} else {
throw new RangeError("Invalid normalization form: " + form);
}
};
unorm.shimApplied = true;
}
}(this)); }(this));