modules: remove all conditional requires. see #105.
This commit is contained in:
parent
9f522c5ca4
commit
67a00bfe50
@ -1,3 +1,2 @@
|
||||
// Empty module for browserify.
|
||||
module.exports = null;
|
||||
throw new Error('Module not available.');
|
||||
exports.empty = true;
|
||||
|
||||
@ -10,6 +10,5 @@ exports.PaymentRequest = require('./paymentrequest');
|
||||
exports.PaymentDetails = require('./paymentdetails');
|
||||
exports.Payment = require('./payment');
|
||||
exports.PaymentACK = require('./paymentack');
|
||||
exports.asn1 = require('./asn1');
|
||||
exports.x509 = require('./x509');
|
||||
exports.pk = require('./pk');
|
||||
|
||||
@ -10,7 +10,7 @@ var assert = require('assert');
|
||||
var Output = require('../primitives/output');
|
||||
var TX = require('../primitives/tx');
|
||||
var Script = require('../script/script');
|
||||
var protobuf = require('./protobuf');
|
||||
var protobuf = require('../utils/protobuf');
|
||||
var PaymentDetails = require('./paymentdetails');
|
||||
var ProtoReader = protobuf.ProtoReader;
|
||||
var ProtoWriter = protobuf.ProtoWriter;
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var protobuf = require('./protobuf');
|
||||
var protobuf = require('../utils/protobuf');
|
||||
var Payment = require('./payment');
|
||||
var ProtoReader = protobuf.ProtoReader;
|
||||
var ProtoWriter = protobuf.ProtoWriter;
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
var assert = require('assert');
|
||||
var utils = require('../utils/utils');
|
||||
var Output = require('../primitives/output');
|
||||
var protobuf = require('./protobuf');
|
||||
var protobuf = require('../utils/protobuf');
|
||||
var ProtoReader = protobuf.ProtoReader;
|
||||
var ProtoWriter = protobuf.ProtoWriter;
|
||||
|
||||
|
||||
@ -10,8 +10,8 @@ var assert = require('assert');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var x509 = require('./x509');
|
||||
var asn1 = require('./asn1');
|
||||
var protobuf = require('./protobuf');
|
||||
var PEM = require('../utils/pem');
|
||||
var protobuf = require('../utils/protobuf');
|
||||
var PaymentDetails = require('./paymentdetails');
|
||||
var ProtoReader = protobuf.ProtoReader;
|
||||
var ProtoWriter = protobuf.ProtoWriter;
|
||||
@ -154,7 +154,7 @@ PaymentRequest.prototype.setChain = function setChain(chain) {
|
||||
for (i = 0; i < chain.length; i++) {
|
||||
cert = chain[i];
|
||||
if (typeof cert === 'string') {
|
||||
pem = asn1.fromPEM(cert);
|
||||
pem = PEM.decode(cert);
|
||||
assert(pem.type === 'certificate', 'Bad certificate PEM.');
|
||||
cert = pem.data;
|
||||
}
|
||||
|
||||
232
lib/bip70/pk.js
232
lib/bip70/pk.js
@ -6,248 +6,38 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var BN = require('bn.js');
|
||||
var asn1 = require('./asn1');
|
||||
var elliptic = require('elliptic');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var pk = require('../crypto/pk');
|
||||
|
||||
var nativeCrypto;
|
||||
|
||||
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;
|
||||
exports._verify = function verify(hash, msg, sig, key) {
|
||||
switch (key.alg) {
|
||||
case 'dsa':
|
||||
pem = pk.toPEM(key, 'public key');
|
||||
return native.verify(key.alg, hash, msg, sig, pem);
|
||||
return pk.dsa.verify(hash, msg, sig, key.data, key.params);
|
||||
case 'rsa':
|
||||
if (nativeCrypto) {
|
||||
pem = pk.toPEM(key, 'public key');
|
||||
return native.verify(key.alg, hash, msg, sig, pem);
|
||||
}
|
||||
return rsa.verify(hash, msg, sig, key.data);
|
||||
return pk.rsa.verify(hash, msg, sig, key.data);
|
||||
case 'ecdsa':
|
||||
if (!key.curve)
|
||||
throw new Error('No curve present.');
|
||||
return ecdsa.verify(key.curve, hash, msg, sig, key.data);
|
||||
return pk.ecdsa.verify(key.curve, hash, msg, sig, key.data);
|
||||
default:
|
||||
throw new Error('Unsupported algorithm.');
|
||||
}
|
||||
};
|
||||
|
||||
pk.verify = function verify(hash, msg, sig, key) {
|
||||
exports.verify = function verify(hash, msg, sig, key) {
|
||||
try {
|
||||
return pk._verify(hash, msg, sig, key);
|
||||
return exports._verify(hash, msg, sig, key);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
pk.sign = function sign(hash, msg, key) {
|
||||
var pem;
|
||||
exports.sign = function sign(hash, msg, key) {
|
||||
switch (key.alg) {
|
||||
case 'dsa':
|
||||
pem = pk.toPEM(key, 'private key');
|
||||
return native.sign(key.alg, hash, msg, pem);
|
||||
return pk.dsa.sign(hash, msg, key.data, key.params);
|
||||
case 'rsa':
|
||||
if (nativeCrypto) {
|
||||
pem = pk.toPEM(key, 'private key');
|
||||
return native.sign(key.alg, hash, msg, pem);
|
||||
}
|
||||
return rsa.sign(hash, msg, key.data);
|
||||
return pk.rsa.sign(hash, msg, key.data);
|
||||
case 'ecdsa':
|
||||
if (!key.curve)
|
||||
throw new Error('No curve present.');
|
||||
return ecdsa.sign(key.curve, hash, msg, key.data);
|
||||
return pk.ecdsa.sign(key.curve, hash, msg, key.data);
|
||||
default:
|
||||
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;
|
||||
|
||||
@ -7,7 +7,8 @@
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var asn1 = require('./asn1');
|
||||
var ASN1 = require('../utils/asn1');
|
||||
var PEM = require('../utils/pem');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var pk = require('./pk');
|
||||
@ -69,7 +70,7 @@ x509.setTrust = function setTrust(certs) {
|
||||
}
|
||||
|
||||
if (typeof cert === 'string') {
|
||||
pem = asn1.fromPEM(cert);
|
||||
pem = PEM.decode(cert);
|
||||
assert(pem.type === 'certificate', 'Must add certificates to trust.');
|
||||
cert = pem.data;
|
||||
}
|
||||
@ -137,7 +138,7 @@ x509.getCurve = function getCurve(params) {
|
||||
return;
|
||||
|
||||
try {
|
||||
oid = asn1.parseOID(params);
|
||||
oid = ASN1.parseOID(params);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
@ -147,7 +148,7 @@ x509.getCurve = function getCurve(params) {
|
||||
|
||||
x509.parse = function parse(der) {
|
||||
try {
|
||||
return asn1.parseCert(der);
|
||||
return ASN1.parseCert(der);
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
@ -189,7 +190,7 @@ x509.signSubject = function signSubject(hash, msg, key, chain) {
|
||||
assert(cert, 'Could not parse certificate.');
|
||||
|
||||
if (typeof key === 'string') {
|
||||
key = asn1.fromPEM(key);
|
||||
key = PEM.decode(key);
|
||||
if (key.alg === 'ecdsa')
|
||||
curve = x509.getCurve(key.params);
|
||||
key = {
|
||||
@ -291,8 +292,6 @@ x509.verifyChain = function verifyChain(chain) {
|
||||
return false;
|
||||
};
|
||||
|
||||
x509.asn1 = asn1;
|
||||
|
||||
function isHash(data) {
|
||||
if (typeof data === 'string')
|
||||
return utils.isHex(data) && data.length === 64;
|
||||
|
||||
73
lib/crypto/backend-browser.js
Normal file
73
lib/crypto/backend-browser.js
Normal 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
50
lib/crypto/backend.js
Normal 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;
|
||||
@ -7,7 +7,7 @@
|
||||
'use strict';
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@ -8,25 +8,13 @@
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var random = require('./random');
|
||||
var scrypt = require('./scrypt');
|
||||
var scryptAsync = require('./scrypt-async');
|
||||
var utils = require('../utils/utils');
|
||||
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 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
|
||||
@ -42,10 +30,7 @@ var crypto = exports;
|
||||
*/
|
||||
|
||||
crypto.hash = function _hash(alg, data) {
|
||||
if (!nodeCrypto)
|
||||
return new Buffer(hash[alg]().update(data).digest());
|
||||
|
||||
return nodeCrypto.createHash(alg).update(data).digest();
|
||||
return backend.hash(alg, data);
|
||||
};
|
||||
|
||||
if (native)
|
||||
@ -129,15 +114,7 @@ crypto.checksum = function checksum(data) {
|
||||
*/
|
||||
|
||||
crypto.hmac = function hmac(alg, data, salt) {
|
||||
var hmac;
|
||||
|
||||
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();
|
||||
return backend.hmac(alg, data, salt);
|
||||
};
|
||||
|
||||
if (native)
|
||||
@ -160,8 +137,8 @@ crypto.pbkdf2 = function pbkdf2(key, salt, iter, len, alg) {
|
||||
if (typeof salt === 'string')
|
||||
salt = new Buffer(salt, 'utf8');
|
||||
|
||||
if (nodeCrypto && nodeCrypto.pbkdf2Sync)
|
||||
return nodeCrypto.pbkdf2Sync(key, salt, iter, len, alg);
|
||||
if (backend.pbkdf2)
|
||||
return backend.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')
|
||||
salt = new Buffer(salt, 'utf8');
|
||||
|
||||
if (nodeCrypto && nodeCrypto.pbkdf2) {
|
||||
if (backend.pbkdf2Async) {
|
||||
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) {
|
||||
var cipher;
|
||||
|
||||
assert(Buffer.isBuffer(data));
|
||||
assert(Buffer.isBuffer(key));
|
||||
assert(Buffer.isBuffer(iv));
|
||||
assert(key.length === 32);
|
||||
assert(iv.length === 16);
|
||||
|
||||
if (!nodeCrypto)
|
||||
return aes.cbc.encrypt(data, key, iv);
|
||||
|
||||
cipher = nodeCrypto.createCipheriv('aes-256-cbc', key, iv);
|
||||
|
||||
return utils.concat(cipher.update(data), cipher.final());
|
||||
return backend.encipher(data, key, iv);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -351,31 +321,7 @@ crypto.decipher = function decipher(data, key, iv) {
|
||||
assert(Buffer.isBuffer(iv));
|
||||
assert(key.length === 32);
|
||||
assert(iv.length === 16);
|
||||
try {
|
||||
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());
|
||||
return backend.decipher(data, key, iv);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -661,7 +607,19 @@ if (native)
|
||||
* @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.
|
||||
@ -673,17 +631,10 @@ crypto.randomBytes = random.randomBytes;
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
crypto.randomRange = random.randomRange;
|
||||
|
||||
/**
|
||||
* Generate a random uint32.
|
||||
* Probably more cryptographically sound than
|
||||
* `Math.random()`.
|
||||
* @function
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
crypto.randomInt = random.randomInt;
|
||||
crypto.randomRange = function randomRange(min, max) {
|
||||
var num = crypto.randomInt();
|
||||
return Math.floor((num / 0x100000000) * (max - min) + min);
|
||||
};
|
||||
|
||||
/*
|
||||
* Expose other objects.
|
||||
@ -694,3 +645,4 @@ lazy('chachapoly', './chachapoly');
|
||||
lazy('ec', './ec');
|
||||
lazy('schnorr', './schnorr');
|
||||
lazy('siphash', './siphash');
|
||||
lazy('pk', './pk');
|
||||
|
||||
347
lib/crypto/ec-elliptic.js
Normal file
347
lib/crypto/ec-elliptic.js
Normal 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
263
lib/crypto/ec-secp256k1.js
Normal 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;
|
||||
};
|
||||
519
lib/crypto/ec.js
519
lib/crypto/ec.js
@ -1,524 +1,21 @@
|
||||
/*!
|
||||
* ec.js - ecdsa wrapper for secp256k1 and 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 elliptic = require('elliptic');
|
||||
var BN = require('bn.js');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('./crypto');
|
||||
var assert = require('assert');
|
||||
var secp256k1;
|
||||
|
||||
try {
|
||||
if (+process.env.BCOIN_USE_ELLIPTIC !== 1)
|
||||
if (+process.env.BCOIN_USE_ELLIPTIC !== 1) {
|
||||
try {
|
||||
secp256k1 = require('secp256k1');
|
||||
} catch (e) {
|
||||
;
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
module.exports = secp256k1
|
||||
? require('./ec-secp256k1')
|
||||
: require('./ec-elliptic');
|
||||
|
||||
187
lib/crypto/pk-browser.js
Normal file
187
lib/crypto/pk-browser.js
Normal 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
142
lib/crypto/pk.js
Normal 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;
|
||||
@ -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;
|
||||
@ -10,9 +10,11 @@ var BN = require('bn.js');
|
||||
var elliptic = require('elliptic');
|
||||
var Signature = require('elliptic/lib/elliptic/ec/signature');
|
||||
var hmacDRBG = require('elliptic/lib/elliptic/hmac-drbg');
|
||||
var curves = elliptic.curves;
|
||||
var curve = elliptic.ec('secp256k1').curve;
|
||||
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
|
||||
@ -335,7 +337,7 @@ schnorr.drbg = function drbg(msg, priv, data) {
|
||||
pers = toArray(kdata.slice(64));
|
||||
|
||||
return new hmacDRBG({
|
||||
hash: curves.secp256k1.hash,
|
||||
hash: hash,
|
||||
entropy: prv,
|
||||
nonce: msg,
|
||||
pers: pers
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('./crypto');
|
||||
var native = require('../utils/native');
|
||||
var native = require('../utils/native').binding;
|
||||
var U32Array = typeof Uint32Array === 'function' ? Uint32Array : Array;
|
||||
|
||||
/**
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
'use strict';
|
||||
|
||||
var crypto = require('./crypto');
|
||||
var native = require('../utils/native');
|
||||
var native = require('../utils/native').binding;
|
||||
var U32Array = typeof Uint32Array === 'function' ? Uint32Array : Array;
|
||||
|
||||
/**
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var native = require('../utils/native');
|
||||
var native = require('../utils/native').binding;
|
||||
|
||||
/**
|
||||
* Javascript siphash implementation. Used for compact block relay.
|
||||
|
||||
16
lib/db/backends-browser.js
Normal file
16
lib/db/backends-browser.js
Normal 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
18
lib/db/backends.js
Normal 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.');
|
||||
}
|
||||
};
|
||||
@ -1,7 +1,5 @@
|
||||
/**
|
||||
* global ldb tracker
|
||||
* @module ldb
|
||||
* @license
|
||||
* ldb.js - database backend for bcoin
|
||||
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
@ -9,9 +7,10 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var LowlevelUp = require('./lowlevelup');
|
||||
var utils = require('../utils/utils');
|
||||
var assert = require('assert');
|
||||
var backends = require('./backends');
|
||||
|
||||
/**
|
||||
* @param {Object} options
|
||||
@ -28,8 +27,8 @@ var assert = require('assert');
|
||||
* @returns {LowlevelUp}
|
||||
*/
|
||||
|
||||
function ldb(options) {
|
||||
var target = ldb.getTarget(options);
|
||||
function LDB(options) {
|
||||
var target = LDB.getTarget(options);
|
||||
|
||||
if (target.backend !== 'rbt')
|
||||
utils.mkdir(target.location, true);
|
||||
@ -66,7 +65,7 @@ function ldb(options) {
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ldb.getBackend = function getBackend(db) {
|
||||
LDB.getBackend = function getBackend(db) {
|
||||
var name, ext;
|
||||
|
||||
if (!db)
|
||||
@ -111,17 +110,10 @@ ldb.getBackend = function getBackend(db) {
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ldb.getTarget = function getTarget(options) {
|
||||
var backend = ldb.getBackend(options.db);
|
||||
LDB.getTarget = function getTarget(options) {
|
||||
var backend = LDB.getBackend(options.db);
|
||||
var location = options.location;
|
||||
var db;
|
||||
|
||||
if (backend.name === 'rbt')
|
||||
db = require('./rbt');
|
||||
else if (utils.isBrowser)
|
||||
db = require('./level');
|
||||
else
|
||||
db = require(backend.name);
|
||||
var db = backends.get(backend.name);
|
||||
|
||||
if (typeof location !== 'string') {
|
||||
assert(backend.name === 'rbt', 'Location required.');
|
||||
@ -139,4 +131,4 @@ ldb.getTarget = function getTarget(options) {
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = ldb;
|
||||
module.exports = LDB;
|
||||
|
||||
@ -13,7 +13,8 @@ var constants = require('../protocol/constants');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var HD = require('./hd');
|
||||
var unorm;
|
||||
var wordlist = require('./wordlist');
|
||||
var nfkd = require('../utils/nfkd');
|
||||
|
||||
/**
|
||||
* HD Mnemonic
|
||||
@ -368,22 +369,7 @@ Mnemonic.getLanguage = function getLanguage(word) {
|
||||
*/
|
||||
|
||||
Mnemonic.getWordlist = function getWordlist(language) {
|
||||
switch (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);
|
||||
}
|
||||
return wordlist.get(language);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -523,20 +509,6 @@ Mnemonic.isMnemonic = function isMnemonic(obj) {
|
||||
&& 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
|
||||
*/
|
||||
|
||||
28
lib/hd/wordlist-browser.js
Normal file
28
lib/hd/wordlist-browser.js
Normal 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
26
lib/hd/wordlist.js
Normal 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
17
lib/hd/words/index.js
Normal 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');
|
||||
@ -7,16 +7,10 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
|
||||
if (!utils.isBrowser) {
|
||||
exports.request = require('./request');
|
||||
exports.Client = require('./client');
|
||||
exports.RPCClient = require('./rpcclient');
|
||||
exports.Wallet = require('./wallet');
|
||||
exports.Base = require('./base');
|
||||
exports.RPC = require('./rpc');
|
||||
exports.Server = require('./server');
|
||||
} else {
|
||||
exports.RPC = require('./rpc');
|
||||
}
|
||||
exports.request = require('./request');
|
||||
exports.Client = require('./client');
|
||||
exports.RPCClient = require('./rpcclient');
|
||||
exports.Wallet = require('./wallet');
|
||||
exports.Base = require('./base');
|
||||
exports.RPC = require('./rpc');
|
||||
exports.Server = require('./server');
|
||||
|
||||
@ -31,13 +31,7 @@ var BufferReader = require('../utils/reader');
|
||||
var TX = require('../primitives/tx');
|
||||
var Logger = require('../node/logger');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var fs;
|
||||
|
||||
try {
|
||||
fs = require('fs');
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
var fs = require('fs');
|
||||
|
||||
function RPC(node) {
|
||||
if (!(this instanceof RPC))
|
||||
@ -2794,7 +2788,7 @@ RPC.prototype.dumpwallet = co(function* dumpwallet(args) {
|
||||
|
||||
out = out.join('\n');
|
||||
|
||||
if (!fs)
|
||||
if (fs.unsupported)
|
||||
return out;
|
||||
|
||||
yield writeFile(file, out);
|
||||
@ -3216,7 +3210,7 @@ RPC.prototype.importwallet = co(function* importwallet(args) {
|
||||
|
||||
file = toString(args[0]);
|
||||
|
||||
if (!fs)
|
||||
if (fs.unsupported)
|
||||
throw new RPCError('FS not available.');
|
||||
|
||||
data = yield readFile(file, 'utf8');
|
||||
|
||||
@ -7,7 +7,9 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var tcp = require('./tcp');
|
||||
var utils = require('../utils/utils');
|
||||
var co = require('../utils/co');
|
||||
var Parser = require('./parser');
|
||||
@ -15,7 +17,6 @@ var Framer = require('./framer');
|
||||
var packets = require('./packets');
|
||||
var packetTypes = packets.types;
|
||||
var NetworkAddress = require('../primitives/netaddress');
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var InvItem = require('../primitives/invitem');
|
||||
var Locker = require('../utils/locker');
|
||||
@ -249,21 +250,15 @@ Peer.prototype._init = function init() {
|
||||
|
||||
Peer.prototype.connect = function connect(port, host) {
|
||||
var self = this;
|
||||
var socket, proxy, net;
|
||||
var proxy = this.pool.proxyServer;
|
||||
var socket;
|
||||
|
||||
assert(!this.socket);
|
||||
|
||||
if (this.createSocket) {
|
||||
socket = this.createSocket(port, host);
|
||||
} else {
|
||||
if (utils.isBrowser) {
|
||||
proxy = require('./proxysocket');
|
||||
socket = proxy.connect(this.pool.proxyServer, port, host);
|
||||
} else {
|
||||
net = require('net');
|
||||
socket = net.connect(port, host);
|
||||
}
|
||||
}
|
||||
if (this.createSocket)
|
||||
socket = this.createSocket(port, host, proxy);
|
||||
else
|
||||
socket = tcp.connect(port, host, proxy);
|
||||
|
||||
this.logger.debug('Connecting to %s.', this.hostname);
|
||||
|
||||
|
||||
@ -7,12 +7,12 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var AsyncObject = require('../utils/async');
|
||||
var assert = require('assert');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var AsyncObject = require('../utils/async');
|
||||
var utils = require('../utils/utils');
|
||||
var IP = require('../utils/ip');
|
||||
var co = require('../utils/co');
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var VerifyError = require('../utils/errors').VerifyError;
|
||||
var NetworkAddress = require('../primitives/netaddress');
|
||||
@ -27,6 +27,8 @@ var Network = require('../protocol/network');
|
||||
var time = require('./timedata');
|
||||
var Peer = require('./peer');
|
||||
var TX = require('../primitives/tx');
|
||||
var tcp = require('./tcp');
|
||||
var request = require('../http/request');
|
||||
|
||||
/**
|
||||
* A pool of peers for handling all network activity.
|
||||
@ -396,7 +398,6 @@ Pool.prototype.connect = function connect() {
|
||||
|
||||
Pool.prototype.listen = function listen() {
|
||||
var self = this;
|
||||
var net;
|
||||
|
||||
if (this.server)
|
||||
return Promise.resolve();
|
||||
@ -404,10 +405,9 @@ Pool.prototype.listen = function listen() {
|
||||
if (this.createServer) {
|
||||
this.server = this.createServer();
|
||||
} else {
|
||||
if (utils.isBrowser)
|
||||
if (!tcp.Server)
|
||||
return;
|
||||
net = require('net');
|
||||
this.server = new net.Server();
|
||||
this.server = new tcp.Server();
|
||||
}
|
||||
|
||||
this.server.on('connection', function(socket) {
|
||||
@ -1871,13 +1871,11 @@ Pool.prototype.isIgnored = function isIgnored(addr) {
|
||||
*/
|
||||
|
||||
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.');
|
||||
|
||||
request = require('../http/request');
|
||||
|
||||
try {
|
||||
res = yield request.promise({
|
||||
method: 'GET',
|
||||
@ -1903,13 +1901,11 @@ Pool.prototype.getIP = co(function* getIP() {
|
||||
*/
|
||||
|
||||
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.');
|
||||
|
||||
request = require('../http/request');
|
||||
|
||||
res = yield request.promise({
|
||||
method: 'GET',
|
||||
uri: 'http://checkip.dyndns.org',
|
||||
|
||||
16
lib/net/tcp-browser.js
Normal file
16
lib/net/tcp-browser.js
Normal 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
16
lib/net/tcp.js
Normal 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;
|
||||
@ -9,10 +9,7 @@
|
||||
var Network = require('../protocol/network');
|
||||
var utils = require('../utils/utils');
|
||||
var assert = require('assert');
|
||||
var fs;
|
||||
|
||||
if (!utils.isBrowser)
|
||||
fs = require('fs');
|
||||
var fs = require('fs');
|
||||
|
||||
/**
|
||||
* @exports config
|
||||
@ -660,7 +657,7 @@ function boolpath(value, prefix, dirname) {
|
||||
}
|
||||
|
||||
function file(value, prefix, dirname, enc) {
|
||||
if (!fs)
|
||||
if (fs.unsupported)
|
||||
return null;
|
||||
|
||||
value = path(value, prefix, dirname);
|
||||
@ -684,7 +681,7 @@ function resolve(a, b) {
|
||||
}
|
||||
|
||||
function readFile(file) {
|
||||
if (!fs)
|
||||
if (fs.unsupported)
|
||||
return '';
|
||||
|
||||
if (!file)
|
||||
|
||||
@ -17,13 +17,7 @@ var Mempool = require('../mempool/mempool');
|
||||
var Pool = require('../net/pool');
|
||||
var Miner = require('../miner/miner');
|
||||
var WalletDB = require('../wallet/walletdb');
|
||||
var HTTPServer;
|
||||
|
||||
try {
|
||||
HTTPServer = require('../http/server');
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
var HTTPServer = require('../http/server');
|
||||
|
||||
/**
|
||||
* Create a fullnode complete with a chain,
|
||||
@ -155,7 +149,7 @@ function FullNode(options) {
|
||||
});
|
||||
|
||||
// HTTP needs access to the node.
|
||||
if (!utils.isBrowser) {
|
||||
if (!HTTPServer.unsupported) {
|
||||
this.http = new HTTPServer({
|
||||
network: this.network,
|
||||
logger: this.logger,
|
||||
|
||||
@ -8,10 +8,7 @@
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var assert = require('assert');
|
||||
var fs;
|
||||
|
||||
if (!utils.isBrowser)
|
||||
fs = require('fs');
|
||||
var fs = require('fs');
|
||||
|
||||
/**
|
||||
* Basic stdout and file logger.
|
||||
@ -287,9 +284,12 @@ Logger.prototype.writeStream = function writeStream(level, args) {
|
||||
if (!this.stream) {
|
||||
if (!this.file)
|
||||
return;
|
||||
if (utils.isBrowser)
|
||||
|
||||
if (fs.unsupported)
|
||||
return;
|
||||
|
||||
utils.mkdir(this.file, true);
|
||||
|
||||
this.stream = fs.createWriteStream(this.file, { flags: 'a' });
|
||||
this.stream.on('error', function() {});
|
||||
}
|
||||
|
||||
@ -13,13 +13,7 @@ var Node = require('./node');
|
||||
var Chain = require('../chain/chain');
|
||||
var Pool = require('../net/pool');
|
||||
var WalletDB = require('../wallet/walletdb');
|
||||
var HTTPServer;
|
||||
|
||||
try {
|
||||
HTTPServer = require('../http/server');
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
var HTTPServer = require('../http/server');
|
||||
|
||||
/**
|
||||
* Create an spv node which only maintains
|
||||
@ -95,7 +89,7 @@ function SPVNode(options) {
|
||||
verify: true
|
||||
});
|
||||
|
||||
if (!utils.isBrowser) {
|
||||
if (!HTTPServer.unsupported) {
|
||||
this.http = new HTTPServer({
|
||||
network: this.network,
|
||||
logger: this.logger,
|
||||
|
||||
@ -31,9 +31,9 @@
|
||||
|
||||
var assert = require('assert');
|
||||
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 primitive = (tag & 0x20) === 0;
|
||||
var oct;
|
||||
@ -53,11 +53,11 @@ asn1.parseTag = function parseTag(p) {
|
||||
return {
|
||||
primitive: primitive,
|
||||
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 num, i, j;
|
||||
|
||||
@ -85,52 +85,52 @@ asn1.parseLen = function parseLen(p, primitive) {
|
||||
return len;
|
||||
};
|
||||
|
||||
asn1.parseCert = function parseCert(data) {
|
||||
ASN1.parseCert = function parseCert(data) {
|
||||
var d = BufferReader(data);
|
||||
var p;
|
||||
|
||||
d.start();
|
||||
|
||||
p = BufferReader(asn1.parseSeq(d));
|
||||
p = BufferReader(ASN1.parseSeq(d));
|
||||
|
||||
return {
|
||||
tbs: asn1.parseTBS(p),
|
||||
sigAlg: asn1.parseAlgIdent(p),
|
||||
sig: asn1.parseBitstr(p),
|
||||
tbs: ASN1.parseTBS(p),
|
||||
sigAlg: ASN1.parseAlgIdent(p),
|
||||
sig: ASN1.parseBitstr(p),
|
||||
raw: d.endData(true)
|
||||
};
|
||||
};
|
||||
|
||||
asn1.parseTBS = function parseTBS(data) {
|
||||
ASN1.parseTBS = function parseTBS(data) {
|
||||
var d = BufferReader(data);
|
||||
var p;
|
||||
|
||||
d.start();
|
||||
|
||||
p = BufferReader(asn1.parseSeq(d));
|
||||
p = BufferReader(ASN1.parseSeq(d));
|
||||
|
||||
return {
|
||||
version: asn1.parseExplicitInt(p, 0, true),
|
||||
serial: asn1.parseInt(p),
|
||||
sig: asn1.parseAlgIdent(p),
|
||||
issuer: asn1.parseName(p),
|
||||
validity: asn1.parseValidity(p),
|
||||
subject: asn1.parseName(p),
|
||||
pubkey: asn1.parsePubkey(p),
|
||||
version: ASN1.parseExplicitInt(p, 0, true),
|
||||
serial: ASN1.parseInt(p),
|
||||
sig: ASN1.parseAlgIdent(p),
|
||||
issuer: ASN1.parseName(p),
|
||||
validity: ASN1.parseValidity(p),
|
||||
subject: ASN1.parseName(p),
|
||||
pubkey: ASN1.parsePubkey(p),
|
||||
raw: d.endData(true)
|
||||
};
|
||||
};
|
||||
|
||||
asn1.parseSeq = function parseSeq(data) {
|
||||
ASN1.parseSeq = function parseSeq(data) {
|
||||
var p = BufferReader(data);
|
||||
var tag = asn1.parseTag(p);
|
||||
var tag = ASN1.parseTag(p);
|
||||
assert.equal(tag.tag, 0x10); // seq
|
||||
return p.readBytes(tag.len, true);
|
||||
};
|
||||
|
||||
asn1.parseInt = function parseInt(data, readNum) {
|
||||
ASN1.parseInt = function parseInt(data, readNum) {
|
||||
var p = BufferReader(data);
|
||||
var tag = asn1.parseTag(p);
|
||||
var tag = ASN1.parseTag(p);
|
||||
var num;
|
||||
|
||||
assert.equal(tag.tag, 0x02); // int
|
||||
@ -143,30 +143,30 @@ asn1.parseInt = function parseInt(data, readNum) {
|
||||
return num;
|
||||
};
|
||||
|
||||
asn1.parseExplicitInt = function parseExplicitInt(data, i, readNum) {
|
||||
ASN1.parseExplicitInt = function parseExplicitInt(data, i, readNum) {
|
||||
var p = BufferReader(data);
|
||||
var off = p.offset;
|
||||
var tag = asn1.parseTag(p);
|
||||
var tag = ASN1.parseTag(p);
|
||||
if (tag.tag !== i) {
|
||||
p.seek(-(p.offset - off));
|
||||
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 tag = asn1.parseTag(p);
|
||||
var tag = ASN1.parseTag(p);
|
||||
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 tag = asn1.parseTag(p);
|
||||
var tag = ASN1.parseTag(p);
|
||||
switch (tag.tag) {
|
||||
case 0x03: // bitstr
|
||||
return asn1.alignBitstr(p.readBytes(tag.len, true));
|
||||
return ASN1.alignBitstr(p.readBytes(tag.len, true));
|
||||
case 0x04: // octstr
|
||||
case 0x12: // numstr
|
||||
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 bits = (data.length - 1) * 8 - padding;
|
||||
var buf = data.slice(1);
|
||||
@ -207,48 +207,48 @@ asn1.alignBitstr = function(data) {
|
||||
return out;
|
||||
};
|
||||
|
||||
asn1.parsePubkey = function parsePubkey(data) {
|
||||
ASN1.parsePubkey = function parsePubkey(data) {
|
||||
var p = BufferReader(data);
|
||||
p = BufferReader(asn1.parseSeq(p));
|
||||
p = BufferReader(ASN1.parseSeq(p));
|
||||
return {
|
||||
alg: asn1.parseAlgIdent(p),
|
||||
pubkey: asn1.parseBitstr(p)
|
||||
alg: ASN1.parseAlgIdent(p),
|
||||
pubkey: ASN1.parseBitstr(p)
|
||||
};
|
||||
};
|
||||
|
||||
asn1.parseName = function parseName(data) {
|
||||
ASN1.parseName = function parseName(data) {
|
||||
var p = BufferReader(data);
|
||||
var values = [];
|
||||
var tag;
|
||||
|
||||
p = BufferReader(asn1.parseSeq(p));
|
||||
p = BufferReader(ASN1.parseSeq(p));
|
||||
|
||||
while (p.left()) {
|
||||
tag = asn1.parseTag(p);
|
||||
tag = ASN1.parseTag(p);
|
||||
assert.equal(tag.tag, 0x11); // set
|
||||
tag = asn1.parseTag(p);
|
||||
tag = ASN1.parseTag(p);
|
||||
assert.equal(tag.tag, 0x10); // seq
|
||||
values.push({
|
||||
type: asn1.parseOID(p),
|
||||
value: asn1.parseString(p)
|
||||
type: ASN1.parseOID(p),
|
||||
value: ASN1.parseString(p)
|
||||
});
|
||||
}
|
||||
|
||||
return values;
|
||||
};
|
||||
|
||||
asn1.parseValidity = function parseValidity(data) {
|
||||
ASN1.parseValidity = function parseValidity(data) {
|
||||
var p = BufferReader(data);
|
||||
p = BufferReader(asn1.parseSeq(p));
|
||||
p = BufferReader(ASN1.parseSeq(p));
|
||||
return {
|
||||
notBefore: asn1.parseTime(p),
|
||||
notAfter: asn1.parseTime(p)
|
||||
notBefore: ASN1.parseTime(p),
|
||||
notAfter: ASN1.parseTime(p)
|
||||
};
|
||||
};
|
||||
|
||||
asn1.parseTime = function parseTime(data) {
|
||||
ASN1.parseTime = function parseTime(data) {
|
||||
var p = BufferReader(data);
|
||||
var tag = asn1.parseTag(p);
|
||||
var tag = ASN1.parseTag(p);
|
||||
var str = p.readString('ascii', tag.len);
|
||||
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;
|
||||
};
|
||||
|
||||
asn1.parseOID = function parseOID(data) {
|
||||
ASN1.parseOID = function parseOID(data) {
|
||||
var p = BufferReader(data);
|
||||
var tag = asn1.parseTag(p);
|
||||
var tag = ASN1.parseTag(p);
|
||||
var ids = [];
|
||||
var ident = 0;
|
||||
var subident = 0;
|
||||
@ -314,17 +314,17 @@ asn1.parseOID = function parseOID(data) {
|
||||
return result.join('.');
|
||||
};
|
||||
|
||||
asn1.parseAlgIdent = function parseAlgIdent(data) {
|
||||
ASN1.parseAlgIdent = function parseAlgIdent(data) {
|
||||
var p = BufferReader(data);
|
||||
var params = null;
|
||||
var alg;
|
||||
|
||||
p = BufferReader(asn1.parseSeq(p));
|
||||
p = BufferReader(ASN1.parseSeq(p));
|
||||
|
||||
alg = asn1.parseOID(p);
|
||||
alg = ASN1.parseOID(p);
|
||||
|
||||
if (p.left() > 0) {
|
||||
params = p.readBytes(asn1.parseTag(p).len, true);
|
||||
params = p.readBytes(ASN1.parseTag(p).len, true);
|
||||
if (params.length === 0)
|
||||
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);
|
||||
p = BufferReader(asn1.parseSeq(p));
|
||||
p = BufferReader(ASN1.parseSeq(p));
|
||||
return {
|
||||
modulus: asn1.parseInt(p),
|
||||
publicExponent: asn1.parseInt(p)
|
||||
modulus: ASN1.parseInt(p),
|
||||
publicExponent: ASN1.parseInt(p)
|
||||
};
|
||||
};
|
||||
|
||||
asn1.parseRSAPrivate = function parseRSAPrivate(data) {
|
||||
ASN1.parseRSAPrivate = function parseRSAPrivate(data) {
|
||||
var p = BufferReader(data);
|
||||
p = BufferReader(asn1.parseSeq(p));
|
||||
p = BufferReader(ASN1.parseSeq(p));
|
||||
return {
|
||||
version: asn1.parseInt(p, true),
|
||||
modulus: asn1.parseInt(p),
|
||||
publicExponent: asn1.parseInt(p),
|
||||
privateExponent: asn1.parseInt(p),
|
||||
prime1: asn1.parseInt(p),
|
||||
prime2: asn1.parseInt(p),
|
||||
exponent1: asn1.parseInt(p),
|
||||
exponent2: asn1.parseInt(p),
|
||||
coefficient: asn1.parseInt(p)
|
||||
version: ASN1.parseInt(p, true),
|
||||
modulus: ASN1.parseInt(p),
|
||||
publicExponent: ASN1.parseInt(p),
|
||||
privateExponent: ASN1.parseInt(p),
|
||||
prime1: ASN1.parseInt(p),
|
||||
prime2: ASN1.parseInt(p),
|
||||
exponent1: ASN1.parseInt(p),
|
||||
exponent2: 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';
|
||||
};
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var native = require('./native');
|
||||
var native = require('./native').binding;
|
||||
var assert = require('assert');
|
||||
|
||||
/*
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var native = require('./native');
|
||||
var native = require('./native').binding;
|
||||
|
||||
/**
|
||||
* Murmur3 hash.
|
||||
|
||||
@ -6,15 +6,11 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var isBrowser =
|
||||
(typeof process !== 'undefined' && process.browser)
|
||||
|| typeof window !== 'undefined';
|
||||
exports.binding = null;
|
||||
|
||||
module.exports = null;
|
||||
|
||||
if (!isBrowser && +process.env.BCOIN_NO_NATIVE !== 1) {
|
||||
if (+process.env.BCOIN_NO_NATIVE !== 1) {
|
||||
try {
|
||||
module.exports = require('bcoin-native');
|
||||
exports.binding = require('bcoin-native');
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
|
||||
7
lib/utils/nexttick-browser.js
Normal file
7
lib/utils/nexttick-browser.js
Normal 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
9
lib/utils/nexttick.js
Normal 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
20
lib/utils/nfkd-browser.js
Normal 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
23
lib/utils/nfkd.js
Normal 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
100
lib/utils/pem.js
Normal 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';
|
||||
};
|
||||
@ -19,8 +19,10 @@ var assert = require('assert');
|
||||
var base58 = require('./base58');
|
||||
var BN = require('bn.js');
|
||||
var util = require('util');
|
||||
var fs = require('fs');
|
||||
var os = require('os');
|
||||
var Number, Math, Date;
|
||||
var fs, lazy;
|
||||
var lazy;
|
||||
|
||||
/**
|
||||
* Reference to the global object.
|
||||
@ -52,9 +54,6 @@ utils.isBrowser =
|
||||
(typeof process !== 'undefined' && process.browser)
|
||||
|| typeof window !== 'undefined';
|
||||
|
||||
if (!utils.isBrowser)
|
||||
fs = require('fs');
|
||||
|
||||
Number = utils.global.Number;
|
||||
Math = utils.global.Math;
|
||||
Date = utils.global.Date;
|
||||
@ -64,9 +63,9 @@ Date = utils.global.Date;
|
||||
* @const {String}
|
||||
*/
|
||||
|
||||
try {
|
||||
utils.HOME = require('os').homedir();
|
||||
} catch (e) {
|
||||
if (os.homedir) {
|
||||
utils.HOME = os.homedir();
|
||||
} else {
|
||||
utils.HOME = process.env.HOME
|
||||
|| process.env.USERPROFILE
|
||||
|| process.env.HOMEPATH
|
||||
@ -149,6 +148,17 @@ utils.isBase58 = function isBase58(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).
|
||||
* @param {Array} time
|
||||
@ -227,18 +237,7 @@ utils.equal = function equal(a, b) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
if (utils.isBrowser)
|
||||
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);
|
||||
};
|
||||
}
|
||||
utils.nextTick = require('./nexttick');
|
||||
|
||||
/**
|
||||
* Reverse a hex-string (used because of
|
||||
@ -1826,7 +1825,7 @@ utils.normalize = function normalize(path, dirname) {
|
||||
utils.mkdirp = function mkdirp(path) {
|
||||
var i, parts, stat;
|
||||
|
||||
if (!fs)
|
||||
if (fs.unsupported)
|
||||
return;
|
||||
|
||||
path = path.replace(/\\/g, '/');
|
||||
@ -1964,3 +1963,7 @@ lazy('co', './co');
|
||||
lazy('uri', './uri');
|
||||
lazy('BufferReader', './reader');
|
||||
lazy('BufferWriter', './writer');
|
||||
lazy('protobuf', './protobuf');
|
||||
lazy('pem', './pem');
|
||||
lazy('asn1', './asn1');
|
||||
lazy('nfkd', './nfkd');
|
||||
|
||||
@ -15,6 +15,8 @@ var Network = require('../protocol/network');
|
||||
var jobs = require('./jobs');
|
||||
var Parser = require('./parser');
|
||||
var Framer = require('./framer');
|
||||
var os = require('os');
|
||||
var cp = require('child_process');
|
||||
|
||||
/**
|
||||
* A worker pool.
|
||||
@ -396,7 +398,7 @@ utils.inherits(Worker, EventEmitter);
|
||||
|
||||
Worker.prototype._init = function _init() {
|
||||
var self = this;
|
||||
var penv, cp;
|
||||
var penv;
|
||||
|
||||
penv = {
|
||||
BCOIN_WORKER_NETWORK: Network.type
|
||||
@ -423,8 +425,6 @@ Worker.prototype._init = function _init() {
|
||||
|
||||
this.child.postMessage(JSON.stringify(penv));
|
||||
} else {
|
||||
cp = require('child_process');
|
||||
|
||||
this.child = cp.spawn(process.argv[0], [__dirname + '/worker.js'], {
|
||||
stdio: 'pipe',
|
||||
env: utils.merge({}, process.env, penv)
|
||||
@ -835,13 +835,8 @@ Master.listen = function listen() {
|
||||
*/
|
||||
|
||||
function getCores() {
|
||||
var os;
|
||||
|
||||
if (utils.isBrowser)
|
||||
if (os.unsupported)
|
||||
return 2;
|
||||
|
||||
os = require('os');
|
||||
|
||||
return os.cpus().length;
|
||||
}
|
||||
|
||||
|
||||
10
package.json
10
package.json
@ -67,6 +67,16 @@
|
||||
"./lib/http/rpcclient": "./browser/empty.js",
|
||||
"./lib/http/server": "./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/wallet/layout": "./lib/wallet/layout-browser.js",
|
||||
"fs": "./browser/empty.js",
|
||||
|
||||
9
vendor/ip.js
vendored
9
vendor/ip.js
vendored
@ -26,6 +26,7 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
var os = require('os');
|
||||
var ip = exports;
|
||||
|
||||
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`.
|
||||
//
|
||||
ip.address = function(name, family) {
|
||||
var os;
|
||||
|
||||
try {
|
||||
os = require('os');
|
||||
} catch (e) {
|
||||
if (os.unsupported)
|
||||
return '127.0.0.1';
|
||||
}
|
||||
|
||||
var interfaces = os.networkInterfaces();
|
||||
var all;
|
||||
|
||||
//
|
||||
// Default to `ipv4`
|
||||
|
||||
31
vendor/setimmediate.js
vendored
31
vendor/setimmediate.js
vendored
@ -20,11 +20,24 @@
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
(function (global, undefined) {
|
||||
"use strict";
|
||||
(function(root, undefined) {
|
||||
"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) {
|
||||
return;
|
||||
return global.setImmediate;
|
||||
}
|
||||
|
||||
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.
|
||||
if ({}.toString.call(global.process) === "[object process]") {
|
||||
// For Node.js before 0.9
|
||||
@ -192,6 +201,8 @@
|
||||
installSetTimeoutImplementation();
|
||||
}
|
||||
|
||||
attachTo.setImmediate = setImmediate;
|
||||
attachTo.clearImmediate = clearImmediate;
|
||||
}(typeof self === "undefined" ? typeof global === "undefined" ? this : global : self));
|
||||
return setImmediate;
|
||||
}
|
||||
|
||||
module.exports = install();
|
||||
})(this);
|
||||
|
||||
61
vendor/unorm.js
vendored
61
vendor/unorm.js
vendored
@ -425,64 +425,5 @@ UChar.udata={
|
||||
nfkd: nfkd
|
||||
};
|
||||
|
||||
/*globals module:true,define:true*/
|
||||
|
||||
// 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;
|
||||
}
|
||||
module.exports = unorm;
|
||||
}(this));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user