bcoin: use bcrypto. remove crypto module.

This commit is contained in:
Christopher Jeffrey 2017-10-25 20:07:22 -07:00
parent c84afad1f6
commit 636d66a5c7
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
101 changed files with 165 additions and 6632 deletions

View File

@ -1,7 +1,7 @@
'use strict';
const Address = require('../lib/primitives/address');
const random = require('../lib/crypto/random');
const random = require('bcrypto/lib/random');
const bench = require('./bench');
const addrs = [];

View File

@ -1,8 +1,8 @@
'use strict';
const ChaCha20 = require('../lib/crypto/chacha20');
const Poly1305 = require('../lib/crypto/poly1305');
const digest = require('../lib/crypto/digest');
const ChaCha20 = require('bcrypto/lib/chacha20');
const Poly1305 = require('bcrypto/lib/poly1305');
const digest = require('bcrypto/lib/digest');
const bench = require('./bench');
console.log('note: rate measured in kb/s');

View File

@ -1,8 +1,8 @@
'use strict';
const assert = require('assert');
const merkle = require('../lib/crypto/merkle');
const random = require('../lib/crypto/random');
const merkle = require('bcrypto/lib/merkle');
const random = require('bcrypto/lib/random');
const bench = require('./bench');
const leaves = [];

View File

@ -1,6 +1,6 @@
'use strict';
const random = require('../lib/crypto/random');
const random = require('bcrypto/lib/random');
const Script = require('../lib/script/script');
const bench = require('./bench');

View File

@ -5,7 +5,7 @@ const TX = require('../lib/primitives/tx');
const Script = require('../lib/script/script');
const MTX = require('../lib/primitives/mtx');
const encoding = require('../lib/utils/encoding');
const random = require('../lib/crypto/random');
const random = require('bcrypto/lib/random');
const common = require('../test/util/common');
const bench = require('./bench');

View File

@ -1,7 +1,7 @@
'use strict';
const bench = require('./bench');
const random = require('../lib/crypto/random');
const random = require('bcrypto/lib/random');
const WalletDB = require('../lib/wallet/walletdb');
const MTX = require('../lib/primitives/mtx');
const Outpoint = require('../lib/primitives/outpoint');

View File

@ -5,7 +5,7 @@ const net = require('net');
const EventEmitter = require('events');
const bsock = require('bsock');
const util = require('../lib/utils/util');
const digest = require('../lib/crypto/digest');
const digest = require('bcrypto/lib/digest');
const IP = require('../lib/utils/ip');
const BufferWriter = require('../lib/utils/writer');

View File

@ -165,10 +165,7 @@ bcoin.coins = require('./coins');
bcoin.coinview = require('./coins/coinview');
// Crypto
bcoin.crypto = require('./crypto');
bcoin.bn = require('./crypto/bn');
bcoin.secp256k1 = require('./crypto/secp256k1');
bcoin.schnorr = require('./crypto/schnorr');
bcoin.crypto = require('bcrypto');
// DB
bcoin.db = require('./db');

View File

@ -202,10 +202,7 @@ bcoin.define('coins', './coins');
bcoin.define('coinview', './coins/coinview');
// Crypto
bcoin.define('crypto', './crypto');
bcoin.define('bn', './crypto/bn');
bcoin.define('secp256k1', './crypto/secp256k1');
bcoin.define('schnorr', './crypto/schnorr');
bcoin.define('crypto', 'bcrypto');
// DB
bcoin.define('db', './db');

View File

@ -8,7 +8,7 @@
const assert = require('assert');
const util = require('../utils/util');
const digest = require('../crypto/digest');
const digest = require('bcrypto/lib/digest');
const x509 = require('./x509');
const PEM = require('../utils/pem');
const ProtoReader = require('../utils/protoreader');

View File

@ -10,8 +10,9 @@
* @module bip70/pk
*/
const rsa = require('../crypto/rsa');
const ecdsa = require('../crypto/ecdsa');
const digest = require('bcrypto/lib/digest');
const rsa = require('bcrypto/lib/rsa');
const ecdsa = require('bcrypto/lib/ecdsa');
/**
* Verify signature with public key.
@ -23,6 +24,7 @@ const ecdsa = require('../crypto/ecdsa');
*/
exports.verify = function verify(hash, msg, sig, key) {
hash = digest.get(hash);
switch (key.alg) {
case 'rsa':
return rsa.verify(hash, msg, sig, key.data);
@ -42,6 +44,7 @@ exports.verify = function verify(hash, msg, sig, key) {
*/
exports.sign = function sign(hash, msg, key) {
hash = digest.get(hash);
switch (key.alg) {
case 'rsa':
return rsa.sign(hash, msg, key.data);

View File

@ -10,7 +10,7 @@ const assert = require('assert');
const ASN1 = require('../utils/asn1');
const PEM = require('../utils/pem');
const util = require('../utils/util');
const digest = require('../crypto/digest');
const digest = require('bcrypto/lib/digest');
const pk = require('./pk');
const certs = require('./certs');

View File

@ -8,10 +8,10 @@
'use strict';
const assert = require('assert');
const BN = require('../crypto/bn');
const BN = require('bcrypto/lib/bn');
const consensus = require('../protocol/consensus');
const util = require('../utils/util');
const digest = require('../crypto/digest');
const digest = require('bcrypto/lib/digest');
const encoding = require('../utils/encoding');
const BufferReader = require('../utils/reader');
const StaticWriter = require('../utils/staticwriter');

View File

@ -12,7 +12,7 @@
*/
const assert = require('assert');
const secp256k1 = require('../crypto/secp256k1');
const secp256k1 = require('bcrypto/lib/secp256k1');
const encoding = require('../utils/encoding');
const consensus = require('../protocol/consensus');

View File

@ -1,172 +0,0 @@
/*!
* aead.js - aead for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const assert = require('assert');
const ChaCha20 = require('./chacha20');
const Poly1305 = require('./poly1305');
/**
* AEAD (used for bip151)
* @alias module:crypto.AEAD
* @constructor
* @see https://github.com/openssh/openssh-portable
* @see https://tools.ietf.org/html/rfc7539#section-2.8
*/
function AEAD() {
if (!(this instanceof AEAD))
return new AEAD();
this.chacha20 = new ChaCha20();
this.poly1305 = new Poly1305();
this.aadLen = 0;
this.cipherLen = 0;
this.polyKey = null;
}
/**
* Initialize the AEAD with a key and iv.
* @param {Buffer} key
* @param {Buffer} iv - IV / packet sequence number.
*/
AEAD.prototype.init = function init(key, iv) {
const polyKey = Buffer.allocUnsafe(32);
polyKey.fill(0);
this.chacha20.init(key, iv);
this.chacha20.encrypt(polyKey);
this.poly1305.init(polyKey);
// We need to encrypt a full block
// to get the cipher in the correct state.
this.chacha20.encrypt(Buffer.allocUnsafe(32));
// Counter should be one.
assert(this.chacha20.getCounter() === 1);
// Expose for debugging.
this.polyKey = polyKey;
this.aadLen = 0;
this.cipherLen = 0;
};
/**
* Update the aad (will be finalized
* on an encrypt/decrypt call).
* @param {Buffer} aad
*/
AEAD.prototype.aad = function aad(data) {
assert(this.cipherLen === 0, 'Cannot update aad.');
this.poly1305.update(data);
this.aadLen += data.length;
};
/**
* Encrypt a piece of data.
* @param {Buffer} data
*/
AEAD.prototype.encrypt = function encrypt(data) {
if (this.cipherLen === 0)
this.pad16(this.aadLen);
this.chacha20.encrypt(data);
this.poly1305.update(data);
this.cipherLen += data.length;
return data;
};
/**
* Decrypt a piece of data.
* @param {Buffer} data
*/
AEAD.prototype.decrypt = function decrypt(data) {
if (this.cipherLen === 0)
this.pad16(this.aadLen);
this.cipherLen += data.length;
this.poly1305.update(data);
this.chacha20.encrypt(data);
return data;
};
/**
* Authenticate data without decrypting.
* @param {Buffer} data
*/
AEAD.prototype.auth = function auth(data) {
if (this.cipherLen === 0)
this.pad16(this.aadLen);
this.cipherLen += data.length;
this.poly1305.update(data);
return data;
};
/**
* Finalize the aead and generate a MAC.
* @returns {Buffer} MAC
*/
AEAD.prototype.finish = function finish() {
const len = Buffer.allocUnsafe(16);
let lo, hi;
// The RFC says these are supposed to be
// uint32le, but their own fucking test
// cases fail unless they are uint64le's.
lo = this.aadLen % 0x100000000;
hi = (this.aadLen - lo) / 0x100000000;
len.writeUInt32LE(lo, 0, true);
len.writeUInt32LE(hi, 4, true);
lo = this.cipherLen % 0x100000000;
hi = (this.cipherLen - lo) / 0x100000000;
len.writeUInt32LE(lo, 8, true);
len.writeUInt32LE(hi, 12, true);
if (this.cipherLen === 0)
this.pad16(this.aadLen);
this.pad16(this.cipherLen);
this.poly1305.update(len);
return this.poly1305.finish();
};
/**
* Pad a chunk before updating mac.
* @private
* @param {Number} size
*/
AEAD.prototype.pad16 = function pad16(size) {
size %= 16;
if (size === 0)
return;
const pad = Buffer.allocUnsafe(16 - size);
pad.fill(0);
this.poly1305.update(pad);
};
/*
* Expose
*/
module.exports = AEAD;

File diff suppressed because it is too large Load Diff

View File

@ -1,49 +0,0 @@
/*!
* aes.js - aes for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto.aes
*/
const crypto = require('crypto');
const native = require('../native').binding;
/**
* Encrypt data with aes 256 cbc.
* @param {Buffer} data
* @param {Buffer} key
* @param {Buffer} iv
* @returns {Buffer}
*/
exports.encipher = function encipher(data, key, iv) {
const ctx = crypto.createCipheriv('aes-256-cbc', key, iv);
return Buffer.concat([ctx.update(data), ctx.final()]);
};
/**
* Decrypt data with aes 256 cbc.
* @param {Buffer} data
* @param {Buffer} key
* @param {Buffer} iv
* @returns {Buffer}
*/
exports.decipher = function decipher(data, key, iv) {
const ctx = crypto.createDecipheriv('aes-256-cbc', key, iv);
try {
return Buffer.concat([ctx.update(data), ctx.final()]);
} catch (e) {
throw new Error('Bad key for decryption.');
}
};
if (native) {
exports.encipher = native.encipher;
exports.decipher = native.decipher;
}

View File

@ -1,19 +0,0 @@
/*!
* bn.js - big numbers for bcoin
* Copyright (c) 2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto.BN
*/
/**
* bn.js
* @constructor
* @see https://github.com/indutny/bn.js
*/
module.exports = require('bn.js');

View File

@ -1,36 +0,0 @@
/*!
* ccmp.js - constant-time compare for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const assert = require('assert');
/**
* memcmp in constant time (can only return true or false).
* This protects us against timing attacks when
* comparing an input against a secret string.
* @alias module:crypto.ccmp
* @see https://cryptocoding.net/index.php/Coding_rules
* @see `$ man 3 memcmp` (NetBSD's consttime_memequal)
* @param {Buffer} a
* @param {Buffer} b
* @returns {Boolean}
*/
module.exports = function ccmp(a, b) {
assert(Buffer.isBuffer(a));
assert(Buffer.isBuffer(b));
if (b.length === 0)
return a.length === 0;
let res = a.length ^ b.length;
for (let i = 0; i < a.length; i++)
res |= a[i] ^ b[i % b.length];
return res === 0;
};

View File

@ -1,205 +0,0 @@
/*!
* chacha20.js - chacha20 for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const assert = require('assert');
const native = require('../native').binding;
const BIG_ENDIAN = new Int8Array(new Int16Array([1]).buffer)[0] === 0;
/**
* ChaCha20 (used for bip151)
* @alias module:crypto.ChaCha20
* @constructor
* @see https://tools.ietf.org/html/rfc7539#section-2
*/
function ChaCha20() {
if (!(this instanceof ChaCha20))
return new ChaCha20();
this.state = new Uint32Array(16);
this.stream = new Uint32Array(16);
this.bytes = new Uint8Array(this.stream.buffer);
if (BIG_ENDIAN)
this.bytes = Buffer.allocUnsafe(64);
this.pos = 0;
this.ivSize = 0;
}
/**
* Initialize chacha20 with a key, iv, and counter.
* @param {Buffer} key
* @param {Buffer} iv
* @param {Number} counter
*/
ChaCha20.prototype.init = function init(key, iv, counter) {
if (key)
this.initKey(key);
if (iv)
this.initIV(iv, counter);
};
/**
* Set key.
* @param {Buffer} key
*/
ChaCha20.prototype.initKey = function initKey(key) {
this.state[0] = 0x61707865;
this.state[1] = 0x3320646e;
this.state[2] = 0x79622d32;
this.state[3] = 0x6b206574;
this.state[4] = key.readUInt32LE(0, true);
this.state[5] = key.readUInt32LE(4, true);
this.state[6] = key.readUInt32LE(8, true);
this.state[7] = key.readUInt32LE(12, true);
this.state[8] = key.readUInt32LE(16, true);
this.state[9] = key.readUInt32LE(20, true);
this.state[10] = key.readUInt32LE(24, true);
this.state[11] = key.readUInt32LE(28, true);
this.state[12] = 0;
this.pos = 0xffffffff;
};
/**
* Set IV and counter.
* @param {Buffer} iv
* @param {Number} counter
*/
ChaCha20.prototype.initIV = function initIV(iv, counter) {
if (iv.length === 8) {
this.state[13] = 0;
this.state[14] = iv.readUInt32LE(0, true);
this.state[15] = iv.readUInt32LE(4, true);
} else if (iv.length === 12) {
this.state[13] = iv.readUInt32LE(0, true);
this.state[14] = iv.readUInt32LE(4, true);
this.state[15] = iv.readUInt32LE(8, true);
} else {
assert(false, 'Bad iv size.');
}
this.ivSize = iv.length * 8;
this.setCounter(counter);
};
/**
* Encrypt/decrypt data.
* @param {Buffer} data - Will be mutated.
*/
ChaCha20.prototype.encrypt = function encrypt(data) {
for (let i = 0; i < data.length; i++) {
if (this.pos >= 64) {
for (let j = 0; j < 16; j++)
this.stream[j] = this.state[j];
for (let j = 0; j < 10; j++) {
qround(this.stream, 0, 4, 8, 12);
qround(this.stream, 1, 5, 9, 13);
qround(this.stream, 2, 6, 10, 14);
qround(this.stream, 3, 7, 11, 15);
qround(this.stream, 0, 5, 10, 15);
qround(this.stream, 1, 6, 11, 12);
qround(this.stream, 2, 7, 8, 13);
qround(this.stream, 3, 4, 9, 14);
}
for (let j = 0; j < 16; j++) {
this.stream[j] += this.state[j];
if (BIG_ENDIAN)
this.bytes.writeUInt32LE(this.stream[j], j * 4, true);
}
this.state[12]++;
if (this.state[12] === 0) {
assert(this.ivSize === 64, 'Counter overflow.');
this.state[13]++;
assert(this.state[13] !== 0, 'Counter overflow.');
}
this.pos = 0;
}
data[i] ^= this.bytes[this.pos++];
}
return data;
};
/**
* Artificially set the counter.
* @param {Number} counter
*/
ChaCha20.prototype.setCounter = function setCounter(counter) {
if (!counter)
counter = 0;
const lo = counter % 0x100000000;
const hi = (counter - lo) / 0x100000000;
this.state[12] = lo;
if (this.ivSize === 64)
this.state[13] = hi;
};
/**
* Get the counter as a uint64.
* @returns {Number}
*/
ChaCha20.prototype.getCounter = function getCounter() {
const lo = this.state[12];
const hi = this.state[13];
if (this.ivSize === 64)
return hi * 0x100000000 + lo;
return lo;
};
if (native)
ChaCha20 = native.ChaCha20;
/*
* Helpers
*/
function qround(x, a, b, c, d) {
x[a] += x[b];
x[d] = rotl32(x[d] ^ x[a], 16);
x[c] += x[d];
x[b] = rotl32(x[b] ^ x[c], 12);
x[a] += x[b];
x[d] = rotl32(x[d] ^ x[a], 8);
x[c] += x[d];
x[b] = rotl32(x[b] ^ x[c], 7);
}
function rotl32(w, b) {
return (w << b) | (w >>> (32 - b));
}
/*
* Expose
*/
module.exports = ChaCha20;

View File

@ -1,34 +0,0 @@
/*!
* cleanse.js - memzero for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto.cleanse
*/
const native = require('../native').binding;
let counter = 0;
/**
* A maybe-secure memzero.
* @param {Buffer} data
*/
module.exports = function cleanse(data) {
let ctr = counter;
for (let i = 0; i < data.length; i++) {
data[i] = ctr & 0xff;
ctr += i;
}
counter = ctr >>> 0;
};
if (native)
exports.cleanse = native.cleanse;

View File

@ -1,122 +0,0 @@
/*!
* digest-browser.js - hash functions for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto.digest-browser
* @ignore
*/
const assert = require('assert');
const hashjs = require('hash.js');
const SHA256 = require('./sha256');
const POOL64 = Buffer.allocUnsafe(64);
/**
* Hash with chosen algorithm.
* @param {String} alg
* @param {Buffer} data
* @returns {Buffer}
*/
exports.hash = function hash(alg, data) {
if (alg === 'sha256')
return SHA256.digest(data);
const algo = hashjs[alg];
assert(algo != null, 'Unknown algorithm.');
return Buffer.from(algo().update(data).digest());
};
/**
* Hash with ripemd160.
* @param {Buffer} data
* @returns {Buffer}
*/
exports.ripemd160 = function ripemd160(data) {
return exports.hash('ripemd160', data);
};
/**
* Hash with sha1.
* @param {Buffer} data
* @returns {Buffer}
*/
exports.sha1 = function sha1(data) {
return exports.hash('sha1', data);
};
/**
* Hash with sha256.
* @param {Buffer} data
* @returns {Buffer}
*/
exports.sha256 = function sha256(data) {
return SHA256.digest(data);
};
/**
* Hash with sha256 and ripemd160 (OP_HASH160).
* @param {Buffer} data
* @returns {Buffer}
*/
exports.hash160 = function hash160(data) {
return exports.hash('ripemd160', SHA256.digest(data));
};
/**
* Hash with sha256 twice (OP_HASH256).
* @param {Buffer} data
* @returns {Buffer}
*/
exports.hash256 = function hash256(data) {
return SHA256.hash256(data);
};
/**
* Hash left and right hashes with hash256.
* @param {Buffer} left
* @param {Buffer} right
* @returns {Buffer}
*/
exports.root256 = function root256(left, right) {
const data = POOL64;
assert(left.length === 32);
assert(right.length === 32);
left.copy(data, 0);
right.copy(data, 32);
return exports.hash256(data);
};
/**
* Create an HMAC.
* @param {String} alg
* @param {Buffer} data
* @param {Buffer} key
* @returns {Buffer} HMAC
*/
exports.hmac = function hmac(alg, data, key) {
const algo = hashjs[alg];
assert(algo != null, 'Unknown algorithm.');
const ctx = hashjs.hmac(algo, key);
return Buffer.from(ctx.update(data).digest());
};

View File

@ -1,120 +0,0 @@
/*!
* digest.js - hash functions for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto.digest
*/
const assert = require('assert');
const crypto = require('crypto');
const native = require('../native').binding;
const POOL64 = Buffer.allocUnsafe(64);
/**
* Hash with chosen algorithm.
* @param {String} alg
* @param {Buffer} data
* @returns {Buffer}
*/
exports.hash = function hash(alg, data) {
return crypto.createHash(alg).update(data).digest();
};
/**
* Hash with ripemd160.
* @param {Buffer} data
* @returns {Buffer}
*/
exports.ripemd160 = function ripemd160(data) {
return exports.hash('ripemd160', data);
};
/**
* Hash with sha1.
* @param {Buffer} data
* @returns {Buffer}
*/
exports.sha1 = function sha1(data) {
return exports.hash('sha1', data);
};
/**
* Hash with sha256.
* @param {Buffer} data
* @returns {Buffer}
*/
exports.sha256 = function sha256(data) {
return exports.hash('sha256', data);
};
/**
* Hash with sha256 and ripemd160 (OP_HASH160).
* @param {Buffer} data
* @returns {Buffer}
*/
exports.hash160 = function hash160(data) {
return exports.ripemd160(exports.sha256(data));
};
/**
* Hash with sha256 twice (OP_HASH256).
* @param {Buffer} data
* @returns {Buffer}
*/
exports.hash256 = function hash256(data) {
return exports.sha256(exports.sha256(data));
};
/**
* Hash left and right hashes with hash256.
* @param {Buffer} left
* @param {Buffer} right
* @returns {Buffer}
*/
exports.root256 = function root256(left, right) {
const data = POOL64;
assert(left.length === 32);
assert(right.length === 32);
left.copy(data, 0);
right.copy(data, 32);
return exports.hash256(data);
};
/**
* Create an HMAC.
* @param {String} alg
* @param {Buffer} data
* @param {Buffer} key
* @returns {Buffer} HMAC
*/
exports.hmac = function hmac(alg, data, key) {
const ctx = crypto.createHmac(alg, key);
return ctx.update(data).digest();
};
if (native) {
exports.hash = native.hash;
exports.hmac = native.hmac;
exports.ripemd160 = native.ripemd160;
exports.sha1 = native.sha1;
exports.sha256 = native.sha256;
exports.hash160 = native.hash160;
exports.hash256 = native.hash256;
exports.root256 = native.root256;
}

View File

@ -1,65 +0,0 @@
/*!
* ecdsa.js - ecdsa for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto/ecdsa
*/
const assert = require('assert');
const elliptic = require('elliptic');
const digest = require('./digest');
/**
* Verify ECDSA signature.
* @param {String} curve - Curve name.
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} sig - Signature.
* @param {Buffer} key - ASN1 serialized ECDSA key.
* @returns {Boolean}
*/
exports.verify = function verify(curve, alg, msg, sig, key) {
assert(typeof curve === 'string', 'No curve selected.');
assert(typeof alg === 'string', 'No algorithm selected.');
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert(Buffer.isBuffer(key));
const ec = elliptic.ec(curve);
const hash = digest.hash(alg, msg);
try {
return ec.verify(hash, sig, key);
} catch (e) {
return false;
}
};
/**
* Sign message with ECDSA key.
* @memberof module:crypto/pk.ecdsa
* @param {String} curve - Curve name.
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} key - ASN1 serialized ECDSA key.
* @returns {Buffer} Signature (DER)
*/
exports.sign = function sign(curve, alg, msg, key) {
assert(typeof curve === 'string', 'No curve selected.');
assert(typeof alg === 'string', 'No algorithm selected.');
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(key));
const ec = elliptic.ec(curve);
const hash = digest.hash(alg, msg);
const sig = ec.sign(hash, key, { canonical: true });
return Buffer.from(sig.toDER());
};

View File

@ -1,65 +0,0 @@
/*!
* hkdf.js - hkdf for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto/hkdf
*/
const digest = require('./digest');
/**
* Perform hkdf extraction.
* @param {Buffer} ikm
* @param {Buffer} key
* @param {String} alg
* @returns {Buffer}
*/
exports.extract = function extract(ikm, key, alg) {
return digest.hmac(alg, ikm, key);
};
/**
* Perform hkdf expansion.
* @param {Buffer} prk
* @param {Buffer} info
* @param {Number} len
* @param {String} alg
* @returns {Buffer}
*/
exports.expand = function expand(prk, info, len, alg) {
const size = digest.hash(alg, Buffer.alloc(0)).length;
const blocks = Math.ceil(len / size);
if (blocks > 255)
throw new Error('Too many blocks.');
const okm = Buffer.allocUnsafe(len);
if (blocks === 0)
return okm;
const buf = Buffer.allocUnsafe(size + info.length + 1);
// First round:
info.copy(buf, size);
buf[buf.length - 1] = 1;
let out = digest.hmac(alg, buf.slice(size), prk);
out.copy(okm, 0);
for (let i = 1; i < blocks; i++) {
out.copy(buf, 0);
buf[buf.length - 1]++;
out = digest.hmac(alg, buf, prk);
out.copy(okm, i * size);
}
return okm;
};

View File

@ -1,120 +0,0 @@
/*!
* hmac-drbg.js - hmac-drbg implementation for bcoin
* Copyright (c) 2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
* Parts of this software based on hmac-drbg.
*/
'use strict';
const assert = require('assert');
const digest = require('./digest');
/*
* Constants
*/
const HASH_ALG = 'sha256';
const HASH_SIZE = 32;
const RESEED_INTERVAL = 0x1000000000000;
const POOL33 = Buffer.allocUnsafe(HASH_SIZE + 1);
const POOL112 = Buffer.allocUnsafe(HASH_SIZE * 2 + 48);
const POOL145 = Buffer.allocUnsafe(POOL33.length + POOL112.length);
/**
* HmacDRBG
* @constructor
*/
function HmacDRBG(entropy, nonce, pers) {
if (!(this instanceof HmacDRBG))
return new HmacDRBG(entropy, nonce, pers);
this.K = Buffer.allocUnsafe(HASH_SIZE);
this.V = Buffer.allocUnsafe(HASH_SIZE);
this.rounds = 0;
this.init(entropy, nonce, pers);
}
HmacDRBG.prototype.init = function init(entropy, nonce, pers) {
for (let i = 0; i < this.V.length; i++) {
this.K[i] = 0x00;
this.V[i] = 0x01;
}
this.reseed(entropy, nonce, pers);
};
HmacDRBG.prototype.reseed = function reseed(entropy, nonce, pers) {
const seed = POOL112;
assert(Buffer.isBuffer(entropy));
assert(Buffer.isBuffer(nonce));
assert(Buffer.isBuffer(pers));
assert(entropy.length === HASH_SIZE);
assert(nonce.length === HASH_SIZE);
assert(pers.length === 48);
entropy.copy(seed, 0);
nonce.copy(seed, HASH_SIZE);
pers.copy(seed, HASH_SIZE * 2);
this.update(seed);
this.rounds = 1;
};
HmacDRBG.prototype.iterate = function iterate() {
const data = POOL33;
this.V.copy(data, 0);
data[HASH_SIZE] = 0x00;
this.K = digest.hmac(HASH_ALG, data, this.K);
this.V = digest.hmac(HASH_ALG, this.V, this.K);
};
HmacDRBG.prototype.update = function update(seed) {
const data = POOL145;
assert(Buffer.isBuffer(seed));
assert(seed.length === HASH_SIZE * 2 + 48);
this.V.copy(data, 0);
data[HASH_SIZE] = 0x00;
seed.copy(data, HASH_SIZE + 1);
this.K = digest.hmac(HASH_ALG, data, this.K);
this.V = digest.hmac(HASH_ALG, this.V, this.K);
data[HASH_SIZE] = 0x01;
this.K = digest.hmac(HASH_ALG, data, this.K);
this.V = digest.hmac(HASH_ALG, this.V, this.K);
};
HmacDRBG.prototype.generate = function generate(len) {
if (this.rounds > RESEED_INTERVAL)
throw new Error('Reseed is required.');
const data = Buffer.allocUnsafe(len);
let pos = 0;
while (pos < len) {
this.V = digest.hmac(HASH_ALG, this.V, this.K);
this.V.copy(data, pos);
pos += HASH_SIZE;
}
this.iterate();
this.rounds++;
return data;
};
/*
* Expose
*/
module.exports = HmacDRBG;

View File

@ -1,51 +0,0 @@
/*!
* crypto/index.js - crypto for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto
*/
const digest = require('./digest');
const random = require('./random');
const aes = require('./aes');
exports.aes = require('./aes');
exports.AEAD = require('./aead');
exports.BN = require('./bn');
exports.ccmp = require('./ccmp');
exports.ChaCha20 = require('./chacha20');
exports.cleanse = require('./cleanse');
exports.digest = require('./digest');
exports.ecdsa = require('./ecdsa');
exports.hkdf = require('./hkdf');
exports.HmacDRBG = require('./hmac-drbg');
exports.merkle = require('./merkle');
exports.pbkdf2 = require('./pbkdf2');
exports.Poly1305 = require('./poly1305');
exports.random = require('./random');
exports.rsa = require('./rsa');
exports.schnorr = require('./schnorr');
exports.scrypt = require('./scrypt');
exports.secp256k1 = require('./secp256k1');
exports.siphash = require('./siphash');
exports.hash = digest.hash;
exports.ripemd160 = digest.ripemd160;
exports.sha1 = digest.sha1;
exports.sha256 = digest.sha256;
exports.hash160 = digest.hash160;
exports.hash256 = digest.hash256;
exports.root256 = digest.root256;
exports.hmac = digest.hmac;
exports.encipher = aes.encipher;
exports.decipher = aes.decipher;
exports.randomBytes = random.randomBytes;
exports.randomInt = random.randomInt;
exports.randomRange = random.randomRange;

View File

@ -1,115 +0,0 @@
/*!
* merkle.js - merkle trees for bcoin
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto/merkle
*/
const digest = require('./digest');
/**
* Build a merkle tree from leaves.
* Note that this will mutate the `leaves` array!
* @param {Buffer[]} leaves
* @returns {Array} [nodes, malleated]
*/
exports.createTree = function createTree(leaves) {
const nodes = leaves;
let size = leaves.length;
let malleated = false;
let i = 0;
if (size === 0) {
nodes.push(Buffer.alloc(32));
return [nodes, malleated];
}
while (size > 1) {
for (let j = 0; j < size; j += 2) {
const k = Math.min(j + 1, size - 1);
const left = nodes[i + j];
const right = nodes[i + k];
if (k === j + 1 && k + 1 === size
&& left.equals(right)) {
malleated = true;
}
const hash = digest.root256(left, right);
nodes.push(hash);
}
i += size;
size += 1;
size >>>= 1;
}
return [nodes, malleated];
};
/**
* Calculate merkle root from leaves.
* @param {Buffer[]} leaves
* @returns {Array} [root, malleated]
*/
exports.createRoot = function createRoot(leaves) {
const [nodes, malleated] = exports.createTree(leaves);
const root = nodes[nodes.length - 1];
return [root, malleated];
};
/**
* Collect a merkle branch from vector index.
* @param {Number} index
* @param {Buffer[]} leaves
* @returns {Buffer[]} branch
*/
exports.createBranch = function createBranch(index, leaves) {
let size = leaves.length;
const [nodes] = exports.createTree(leaves);
const branch = [];
let i = 0;
while (size > 1) {
const j = Math.min(index ^ 1, size - 1);
branch.push(nodes[i + j]);
index >>>= 1;
i += size;
size += 1;
size >>>= 1;
}
return branch;
};
/**
* Derive merkle root from branch.
* @param {Buffer} hash
* @param {Buffer[]} branch
* @param {Number} index
* @returns {Buffer} root
*/
exports.deriveRoot = function deriveRoot(hash, branch, index) {
let root = hash;
for (const hash of branch) {
if (index & 1)
root = digest.root256(hash, root);
else
root = digest.root256(root, hash);
index >>>= 1;
}
return root;
};

View File

@ -1,101 +0,0 @@
/*!
* pbkdf2.js - pbkdf2 for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto.pbkdf2-browser
* @ignore
*/
const digest = require('./digest');
const crypto = global.crypto || global.msCrypto || {};
const subtle = crypto.subtle || {};
/**
* Perform key derivation using PBKDF2.
* @param {Buffer} key
* @param {Buffer} salt
* @param {Number} iter
* @param {Number} len
* @param {String} alg
* @returns {Buffer}
*/
exports.derive = function derive(key, salt, iter, len, alg) {
const size = digest.hash(alg, Buffer.alloc(0)).length;
const blocks = Math.ceil(len / size);
const out = Buffer.allocUnsafe(len);
const buf = Buffer.allocUnsafe(salt.length + 4);
const block = Buffer.allocUnsafe(size);
let pos = 0;
salt.copy(buf, 0);
for (let i = 0; i < blocks; i++) {
buf.writeUInt32BE(i + 1, salt.length, true);
let mac = digest.hmac(alg, buf, key);
mac.copy(block, 0);
for (let j = 1; j < iter; j++) {
mac = digest.hmac(alg, mac, key);
for (let k = 0; k < size; k++)
block[k] ^= mac[k];
}
block.copy(out, pos);
pos += size;
}
return out;
};
/**
* Execute pbkdf2 asynchronously.
* @param {Buffer} key
* @param {Buffer} salt
* @param {Number} iter
* @param {Number} len
* @param {String} alg
* @returns {Promise}
*/
exports.deriveAsync = async function deriveAsync(key, salt, iter, len, alg) {
const algo = { name: 'PBKDF2' };
const use = ['deriveBits'];
if (!subtle.importKey || !subtle.deriveBits)
return exports.derive(key, salt, iter, len, alg);
const options = {
name: 'PBKDF2',
salt: salt,
iterations: iter,
hash: getHash(alg)
};
const imported = await subtle.importKey('raw', key, algo, false, use);
const data = await subtle.deriveBits(options, imported, len * 8);
return Buffer.from(data);
};
/*
* Helpers
*/
function getHash(name) {
switch (name) {
case 'sha1':
return 'SHA-1';
case 'sha256':
return 'SHA-256';
case 'sha384':
return 'SHA-384';
case 'sha512':
return 'SHA-512';
default:
throw new Error(`Algorithm not supported: ${name}.`);
}
}

View File

@ -1,49 +0,0 @@
/*!
* pbkdf2.js - pbkdf2 for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto.pbkdf2
*/
const crypto = require('crypto');
/**
* Perform key derivation using PBKDF2.
* @param {Buffer} key
* @param {Buffer} salt
* @param {Number} iter
* @param {Number} len
* @param {String} alg
* @returns {Buffer}
*/
exports.derive = function derive(key, salt, iter, len, alg) {
return crypto.pbkdf2Sync(key, salt, iter, len, alg);
};
/**
* Execute pbkdf2 asynchronously.
* @param {Buffer} key
* @param {Buffer} salt
* @param {Number} iter
* @param {Number} len
* @param {String} alg
* @returns {Promise}
*/
exports.deriveAsync = function deriveAsync(key, salt, iter, len, alg) {
return new Promise((resolve, reject) => {
crypto.pbkdf2(key, salt, iter, len, alg, (err, result) => {
if (err) {
reject(err);
return;
}
resolve(result);
});
});
};

View File

@ -1,321 +0,0 @@
/*!
* poly1305.js - poly1305 for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const native = require('../native').binding;
/**
* Poly1305 (used for bip151)
* @alias module:crypto/chachapoly.Poly1305
* @constructor
* @see https://github.com/floodyberry/poly1305-donna
* @see https://tools.ietf.org/html/rfc7539#section-2.5
*/
function Poly1305() {
if (!(this instanceof Poly1305))
return new Poly1305();
this.r = new Uint16Array(10);
this.h = new Uint16Array(10);
this.pad = new Uint16Array(8);
this.fin = 0;
this.leftover = 0;
this.buffer = Buffer.allocUnsafe(16);
}
/**
* Initialize poly1305 with a key.
* @param {Buffer} key
*/
Poly1305.prototype.init = function init(key) {
// r &= 0xffffffc0ffffffc0ffffffc0fffffff
const t0 = key.readUInt16LE(0, true);
const t1 = key.readUInt16LE(2, true);
const t2 = key.readUInt16LE(4, true);
const t3 = key.readUInt16LE(6, true);
const t4 = key.readUInt16LE(8, true);
const t5 = key.readUInt16LE(10, true);
const t6 = key.readUInt16LE(12, true);
const t7 = key.readUInt16LE(14, true);
this.r[0] = t0 & 0x1fff;
this.r[1] = ((t0 >>> 13) | (t1 << 3)) & 0x1fff;
this.r[2] = ((t1 >>> 10) | (t2 << 6)) & 0x1f03;
this.r[3] = ((t2 >>> 7) | (t3 << 9)) & 0x1fff;
this.r[4] = ((t3 >>> 4) | (t4 << 12)) & 0x00ff;
this.r[5] = (t4 >>> 1) & 0x1ffe;
this.r[6] = ((t4 >>> 14) | (t5 << 2)) & 0x1fff;
this.r[7] = ((t5 >>> 11) | (t6 << 5)) & 0x1f81;
this.r[8] = ((t6 >>> 8) | (t7 << 8)) & 0x1fff;
this.r[9] = (t7 >>> 5) & 0x007f;
// h = 0
for (let i = 0; i < 10; i++)
this.h[i] = 0;
// save pad for later
for (let i = 0; i < 8; i++)
this.pad[i] = key.readUInt16LE(16 + (2 * i), true);
this.leftover = 0;
this.fin = 0;
};
/**
* Process 16 byte blocks.
* @param {Buffer} data - Blocks.
* @param {Number} bytes - Size.
* @param {Number} m - Offset pointer.
*/
Poly1305.prototype.blocks = function blocks(data, bytes, m) {
const hibit = this.fin ? 0 : (1 << 11); // 1 << 128
const d = new Uint32Array(10);
while (bytes >= 16) {
// h += m[i]
const t0 = data.readUInt16LE(m + 0, true);
const t1 = data.readUInt16LE(m + 2, true);
const t2 = data.readUInt16LE(m + 4, true);
const t3 = data.readUInt16LE(m + 6, true);
const t4 = data.readUInt16LE(m + 8, true);
const t5 = data.readUInt16LE(m + 10, true);
const t6 = data.readUInt16LE(m + 12, true);
const t7 = data.readUInt16LE(m + 14, true);
this.h[0] += t0 & 0x1fff;
this.h[1] += ((t0 >>> 13) | (t1 << 3)) & 0x1fff;
this.h[2] += ((t1 >>> 10) | (t2 << 6)) & 0x1fff;
this.h[3] += ((t2 >>> 7) | (t3 << 9)) & 0x1fff;
this.h[4] += ((t3 >>> 4) | (t4 << 12)) & 0x1fff;
this.h[5] += ((t4 >>> 1)) & 0x1fff;
this.h[6] += ((t4 >>> 14) | (t5 << 2)) & 0x1fff;
this.h[7] += ((t5 >>> 11) | (t6 << 5)) & 0x1fff;
this.h[8] += ((t6 >>> 8) | (t7 << 8)) & 0x1fff;
this.h[9] += ((t7 >>> 5)) | hibit;
// h *= r, (partial) h %= p
let c = 0;
for (let i = 0; i < 10; i++) {
d[i] = c;
for (let j = 0; j < 10; j++) {
let a = this.h[j];
if (j <= i)
a *= this.r[i - j];
else
a *= 5 * this.r[i + 10 - j];
d[i] += a;
// Sum(h[i] * r[i] * 5) will overflow slightly
// above 6 products with an unclamped r, so
// carry at 5
if (j === 4) {
c = d[i] >>> 13;
d[i] &= 0x1fff;
}
}
c += d[i] >>> 13;
d[i] &= 0x1fff;
}
c = (c << 2) + c; // c *= 5
c += d[0];
d[0] = (c & 0x1fff);
c = c >>> 13;
d[1] += c;
for (let i = 0; i < 10; i++)
this.h[i] = d[i];
m += 16;
bytes -= 16;
}
};
/**
* Update the MAC with data (will be
* processed as 16 byte blocks).
* @param {Buffer} data
*/
Poly1305.prototype.update = function update(data) {
let bytes = data.length;
let m = 0;
// handle leftover
if (this.leftover) {
let want = 16 - this.leftover;
if (want > bytes)
want = bytes;
for (let i = 0; i < want; i++)
this.buffer[this.leftover + i] = data[m + i];
bytes -= want;
m += want;
this.leftover += want;
if (this.leftover < 16)
return;
this.blocks(this.buffer, 16, 0);
this.leftover = 0;
}
// process full blocks
if (bytes >= 16) {
const want = bytes & ~(16 - 1);
this.blocks(data, want, m);
m += want;
bytes -= want;
}
// store leftover
if (bytes) {
for (let i = 0; i < bytes; i++)
this.buffer[this.leftover + i] = data[m + i];
this.leftover += bytes;
}
};
/**
* Finalize and return a 16-byte MAC.
* @returns {Buffer}
*/
Poly1305.prototype.finish = function finish() {
const mac = Buffer.allocUnsafe(16);
const g = new Uint16Array(10);
// process the remaining block
if (this.leftover) {
let i = this.leftover;
this.buffer[i++] = 1;
for (; i < 16; i++)
this.buffer[i] = 0;
this.fin = 1;
this.blocks(this.buffer, 16, 0);
}
// fully carry h
let c = this.h[1] >>> 13;
this.h[1] &= 0x1fff;
for (let i = 2; i < 10; i++) {
this.h[i] += c;
c = this.h[i] >>> 13;
this.h[i] &= 0x1fff;
}
this.h[0] += c * 5;
c = this.h[0] >>> 13;
this.h[0] &= 0x1fff;
this.h[1] += c;
c = this.h[1] >>> 13;
this.h[1] &= 0x1fff;
this.h[2] += c;
// compute h + -p
g[0] = this.h[0] + 5;
c = g[0] >>> 13;
g[0] &= 0x1fff;
for (let i = 1; i < 10; i++) {
g[i] = this.h[i] + c;
c = g[i] >>> 13;
g[i] &= 0x1fff;
}
// select h if h < p, or h + -p if h >= p
let mask = (c ^ 1) - 1;
for (let i = 0; i < 10; i++)
g[i] &= mask;
mask = ~mask;
for (let i = 0; i < 10; i++)
this.h[i] = (this.h[i] & mask) | g[i];
// h = h % (2^128)
this.h[0] = ((this.h[0]) | (this.h[1] << 13)) & 0xffff;
this.h[1] = ((this.h[1] >>> 3) | (this.h[2] << 10)) & 0xffff;
this.h[2] = ((this.h[2] >>> 6) | (this.h[3] << 7)) & 0xffff;
this.h[3] = ((this.h[3] >>> 9) | (this.h[4] << 4)) & 0xffff;
this.h[4] = ((this.h[4] >>> 12)
| (this.h[5] << 1) | (this.h[6] << 14)) & 0xffff;
this.h[5] = ((this.h[6] >>> 2) | (this.h[7] << 11)) & 0xffff;
this.h[6] = ((this.h[7] >>> 5) | (this.h[8] << 8)) & 0xffff;
this.h[7] = ((this.h[8] >>> 8) | (this.h[9] << 5)) & 0xffff;
// mac = (h + pad) % (2^128)
let f = this.h[0] + this.pad[0];
this.h[0] = f;
for (let i = 1; i < 8; i++) {
f = this.h[i] + this.pad[i] + (f >>> 16);
this.h[i] = f;
}
for (let i = 0; i < 8; i++)
mac.writeUInt16LE(this.h[i], i * 2, true);
// zero out the state
for (let i = 0; i < 10; i++)
this.h[i] = 0;
for (let i = 0; i < 10; i++)
this.r[i] = 0;
for (let i = 0; i < 8; i++)
this.pad[i] = 0;
return mac;
};
/**
* Return a MAC for a message and key.
* @param {Buffer} msg
* @param {Buffer} key
* @returns {Buffer} MAC
*/
Poly1305.auth = function auth(msg, key) {
const poly = new Poly1305();
poly.init(key);
poly.update(msg);
return poly.finish();
};
/**
* Compare two MACs in constant time.
* @param {Buffer} mac1
* @param {Buffer} mac2
* @returns {Boolean}
*/
Poly1305.verify = function verify(mac1, mac2) {
let dif = 0;
// Compare in constant time.
for (let i = 0; i < 16; i++)
dif |= mac1[i] ^ mac2[i];
dif = (dif - 1) >>> 31;
return (dif & 1) !== 0;
};
if (native)
Poly1305 = native.Poly1305;
/*
* Expose
*/
module.exports = Poly1305;

View File

@ -1,63 +0,0 @@
/*!
* random-browser.js - randomness for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto.random-browser
* @ignore
*/
const crypto = global.crypto || global.msCrypto || {};
/**
* Generate pseudo-random bytes.
* @param {Number} size
* @returns {Buffer}
*/
exports.randomBytes = function randomBytes(size) {
const data = new Uint8Array(size);
crypto.getRandomValues(data);
return Buffer.from(data.buffer);
};
if (!crypto.getRandomValues) {
// Out of luck here. Use bad randomness for now.
exports.randomBytes = function randomBytes(size) {
const data = Buffer.allocUnsafe(size);
for (let i = 0; i < data.length; i++)
data[i] = Math.floor(Math.random() * 256);
return data;
};
}
/**
* Generate a random uint32.
* Probably more cryptographically sound than
* `Math.random()`.
* @returns {Number}
*/
exports.randomInt = function randomInt() {
return exports.randomBytes(4).readUInt32LE(0, true);
};
/**
* Generate a random number within a range.
* Probably more cryptographically sound than
* `Math.random()`.
* @param {Number} min - Inclusive.
* @param {Number} max - Exclusive.
* @returns {Number}
*/
exports.randomRange = function randomRange(min, max) {
const num = exports.randomInt();
return Math.floor((num / 0x100000000) * (max - min) + min);
};

View File

@ -1,47 +0,0 @@
/*!
* random.js - randomness for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto.random
*/
const crypto = require('crypto');
/**
* Generate pseudo-random bytes.
* @function
* @param {Number} size
* @returns {Buffer}
*/
exports.randomBytes = crypto.randomBytes;
/**
* Generate a random uint32.
* Probably more cryptographically sound than
* `Math.random()`.
* @returns {Number}
*/
exports.randomInt = function randomInt() {
return exports.randomBytes(4).readUInt32LE(0, true);
};
/**
* Generate a random number within a range.
* Probably more cryptographically sound than
* `Math.random()`.
* @param {Number} min - Inclusive.
* @param {Number} max - Exclusive.
* @returns {Number}
*/
exports.randomRange = function randomRange(min, max) {
const num = exports.randomInt();
return Math.floor((num / 0x100000000) * (max - min) + min);
};

View File

@ -1,186 +0,0 @@
/*!
* rsa-browser.js - rsa for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const assert = require('assert');
const BN = require('./bn');
const ASN1 = require('../utils/asn1');
const digest = require('./digest');
const ccmp = require('./ccmp');
/**
* @exports crypto/rsa
* @ignore
*/
const rsa = exports;
/**
* PKCS signature prefixes.
* @type {Object}
*/
rsa.prefixes = {
md5: Buffer.from('3020300c06082a864886f70d020505000410', 'hex'),
sha1: Buffer.from('3021300906052b0e03021a05000414', 'hex'),
sha224: Buffer.from('302d300d06096086480165030402040500041c', 'hex'),
sha256: Buffer.from('3031300d060960864801650304020105000420', 'hex'),
sha384: Buffer.from('3041300d060960864801650304020205000430', 'hex'),
sha512: Buffer.from('3051300d060960864801650304020305000440', 'hex'),
ripemd160: Buffer.from('30203008060628cf060300310414', 'hex')
};
/**
* Verify RSA signature.
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} sig - Signature.
* @param {Buffer} key - ASN1 serialized RSA key.
* @returns {Boolean}
*/
rsa.verify = function verify(alg, msg, sig, key) {
assert(typeof alg === 'string', 'No algorithm selected.');
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert(Buffer.isBuffer(key));
const prefix = rsa.prefixes[alg];
if (!prefix)
throw new Error('Unknown PKCS prefix.');
const hash = digest.hash(alg, msg);
const len = prefix.length + hash.length;
const pub = ASN1.parseRSAPublic(key);
const N = new BN(pub.modulus);
const e = new BN(pub.publicExponent);
const k = Math.ceil(N.bitLength() / 8);
if (k < len + 11)
throw new Error('Message too long.');
const m = rsa.encrypt(N, e, sig);
const em = leftpad(m, k);
let ok = ceq(em[0], 0x00);
ok &= ceq(em[1], 0x01);
ok &= ccmp(em.slice(k - hash.length, k), hash);
ok &= ccmp(em.slice(k - len, k - hash.length), prefix);
ok &= ceq(em[k - len - 1], 0x00);
for (let i = 2; i < k - len - 1; i++)
ok &= ceq(em[i], 0xff);
return ok === 1;
};
/**
* Sign message with RSA key.
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} key - ASN1 serialized RSA key.
* @returns {Buffer} Signature (DER)
*/
rsa.sign = function sign(alg, msg, key) {
assert(typeof alg === 'string', 'No algorithm selected.');
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(key));
const prefix = rsa.prefixes[alg];
if (!prefix)
throw new Error('Unknown PKCS prefix.');
const hash = digest.hash(alg, msg);
const len = prefix.length + hash.length;
const priv = ASN1.parseRSAPrivate(key);
const N = new BN(priv.modulus);
const D = new BN(priv.privateExponent);
const k = Math.ceil(N.bitLength() / 8);
if (k < len + 11)
throw new Error('Message too long.');
const em = Buffer.allocUnsafe(k);
em.fill(0);
em[1] = 0x01;
for (let 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);
};
/**
* Decrypt with modulus and exponent.
* @param {BN} N
* @param {BN} D
* @param {Buffer} m
* @returns {Buffer}
*/
rsa.decrypt = function decrypt(N, D, m) {
const 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');
};
/**
* Encrypt with modulus and exponent.
* @param {BN} N
* @param {BN} e
* @param {Buffer} m
* @returns {Buffer}
*/
rsa.encrypt = function encrypt(N, e, m) {
return new BN(m)
.toRed(BN.red(N))
.redPow(e)
.fromRed()
.toArrayLike(Buffer, 'be');
};
/*
* Helpers
*/
function leftpad(input, size) {
let n = input.length;
if (n > size)
n = size;
const out = Buffer.allocUnsafe(size);
out.fill(0);
input.copy(out, out.length - n);
return out;
}
function ceq(a, b) {
let r = ~(a ^ b) & 0xff;
r &= r >>> 4;
r &= r >>> 2;
r &= r >>> 1;
return r === 1;
}

View File

@ -1,72 +0,0 @@
/*!
* rsa.js - RSA for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto/rsa
*/
const assert = require('assert');
const crypto = require('crypto');
const PEM = require('../utils/pem');
/**
* Verify RSA signature.
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} sig - Signature.
* @param {Buffer} key - ASN1 serialized RSA key.
* @returns {Boolean}
*/
exports.verify = function verify(alg, msg, sig, key) {
assert(typeof alg === 'string', 'No algorithm selected.');
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert(Buffer.isBuffer(key));
const name = normalizeAlg('rsa', alg);
const pem = PEM.encode(key, 'rsa', 'public key');
const ctx = crypto.createVerify(name);
try {
ctx.update(msg);
return ctx.verify(pem, sig);
} catch (e) {
return false;
}
};
/**
* Sign message with RSA key.
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} key - ASN1 serialized RSA key.
* @returns {Buffer} Signature (DER)
*/
exports.sign = function sign(alg, msg, key) {
assert(typeof alg === 'string', 'No algorithm selected.');
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(key));
const name = normalizeAlg('rsa', alg);
const pem = PEM.encode(key, 'rsa', 'private key');
const ctx = crypto.createSign(name);
ctx.update(msg);
return ctx.sign(pem);
};
/*
* Helpers
*/
function normalizeAlg(alg, hash) {
return `${alg.toUpperCase()}-${hash.toUpperCase()}`;
}

View File

@ -1,342 +0,0 @@
/*!
* schnorr.js - schnorr signatures for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const assert = require('assert');
const elliptic = require('elliptic');
const Signature = require('elliptic/lib/elliptic/ec/signature');
const BN = require('./bn');
const HmacDRBG = require('./hmac-drbg');
const sha256 = require('./digest').sha256;
const curve = elliptic.ec('secp256k1').curve;
const POOL64 = Buffer.allocUnsafe(64);
/**
* @exports crypto/schnorr
*/
const schnorr = exports;
/**
* Hash (r | M).
* @param {Buffer} msg
* @param {BN} r
* @returns {Buffer}
*/
schnorr.hash = function hash(msg, r) {
const R = r.toArrayLike(Buffer, 'be', 32);
const B = POOL64;
R.copy(B, 0);
msg.copy(B, 32);
return new BN(sha256(B));
};
/**
* Sign message.
* @private
* @param {Buffer} msg
* @param {BN} priv
* @param {BN} k
* @param {Buffer} pn
* @returns {Signature|null}
*/
schnorr.trySign = function trySign(msg, prv, k, pn) {
if (prv.isZero())
throw new Error('Bad private key.');
if (prv.gte(curve.n))
throw new Error('Bad private key.');
if (k.isZero())
return null;
if (k.gte(curve.n))
return null;
let r = curve.g.mul(k);
if (pn)
r = r.add(pn);
if (r.y.isOdd()) {
k = k.umod(curve.n);
k = curve.n.sub(k);
}
const h = schnorr.hash(msg, r.getX());
if (h.isZero())
return null;
if (h.gte(curve.n))
return null;
let s = h.imul(prv);
s = k.isub(s);
s = s.umod(curve.n);
if (s.isZero())
return null;
return new Signature({ r: r.getX(), s: s });
};
/**
* Sign message.
* @param {Buffer} msg
* @param {Buffer} key
* @param {Buffer} pubNonce
* @returns {Signature}
*/
schnorr.sign = function sign(msg, key, pubNonce) {
const prv = new BN(key);
const drbg = schnorr.drbg(msg, key, pubNonce);
const len = curve.n.byteLength();
let pn;
if (pubNonce)
pn = curve.decodePoint(pubNonce);
let sig;
while (!sig) {
const k = new BN(drbg.generate(len));
sig = schnorr.trySign(msg, prv, k, pn);
}
return sig;
};
/**
* Verify signature.
* @param {Buffer} msg
* @param {Buffer} signature
* @param {Buffer} key
* @returns {Buffer}
*/
schnorr.verify = function verify(msg, signature, key) {
const sig = new Signature(signature);
const h = schnorr.hash(msg, sig.r);
if (h.gte(curve.n))
throw new Error('Invalid hash.');
if (h.isZero())
throw new Error('Invalid hash.');
if (sig.s.gte(curve.n))
throw new Error('Invalid S value.');
if (sig.r.gt(curve.p))
throw new Error('Invalid R value.');
const k = curve.decodePoint(key);
const l = k.mul(h);
const r = curve.g.mul(sig.s);
const rl = l.add(r);
if (rl.y.isOdd())
throw new Error('Odd R value.');
return rl.getX().eq(sig.r);
};
/**
* Recover public key.
* @param {Buffer} msg
* @param {Buffer} signature
* @returns {Buffer}
*/
schnorr.recover = function recover(signature, msg) {
const sig = new Signature(signature);
const h = schnorr.hash(msg, sig.r);
if (h.gte(curve.n))
throw new Error('Invalid hash.');
if (h.isZero())
throw new Error('Invalid hash.');
if (sig.s.gte(curve.n))
throw new Error('Invalid S value.');
if (sig.r.gt(curve.p))
throw new Error('Invalid R value.');
let hinv = h.invm(curve.n);
hinv = hinv.umod(curve.n);
let s = sig.s;
s = curve.n.sub(s);
s = s.umod(curve.n);
s = s.imul(hinv);
s = s.umod(curve.n);
const R = curve.pointFromX(sig.r, false);
let l = R.mul(hinv);
let r = curve.g.mul(s);
const k = l.add(r);
l = k.mul(h);
r = curve.g.mul(sig.s);
const rl = l.add(r);
if (rl.y.isOdd())
throw new Error('Odd R value.');
if (!rl.getX().eq(sig.r))
throw new Error('Could not recover pubkey.');
return Buffer.from(k.encode('array', true));
};
/**
* Combine signatures.
* @param {Buffer[]} sigs
* @returns {Signature}
*/
schnorr.combineSigs = function combineSigs(sigs) {
let s = new BN(0);
let r, last;
for (let i = 0; i < sigs.length; i++) {
const sig = new Signature(sigs[i]);
if (sig.s.isZero())
throw new Error('Bad S value.');
if (sig.s.gte(curve.n))
throw new Error('Bad S value.');
if (!r)
r = sig.r;
if (last && !last.r.eq(sig.r))
throw new Error('Bad signature combination.');
s = s.iadd(sig.s);
s = s.umod(curve.n);
last = sig;
}
if (s.isZero())
throw new Error('Bad combined signature.');
return new Signature({ r: r, s: s });
};
/**
* Combine public keys.
* @param {Buffer[]} keys
* @returns {Buffer}
*/
schnorr.combineKeys = function combineKeys(keys) {
if (keys.length === 0)
throw new Error();
if (keys.length === 1)
return keys[0];
let point = curve.decodePoint(keys[0]);
for (let i = 1; i < keys.length; i++) {
const key = curve.decodePoint(keys[i]);
point = point.add(key);
}
return Buffer.from(point.encode('array', true));
};
/**
* Partially sign.
* @param {Buffer} msg
* @param {Buffer} priv
* @param {Buffer} privNonce
* @param {Buffer} pubNonce
* @returns {Buffer}
*/
schnorr.partialSign = function partialSign(msg, priv, privNonce, pubNonce) {
const prv = new BN(priv);
const k = new BN(privNonce);
const pn = curve.decodePoint(pubNonce);
const sig = schnorr.trySign(msg, prv, k, pn);
if (!sig)
throw new Error('Bad K value.');
return sig;
};
/**
* Schnorr personalization string.
* @const {Buffer}
*/
schnorr.alg = Buffer.from('Schnorr+SHA256 ', 'ascii');
/**
* Instantiate an HMAC-DRBG.
* @param {Buffer} msg
* @param {Buffer} priv
* @param {Buffer} data
* @returns {HmacDRBG}
*/
schnorr.drbg = function drbg(msg, priv, data) {
const pers = Buffer.allocUnsafe(48);
pers.fill(0);
if (data) {
assert(data.length === 32);
data.copy(pers, 0);
}
schnorr.alg.copy(pers, 32);
return new HmacDRBG(priv, msg, pers);
};
/**
* Generate pub+priv nonce pair.
* @param {Buffer} msg
* @param {Buffer} priv
* @param {Buffer} data
* @returns {Buffer}
*/
schnorr.generateNoncePair = function generateNoncePair(msg, priv, data) {
const drbg = schnorr.drbg(msg, priv, data);
const len = curve.n.byteLength();
let k;
for (;;) {
k = new BN(drbg.generate(len));
if (k.isZero())
continue;
if (k.gte(curve.n))
continue;
break;
}
return Buffer.from(curve.g.mul(k).encode('array', true));
};

View File

@ -1,269 +0,0 @@
/*!
* scrypt.js - scrypt for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*
* Ported from:
* https://github.com/Tarsnap/scrypt/blob/master/lib/crypto/crypto_scrypt-ref.c
*
* Copyright 2009 Colin Percival
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* eslint camelcase: "off" */
'use strict';
/**
* @module crypto/scrypt
*/
const pbkdf2 = require('./pbkdf2');
const native = require('../native').binding;
/**
* Javascript scrypt implementation. Scrypt is
* used in bip38. Bcoin doesn't support bip38
* yet, but here it is, just in case.
* @alias module:crypto/scrypt.derive
* @param {Buffer} passwd
* @param {Buffer} salt
* @param {Number} N
* @param {Number} r
* @param {Number} p
* @param {Number} len
* @returns {Buffer}
*/
function derive(passwd, salt, N, r, p, len) {
if (r * p >= (1 << 30))
throw new Error('EFBIG');
if ((N & (N - 1)) !== 0 || N === 0)
throw new Error('EINVAL');
if (N > 0xffffffff)
throw new Error('EINVAL');
const XY = Buffer.allocUnsafe(256 * r);
const V = Buffer.allocUnsafe(128 * r * N);
const B = pbkdf2.derive(passwd, salt, 1, p * 128 * r, 'sha256');
for (let i = 0; i < p; i++)
smix(B, i * 128 * r, r, N, V, XY);
return pbkdf2.derive(passwd, B, 1, len, 'sha256');
}
if (native)
derive = native.scrypt;
/**
* Asynchronous scrypt implementation.
* @alias module:crypto/scrypt.deriveAsync
* @function
* @param {Buffer} passwd
* @param {Buffer} salt
* @param {Number} N
* @param {Number} r
* @param {Number} p
* @param {Number} len
* @returns {Promise}
*/
async function deriveAsync(passwd, salt, N, r, p, len) {
if (r * p >= (1 << 30))
throw new Error('EFBIG');
if ((N & (N - 1)) !== 0 || N === 0)
throw new Error('EINVAL');
if (N > 0xffffffff)
throw new Error('EINVAL');
const XY = Buffer.allocUnsafe(256 * r);
const V = Buffer.allocUnsafe(128 * r * N);
const B = await pbkdf2.deriveAsync(passwd, salt, 1, p * 128 * r, 'sha256');
for (let i = 0; i < p; i++)
await smixAsync(B, i * 128 * r, r, N, V, XY);
return await pbkdf2.deriveAsync(passwd, B, 1, len, 'sha256');
}
if (native)
deriveAsync = native.scryptAsync;
/*
* Helpers
*/
function salsa20_8(B) {
const B32 = new Uint32Array(16);
const x = new Uint32Array(16);
for (let i = 0; i < 16; i++)
B32[i] = B.readUInt32LE(i * 4, true);
for (let i = 0; i < 16; i++)
x[i] = B32[i];
for (let i = 0; i < 8; i += 2) {
x[4] ^= R(x[0] + x[12], 7);
x[8] ^= R(x[4] + x[0], 9);
x[12] ^= R(x[8] + x[4], 13);
x[0] ^= R(x[12] + x[8], 18);
x[9] ^= R(x[5] + x[1], 7);
x[13] ^= R(x[9] + x[5], 9);
x[1] ^= R(x[13] + x[9], 13);
x[5] ^= R(x[1] + x[13], 18);
x[14] ^= R(x[10] + x[6], 7);
x[2] ^= R(x[14] + x[10], 9);
x[6] ^= R(x[2] + x[14], 13);
x[10] ^= R(x[6] + x[2], 18);
x[3] ^= R(x[15] + x[11], 7);
x[7] ^= R(x[3] + x[15], 9);
x[11] ^= R(x[7] + x[3], 13);
x[15] ^= R(x[11] + x[7], 18);
x[1] ^= R(x[0] + x[3], 7);
x[2] ^= R(x[1] + x[0], 9);
x[3] ^= R(x[2] + x[1], 13);
x[0] ^= R(x[3] + x[2], 18);
x[6] ^= R(x[5] + x[4], 7);
x[7] ^= R(x[6] + x[5], 9);
x[4] ^= R(x[7] + x[6], 13);
x[5] ^= R(x[4] + x[7], 18);
x[11] ^= R(x[10] + x[9], 7);
x[8] ^= R(x[11] + x[10], 9);
x[9] ^= R(x[8] + x[11], 13);
x[10] ^= R(x[9] + x[8], 18);
x[12] ^= R(x[15] + x[14], 7);
x[13] ^= R(x[12] + x[15], 9);
x[14] ^= R(x[13] + x[12], 13);
x[15] ^= R(x[14] + x[13], 18);
}
for (let i = 0; i < 16; i++)
B32[i] += x[i];
for (let i = 0; i < 16; i++)
B.writeUInt32LE(B32[i], 4 * i, true);
}
function R(a, b) {
return (a << b) | (a >>> (32 - b));
}
function blockmix_salsa8(B, Y, Yo, r) {
const X = Buffer.allocUnsafe(64);
blkcpy(X, B, 0, (2 * r - 1) * 64, 64);
for (let i = 0; i < 2 * r; i++) {
blkxor(X, B, 0, i * 64, 64);
salsa20_8(X);
blkcpy(Y, X, Yo + i * 64, 0, 64);
}
for (let i = 0; i < r; i++)
blkcpy(B, Y, i * 64, Yo + (i * 2) * 64, 64);
for (let i = 0; i < r; i++)
blkcpy(B, Y, (i + r) * 64, Yo + (i * 2 + 1) * 64, 64);
}
function integerify(B, r) {
return B.readUInt32LE((2 * r - 1) * 64, true);
}
function smix(B, Bo, r, N, V, XY) {
const X = XY;
const Y = XY;
blkcpy(X, B, 0, Bo, 128 * r);
for (let i = 0; i < N; i++) {
blkcpy(V, X, i * (128 * r), 0, 128 * r);
blockmix_salsa8(X, Y, 128 * r, r);
}
for (let i = 0; i < N; i++) {
const j = integerify(X, r) & (N - 1);
blkxor(X, V, 0, j * (128 * r), 128 * r);
blockmix_salsa8(X, Y, 128 * r, r);
}
blkcpy(B, X, Bo, 0, 128 * r);
}
async function smixAsync(B, Bo, r, N, V, XY) {
const X = XY;
const Y = XY;
blkcpy(X, B, 0, Bo, 128 * r);
for (let i = 0; i < N; i++) {
blkcpy(V, X, i * (128 * r), 0, 128 * r);
blockmix_salsa8(X, Y, 128 * r, r);
await wait();
}
for (let i = 0; i < N; i++) {
const j = integerify(X, r) & (N - 1);
blkxor(X, V, 0, j * (128 * r), 128 * r);
blockmix_salsa8(X, Y, 128 * r, r);
await wait();
}
blkcpy(B, X, Bo, 0, 128 * r);
}
function blkcpy(dest, src, s1, s2, len) {
src.copy(dest, s1, s2, s2 + len);
}
function blkxor(dest, src, s1, s2, len) {
for (let i = 0; i < len; i++)
dest[s1 + i] ^= src[s2 + i];
}
function wait() {
return new Promise(r => setImmediate(r));
}
/*
* Expose
*/
exports.derive = derive;
exports.deriveAsync = deriveAsync;

View File

@ -1,345 +0,0 @@
/*!
* secp256k1-elliptic.js - wrapper for elliptic
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const assert = require('assert');
const elliptic = require('elliptic');
const secp256k1 = elliptic.ec('secp256k1');
const Signature = require('elliptic/lib/elliptic/ec/signature');
const BN = require('./bn');
const curve = secp256k1.curve;
/**
* @exports crypto/secp256k1-elliptic
* @ignore
*/
const ec = exports;
/**
* Whether we're using native bindings.
* @const {Boolean}
*/
ec.binding = false;
/**
* Generate a private key.
* @returns {Buffer} Private key.
*/
ec.generatePrivateKey = function generatePrivateKey() {
const key = secp256k1.genKeyPair();
return key.getPrivate().toArrayLike(Buffer, 'be', 32);
};
/**
* Create a public key from a private key.
* @param {Buffer} priv
* @param {Boolean?} compress
* @returns {Buffer}
*/
ec.publicKeyCreate = function publicKeyCreate(priv, compress) {
if (compress == null)
compress = true;
assert(Buffer.isBuffer(priv));
const key = secp256k1.keyPair({ priv: priv });
return Buffer.from(key.getPublic(compress, 'array'));
};
/**
* Compress or decompress public key.
* @param {Buffer} pub
* @returns {Buffer}
*/
ec.publicKeyConvert = function publicKeyConvert(key, compress) {
if (compress == null)
compress = true;
const point = curve.decodePoint(key);
return Buffer.from(point.encode('array', compress));
};
/**
* ((tweak + key) % n)
* @param {Buffer} privateKey
* @param {Buffer} tweak
* @returns {Buffer} privateKey
*/
ec.privateKeyTweakAdd = function privateKeyTweakAdd(privateKey, tweak) {
const 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, compress) {
if (compress == null)
compress = true;
const key = curve.decodePoint(publicKey);
const point = curve.g.mul(new BN(tweak)).add(key);
const pub = Buffer.from(point.encode('array', compress));
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?} compress
* @returns {Buffer[]|Buffer|null}
*/
ec.recover = function recover(msg, sig, j, compress) {
if (!j)
j = 0;
if (compress == null)
compress = true;
let point;
try {
point = secp256k1.recoverPubKey(msg, sig, j);
} catch (e) {
return null;
}
return Buffer.from(point.encode('array', compress));
};
/**
* Verify a signature.
* @param {Buffer} msg
* @param {Buffer} sig - DER formatted.
* @param {Buffer} key
* @returns {Boolean}
*/
ec.verify = function verify(msg, sig, key) {
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.
// https://github.com/indutny/elliptic/issues/78
sig = normalizeLength(sig);
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 {
const pub = secp256k1.keyPair({ pub: key });
return pub.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.isZero() && key.lt(curve.n);
};
/**
* Sign a message.
* @param {Buffer} msg
* @param {Buffer} key - Private key.
* @returns {Buffer} DER-formatted signature.
*/
ec.sign = function sign(msg, key) {
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(key));
// Sign message and ensure low S value
const sig = secp256k1.sign(msg, key, { canonical: true });
// Convert to DER
return Buffer.from(sig.toDER());
};
/**
* Convert DER signature to R/S.
* @param {Buffer} raw
* @returns {Buffer} R/S-formatted signature.
*/
ec.fromDER = function fromDER(raw) {
assert(Buffer.isBuffer(raw));
const sig = new Signature(raw);
const out = Buffer.allocUnsafe(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(raw) {
assert(Buffer.isBuffer(raw));
const sig = new Signature({
r: new BN(raw.slice(0, 32), 'be'),
s: new BN(raw.slice(32, 64), 'be')
});
return Buffer.from(sig.toDER());
};
/**
* Test whether a signature has a low S value.
* @param {Buffer} sig
* @returns {Boolean}
*/
ec.isLowS = function isLowS(raw) {
let sig;
try {
sig = new Signature(raw);
} catch (e) {
return false;
}
if (sig.s.isZero())
return false;
// If S is greater than half the order,
// it's too high.
if (sig.s.gt(secp256k1.nh))
return false;
return true;
};
/*
* Helpers
*/
function normalizeLength(sig) {
let data = sig;
let pos = 0;
let len;
if (data[pos++] !== 0x30)
return sig;
[len, pos] = getLength(data, pos);
if (data.length > len + pos)
data = data.slice(0, len + pos);
if (data[pos++] !== 0x02)
return sig;
// R length.
[len, pos] = getLength(data, pos);
pos += len;
if (data[pos++] !== 0x02)
return sig;
// S length.
[len, pos] = getLength(data, pos);
if (data.length > len + pos)
data = data.slice(0, len + pos);
return data;
}
function getLength(buf, pos) {
const initial = buf[pos++];
if (!(initial & 0x80))
return [initial, pos];
const len = initial & 0xf;
let val = 0;
for (let i = 0; i < len; i++) {
val <<= 8;
val |= buf[pos++];
}
return [val, pos];
}

View File

@ -1,257 +0,0 @@
/*!
* secp256k1-native.js - wrapper for secp256k1-node
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const assert = require('assert');
const secp256k1 = require('secp256k1');
const random = require('./random');
/**
* @exports crypto/secp256k1
*/
const ec = exports;
/*
* Constants
*/
const ZERO_S = Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'
);
const HALF_ORDER = Buffer.from(
'7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0',
'hex');
/**
* Whether we're using native bindings.
* @const {Boolean}
* @private
*/
ec.binding = true;
/**
* Generate a private key.
* @returns {Buffer} Private key.
*/
ec.generatePrivateKey = function generatePrivateKey() {
let priv;
do {
priv = random.randomBytes(32);
} while (!secp256k1.privateKeyVerify(priv));
return priv;
};
/**
* Create a public key from a private key.
* @param {Buffer} priv
* @param {Boolean?} compress
* @returns {Buffer}
*/
ec.publicKeyCreate = function publicKeyCreate(priv, compress) {
assert(Buffer.isBuffer(priv));
return secp256k1.publicKeyCreate(priv, compress);
};
/**
* Compress or decompress public key.
* @param {Buffer} pub
* @returns {Buffer}
*/
ec.publicKeyConvert = function publicKeyConvert(key, compress) {
return secp256k1.publicKeyConvert(key, compress);
};
/**
* ((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, compress) {
return secp256k1.publicKeyTweakAdd(publicKey, tweak, compress);
};
/**
* Create an ecdh.
* @param {Buffer} pub
* @param {Buffer} priv
* @returns {Buffer}
*/
ec.ecdh = function ecdh(pub, priv) {
const 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?} compress
* @returns {Buffer[]|Buffer|null}
*/
ec.recover = function recover(msg, sig, j, compress) {
if (!j)
j = 0;
try {
sig = secp256k1.signatureImport(sig);
} catch (e) {
return null;
}
let key;
try {
key = secp256k1.recover(msg, sig, j, compress);
} catch (e) {
return null;
}
return key;
};
/**
* Verify a signature.
* @param {Buffer} msg
* @param {Buffer} sig - DER formatted.
* @param {Buffer} key
* @returns {Boolean}
*/
ec.verify = function verify(msg, sig, key) {
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 {
sig = secp256k1.signatureImportLax(sig);
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) {
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(key));
// Sign message
let sig = secp256k1.sign(msg, key);
// Ensure low S value
sig = secp256k1.signatureNormalize(sig.signature);
// Convert to DER
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) {
let s;
try {
const rs = secp256k1.signatureImport(sig);
s = rs.slice(32, 64);
} catch (e) {
return false;
}
if (s.equals(ZERO_S))
return false;
// If S is greater than half the order,
// it's too high.
if (s.compare(HALF_ORDER) > 0)
return false;
return true;
};

View File

@ -1,21 +0,0 @@
/*!
* secp256k1.js - ecdsa wrapper for secp256k1 and elliptic
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
let native;
if (Number(process.env.BCOIN_NO_SECP256K1) !== 1) {
try {
native = require('secp256k1/bindings');
} catch (e) {
;
}
}
module.exports = native
? require('./secp256k1-native')
: require('./secp256k1-browser');

View File

@ -1,399 +0,0 @@
/*!
* sha256.js - SHA256 implementation for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
* Parts of this software based on hash.js.
*/
'use strict';
/**
* @module crypto/sha256
* @ignore
*/
/*
* Constants
*/
const DESC = Buffer.allocUnsafe(8);
const BUFFER64 = Buffer.allocUnsafe(64);
const PADDING = Buffer.allocUnsafe(64);
const K = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];
PADDING.fill(0);
PADDING[0] = 0x80;
/**
* SHA256
* @alias module:crypto/sha256.SHA256
* @constructor
* @property {Number[]} s
* @property {Number[]} w
* @property {Buffer} block
* @property {Number} bytes
*/
function SHA256() {
if (!(this instanceof SHA256))
return new SHA256();
this.s = new Array(8);
this.w = new Array(64);
this.block = Buffer.allocUnsafe(64);
this.bytes = 0;
}
/**
* Initialize SHA256 context.
*/
SHA256.prototype.init = function init() {
this.s[0] = 0x6a09e667;
this.s[1] = 0xbb67ae85;
this.s[2] = 0x3c6ef372;
this.s[3] = 0xa54ff53a;
this.s[4] = 0x510e527f;
this.s[5] = 0x9b05688c;
this.s[6] = 0x1f83d9ab;
this.s[7] = 0x5be0cd19;
this.bytes = 0;
};
/**
* Update SHA256 context.
* @param {Buffer} data
*/
SHA256.prototype.update = function update(data) {
return this._update(data, data.length);
};
/**
* Finalize SHA256 context.
* @returns {Buffer}
*/
SHA256.prototype.finish = function finish() {
return this._finish(Buffer.allocUnsafe(32));
};
/**
* Update SHA256 context.
* @private
* @param {Buffer} data
* @param {Number} len
*/
SHA256.prototype._update = function _update(data, len) {
let size = this.bytes & 0x3f;
let pos = 0;
this.bytes += len;
if (size > 0) {
let want = 64 - size;
if (want > len)
want = len;
for (let i = 0; i < want; i++)
this.block[size + i] = data[i];
size += want;
len -= want;
pos += want;
if (size < 64)
return;
this.transform(this.block, 0);
}
while (len >= 64) {
this.transform(data, pos);
pos += 64;
len -= 64;
}
for (let i = 0; i < len; i++)
this.block[i] = data[pos + i];
};
/**
* Finalize SHA256 context.
* @private
* @param {Buffer} out
* @returns {Buffer}
*/
SHA256.prototype._finish = function _finish(out) {
writeU32(DESC, this.bytes >>> 29, 0);
writeU32(DESC, this.bytes << 3, 4);
this._update(PADDING, 1 + ((119 - (this.bytes % 64)) % 64));
this._update(DESC, 8);
for (let i = 0; i < 8; i++) {
writeU32(out, this.s[i], i * 4);
this.s[i] = 0;
}
return out;
};
/**
* Transform SHA256 block.
* @param {Buffer} chunk
* @param {Number} pos
*/
SHA256.prototype.transform = function transform(chunk, pos) {
const w = this.w;
let a = this.s[0];
let b = this.s[1];
let c = this.s[2];
let d = this.s[3];
let e = this.s[4];
let f = this.s[5];
let g = this.s[6];
let h = this.s[7];
let i = 0;
for (; i < 16; i++)
w[i] = readU32(chunk, pos + i * 4);
for (; i < 64; i++)
w[i] = sigma1(w[i - 2]) + w[i - 7] + sigma0(w[i - 15]) + w[i - 16];
for (i = 0; i < 64; i++) {
let t1 = h + Sigma1(e);
t1 += Ch(e, f, g);
t1 += K[i] + w[i];
let t2 = Sigma0(a);
t2 += Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
this.s[0] += a;
this.s[1] += b;
this.s[2] += c;
this.s[3] += d;
this.s[4] += e;
this.s[5] += f;
this.s[6] += g;
this.s[7] += h;
this.s[0] >>>= 0;
this.s[1] >>>= 0;
this.s[2] >>>= 0;
this.s[3] >>>= 0;
this.s[4] >>>= 0;
this.s[5] >>>= 0;
this.s[6] >>>= 0;
this.s[7] >>>= 0;
};
/**
* SHA256Hmac
* @alias module:crypto/sha256.SHA256Hmac
* @constructor
* @property {SHA256} inner
* @property {SHA256} outer
*/
function SHA256Hmac() {
if (!(this instanceof SHA256Hmac))
return new SHA256Hmac();
this.inner = new SHA256();
this.outer = new SHA256();
}
/**
* Initialize HMAC context.
* @param {Buffer} data
*/
SHA256Hmac.prototype.init = function init(data) {
const key = BUFFER64;
if (data.length > 64) {
this.inner.init();
this.inner.update(data);
this.inner._finish(key);
key.fill(0, 32, 64);
} else {
data.copy(key, 0);
key.fill(0, data.length, 64);
}
for (let i = 0; i < key.length; i++)
key[i] ^= 0x36;
this.inner.init();
this.inner.update(key);
for (let i = 0; i < key.length; i++)
key[i] ^= 0x6a;
this.outer.init();
this.outer.update(key);
};
/**
* Update HMAC context.
* @param {Buffer} data
*/
SHA256Hmac.prototype.update = function update(data) {
this.inner.update(data);
};
/**
* Finalize HMAC context.
* @returns {Buffer}
*/
SHA256Hmac.prototype.finish = function finish() {
this.outer.update(this.inner.finish());
return this.outer.finish();
};
/*
* Helpers
* @see https://github.com/bitcoin-core/secp256k1/blob/master/src/hash_impl.h
*/
function Sigma0(x) {
return (x >>> 2 | x << 30) ^ (x >>> 13 | x << 19) ^ (x >>> 22 | x << 10);
}
function Sigma1(x) {
return (x >>> 6 | x << 26) ^ (x >>> 11 | x << 21) ^ (x >>> 25 | x << 7);
}
function sigma0(x) {
return (x >>> 7 | x << 25) ^ (x >>> 18 | x << 14) ^ (x >>> 3);
}
function sigma1(x) {
return (x >>> 17 | x << 15) ^ (x >>> 19 | x << 13) ^ (x >>> 10);
}
function Ch(x, y, z) {
return z ^ (x & (y ^ z));
}
function Maj(x, y, z) {
return (x & y) | (z & (x | y));
}
function writeU32(buf, value, offset) {
buf[offset] = value >>> 24;
buf[offset + 1] = (value >> 16) & 0xff;
buf[offset + 2] = (value >> 8) & 0xff;
buf[offset + 3] = value & 0xff;
}
function readU32(buf, offset) {
return ((buf[offset] & 0xff) * 0x1000000)
+ ((buf[offset + 1] & 0xff) << 16)
| ((buf[offset + 2] & 0xff) << 8)
| (buf[offset + 3] & 0xff);
}
/*
* Context Helpers
*/
const ctx = new SHA256();
const mctx = new SHA256Hmac();
/**
* Hash buffer with sha256.
* @alias module:crypto/sha256.sha256
* @param {Buffer} data
* @returns {Buffer}
*/
function sha256(data) {
ctx.init();
ctx.update(data);
return ctx.finish();
}
/**
* Hash buffer with double sha256.
* @alias module:crypto/sha256.hash256
* @param {Buffer} data
* @returns {Buffer}
*/
function hash256(data) {
const out = Buffer.allocUnsafe(32);
ctx.init();
ctx.update(data);
ctx._finish(out);
ctx.init();
ctx.update(out);
ctx._finish(out);
return out;
}
/**
* Create a sha256 HMAC from buffer and key.
* @alias module:crypto/sha256.hmac
* @param {Buffer} data
* @param {Buffer} key
* @returns {Buffer}
*/
function hmac(data, key) {
mctx.init(key);
mctx.update(data);
return mctx.finish();
}
/*
* Expose
*/
exports = SHA256;
exports.SHA256 = SHA256;
exports.SHA256Hmac = SHA256Hmac;
exports.digest = sha256;
exports.hmac = hmac;
exports.hash256 = hash256;
module.exports = exports;

View File

@ -1,304 +0,0 @@
/*!
* siphash.js - siphash for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*
* Ported from:
* https://github.com/bitcoin/bitcoin/blob/master/src/hash.cpp
*/
'use strict';
/**
* @module crypto/siphash
*/
const native = require('../native').binding;
/**
* Javascript siphash 2-4 implementation.
* @private
* @param {Buffer} data
* @param {Buffer} key - 128 bit key.
* @param {Number} shift
* @returns {Array} [hi, lo]
*/
function _siphash(data, key, shift) {
const blocks = Math.floor(data.length / 8);
const c0 = U64(0x736f6d65, 0x70736575);
const c1 = U64(0x646f7261, 0x6e646f6d);
const c2 = U64(0x6c796765, 0x6e657261);
const c3 = U64(0x74656462, 0x79746573);
const f0 = U64(blocks << (shift - 32), 0);
const f1 = U64(0, 0xff);
const k0 = U64.fromRaw(key, 0);
const k1 = U64.fromRaw(key, 8);
// Init
const v0 = c0.ixor(k0);
const v1 = c1.ixor(k1);
const v2 = c2.ixor(k0);
const v3 = c3.ixor(k1);
// Blocks
let p = 0;
for (let i = 0; i < blocks; i++) {
const d = U64.fromRaw(data, p);
p += 8;
v3.ixor(d);
sipround(v0, v1, v2, v3);
sipround(v0, v1, v2, v3);
v0.ixor(d);
}
switch (data.length & 7) {
case 7:
f0.hi |= data[p + 6] << 16;
case 6:
f0.hi |= data[p + 5] << 8;
case 5:
f0.hi |= data[p + 4];
case 4:
f0.lo |= data[p + 3] << 24;
case 3:
f0.lo |= data[p + 2] << 16;
case 2:
f0.lo |= data[p + 1] << 8;
case 1:
f0.lo |= data[p];
}
// Finalization
v3.ixor(f0);
sipround(v0, v1, v2, v3);
sipround(v0, v1, v2, v3);
v0.ixor(f0);
v2.ixor(f1);
sipround(v0, v1, v2, v3);
sipround(v0, v1, v2, v3);
sipround(v0, v1, v2, v3);
sipround(v0, v1, v2, v3);
v0.ixor(v1);
v0.ixor(v2);
v0.ixor(v3);
return [v0.hi, v0.lo];
}
/**
* Javascript siphash 2-4 implementation (64 bit ints).
* @private
* @param {Number} hi
* @param {Number} lo
* @param {Buffer} key - 128 bit key.
* @returns {Array} [hi, lo]
*/
function _siphash64(hi, lo, key) {
const c0 = U64(0x736f6d65, 0x70736575);
const c1 = U64(0x646f7261, 0x6e646f6d);
const c2 = U64(0x6c796765, 0x6e657261);
const c3 = U64(0x74656462, 0x79746573);
const f0 = U64(hi, lo);
const f1 = U64(0, 0xff);
const k0 = U64.fromRaw(key, 0);
const k1 = U64.fromRaw(key, 8);
// Init
const v0 = c0.ixor(k0);
const v1 = c1.ixor(k1);
const v2 = c2.ixor(k0);
const v3 = c3.ixor(k1);
// Finalization
v3.ixor(f0);
sipround(v0, v1, v2, v3);
sipround(v0, v1, v2, v3);
v0.ixor(f0);
v2.ixor(f1);
sipround(v0, v1, v2, v3);
sipround(v0, v1, v2, v3);
sipround(v0, v1, v2, v3);
sipround(v0, v1, v2, v3);
v0.ixor(v1);
v0.ixor(v2);
v0.ixor(v3);
return [v0.hi, v0.lo];
}
/**
* Javascript siphash 2-4 implementation (shift=56).
* @alias module:crypto/siphash.siphash
* @param {Buffer} data
* @param {Buffer} key - 128 bit key.
* @returns {Array} [hi, lo]
*/
function siphash(data, key) {
return _siphash(data, key, 56);
}
/**
* Javascript siphash 2-4 implementation (shift=59).
* @alias module:crypto/siphash.siphash256
* @param {Buffer} data
* @param {Buffer} key - 128 bit key.
* @returns {Array} [hi, lo]
*/
function siphash256(data, key) {
return _siphash(data, key, 59);
}
/**
* Javascript siphash 2-4 implementation (32 bit ints).
* @alias module:crypto/siphash.siphash32
* @param {Number} num
* @param {Buffer} key - 128 bit key.
* @returns {Number}
*/
function siphash32(num, key) {
return _siphash64(0, num, key)[1];
}
/**
* Javascript siphash 2-4 implementation (64 bit ints).
* @alias module:crypto/siphash.siphash64
* @param {Number} hi
* @param {Number} lo
* @param {Buffer} key - 128 bit key.
* @returns {Array} [hi, lo]
*/
function siphash64(hi, lo, key) {
return _siphash64(hi, lo, key);
}
if (native) {
siphash = native.siphash;
siphash256 = native.siphash256;
siphash32 = native.siphash32;
siphash64 = native.siphash64;
}
/*
* U64
* @constructor
* @ignore
*/
function U64(hi, lo) {
if (!(this instanceof U64))
return new U64(hi, lo);
this.hi = hi | 0;
this.lo = lo | 0;
}
U64.prototype.iadd = function iadd(b) {
const a = this;
// Credit to @indutny for this method.
const lo = (a.lo + b.lo) | 0;
const s = lo >> 31;
const as = a.lo >> 31;
const bs = b.lo >> 31;
const c = ((as & bs) | (~s & (as ^ bs))) & 1;
const hi = ((a.hi + b.hi) | 0) + c;
a.hi = hi | 0;
a.lo = lo;
return a;
};
U64.prototype.ixor = function ixor(b) {
this.hi ^= b.hi;
this.lo ^= b.lo;
return this;
};
U64.prototype.irotl = function irotl(bits) {
let ahi = this.hi;
let alo = this.lo;
let bhi = this.hi;
let blo = this.lo;
// a = x << b
if (bits < 32) {
ahi <<= bits;
ahi |= alo >>> (32 - bits);
alo <<= bits;
} else {
ahi = alo << (bits - 32);
alo = 0;
}
bits = 64 - bits;
// b = x >> (64 - b)
if (bits < 32) {
blo >>>= bits;
blo |= bhi << (32 - bits);
bhi >>>= bits;
} else {
blo = bhi >>> (bits - 32);
bhi = 0;
}
// a | b
this.hi = ahi | bhi;
this.lo = alo | blo;
return this;
};
U64.fromRaw = function fromRaw(data, off) {
const lo = data.readUInt32LE(off, true);
const hi = data.readUInt32LE(off + 4, true);
return new U64(hi, lo);
};
/*
* Helpers
*/
function sipround(v0, v1, v2, v3) {
v0.iadd(v1);
v1.irotl(13);
v1.ixor(v0);
v0.irotl(32);
v2.iadd(v3);
v3.irotl(16);
v3.ixor(v2);
v0.iadd(v3);
v3.irotl(21);
v3.ixor(v0);
v2.iadd(v1);
v1.irotl(17);
v1.ixor(v2);
v2.irotl(32);
}
/*
* Expose
*/
exports = siphash;
exports.siphash = siphash;
exports.siphash256 = siphash256;
exports.siphash32 = siphash32;
exports.siphash64 = siphash64;
module.exports = exports;

View File

@ -8,10 +8,11 @@
const assert = require('assert');
const util = require('../utils/util');
const digest = require('../crypto/digest');
const cleanse = require('../crypto/cleanse');
const random = require('../crypto/random');
const pbkdf2 = require('../crypto/pbkdf2');
const digest = require('bcrypto/lib/digest');
const cleanse = require('bcrypto/lib/cleanse');
const random = require('bcrypto/lib/random');
const pbkdf2 = require('bcrypto/lib/pbkdf2');
const sha512 = require('bcrypto/lib/sha512');
const StaticWriter = require('../utils/staticwriter');
const BufferReader = require('../utils/reader');
const encoding = require('../utils/encoding');
@ -154,10 +155,10 @@ Mnemonic.prototype.toSeed = function toSeed(passphrase) {
const phrase = nfkd(this.getPhrase());
const passwd = nfkd('mnemonic' + passphrase);
return pbkdf2.derive(
return pbkdf2.derive(sha512,
Buffer.from(phrase, 'utf8'),
Buffer.from(passwd, 'utf8'),
2048, 64, 'sha512');
2048, 64);
};
/**

View File

@ -8,10 +8,10 @@
const assert = require('assert');
const util = require('../utils/util');
const digest = require('../crypto/digest');
const cleanse = require('../crypto/cleanse');
const random = require('../crypto/random');
const secp256k1 = require('../crypto/secp256k1');
const digest = require('bcrypto/lib/digest');
const cleanse = require('bcrypto/lib/cleanse');
const random = require('bcrypto/lib/random');
const secp256k1 = require('bcrypto/lib/secp256k1');
const Network = require('../protocol/network');
const StaticWriter = require('../utils/staticwriter');
const BufferReader = require('../utils/reader');

View File

@ -8,9 +8,9 @@
const assert = require('assert');
const util = require('../utils/util');
const digest = require('../crypto/digest');
const cleanse = require('../crypto/cleanse');
const secp256k1 = require('../crypto/secp256k1');
const digest = require('bcrypto/lib/digest');
const cleanse = require('bcrypto/lib/cleanse');
const secp256k1 = require('bcrypto/lib/secp256k1');
const Network = require('../protocol/network');
const StaticWriter = require('../utils/staticwriter');
const BufferReader = require('../utils/reader');

View File

@ -10,10 +10,10 @@ const assert = require('assert');
const bweb = require('bweb');
const util = require('../utils/util');
const co = require('../utils/co');
const digest = require('../crypto/digest');
const ccmp = require('../crypto/ccmp');
const digest = require('bcrypto/lib/digest');
const ccmp = require('bcrypto/lib/ccmp');
const common = require('../blockchain/common');
const secp256k1 = require('../crypto/secp256k1');
const secp256k1 = require('bcrypto/lib/secp256k1');
const Amount = require('../btc/amount');
const NetAddress = require('../primitives/netaddress');
const Script = require('../script/script');

View File

@ -15,9 +15,9 @@ const base58 = require('../utils/base58');
const Bloom = require('../utils/bloom');
const TX = require('../primitives/tx');
const Outpoint = require('../primitives/outpoint');
const digest = require('../crypto/digest');
const random = require('../crypto/random');
const ccmp = require('../crypto/ccmp');
const digest = require('bcrypto/lib/digest');
const random = require('bcrypto/lib/random');
const ccmp = require('bcrypto/lib/ccmp');
const Network = require('../protocol/network');
const Validator = require('../utils/validator');
const pkg = require('../pkg');

View File

@ -13,7 +13,7 @@ const common = require('../blockchain/common');
const consensus = require('../protocol/consensus');
const policy = require('../protocol/policy');
const util = require('../utils/util');
const random = require('../crypto/random');
const random = require('bcrypto/lib/random');
const {VerifyError} = require('../protocol/errors');
const RollingFilter = require('../utils/rollingfilter');
const Address = require('../primitives/address');

View File

@ -8,7 +8,7 @@
const assert = require('assert');
const consensus = require('../protocol/consensus');
const BN = require('../crypto/bn');
const BN = require('bcrypto/lib/bn');
/**
* @exports mining/common

View File

@ -7,7 +7,7 @@
'use strict';
const assert = require('assert');
const digest = require('../crypto/digest');
const digest = require('bcrypto/lib/digest');
/**
* Hash until the nonce overflows.

View File

@ -9,8 +9,8 @@
const assert = require('assert');
const util = require('../utils/util');
const digest = require('../crypto/digest');
const merkle = require('../crypto/merkle');
const hash256 = require('bcrypto/lib/hash256');
const merkle = require('bcrypto/lib/merkle');
const StaticWriter = require('../utils/staticwriter');
const Address = require('../primitives/address');
const TX = require('../primitives/tx');
@ -178,11 +178,11 @@ BlockTemplate.prototype.getWitnessHash = function getWitnessHash() {
for (const item of this.items)
leaves.push(item.tx.witnessHash());
const [root, malleated] = merkle.createRoot(leaves);
const [root, malleated] = merkle.createRoot(hash256, leaves);
assert(!malleated);
return digest.root256(root, nonce);
return hash256.root(root, nonce);
};
/**
@ -381,7 +381,7 @@ BlockTemplate.prototype.getRawCoinbase = function getRawCoinbase(nonce1, nonce2)
BlockTemplate.prototype.getRoot = function getRoot(nonce1, nonce2) {
const raw = this.getRawCoinbase(nonce1, nonce2);
const hash = digest.hash256(raw);
const hash = hash256.digest(raw);
return this.tree.withFirst(hash);
};
@ -418,7 +418,7 @@ BlockTemplate.prototype.getHeader = function getHeader(root, time, nonce) {
BlockTemplate.prototype.getProof = function getProof(nonce1, nonce2, time, nonce) {
const root = this.getRoot(nonce1, nonce2);
const data = this.getHeader(root, time, nonce);
const hash = digest.hash256(data);
const hash = hash256.digest(data);
return new BlockProof(hash, root, nonce1, nonce2, time, nonce);
};
@ -685,7 +685,7 @@ function MerkleTree() {
MerkleTree.prototype.withFirst = function withFirst(hash) {
for (const step of this.steps)
hash = digest.root256(hash, step);
hash = hash256.root(hash, step);
return hash;
};
@ -742,7 +742,7 @@ MerkleTree.prototype.fromLeaves = function fromLeaves(leaves) {
leaves.push(leaves[len - 1]);
for (let i = 2; i < len; i += 2) {
const hash = digest.root256(leaves[i], leaves[i + 1]);
const hash = hash256.root(leaves[i], leaves[i + 1]);
hashes.push(hash);
}

View File

@ -12,11 +12,11 @@ const assert = require('assert');
const path = require('path');
const EventEmitter = require('events');
const co = require('../utils/co');
const digest = require('../crypto/digest');
const random = require('../crypto/random');
const ccmp = require('../crypto/ccmp');
const digest = require('bcrypto/lib/digest');
const random = require('bcrypto/lib/random');
const ccmp = require('bcrypto/lib/ccmp');
const packets = require('./packets');
const secp256k1 = require('../crypto/secp256k1');
const secp256k1 = require('bcrypto/lib/secp256k1');
const StaticWriter = require('../utils/staticwriter');
const base58 = require('../utils/base58');
const encoding = require('../utils/encoding');

View File

@ -16,12 +16,13 @@ const assert = require('assert');
const EventEmitter = require('events');
const util = require('../utils/util');
const co = require('../utils/co');
const digest = require('../crypto/digest');
const ChaCha20 = require('../crypto/chacha20');
const Poly1305 = require('../crypto/poly1305');
const AEAD = require('../crypto/aead');
const hkdf = require('../crypto/hkdf');
const secp256k1 = require('../crypto/secp256k1');
const hash256 = require('bcrypto/lib/hash256');
const sha256 = require('bcrypto/lib/sha256');
const ChaCha20 = require('bcrypto/lib/chacha20');
const Poly1305 = require('bcrypto/lib/poly1305');
const AEAD = require('bcrypto/lib/aead');
const hkdf = require('bcrypto/lib/hkdf');
const secp256k1 = require('bcrypto/lib/secp256k1');
const packets = require('./packets');
const StaticWriter = require('../utils/staticwriter');
const BufferReader = require('../utils/reader');
@ -104,11 +105,11 @@ BIP151Stream.prototype.init = function init(publicKey) {
bw.writeU8(this.cipher);
const data = bw.render();
const prk = hkdf.extract(data, HKDF_SALT, 'sha256');
const prk = hkdf.extract(sha256, data, HKDF_SALT);
this.k1 = hkdf.expand(prk, INFO_KEY1, 32, 'sha256');
this.k2 = hkdf.expand(prk, INFO_KEY2, 32, 'sha256');
this.sid = hkdf.expand(prk, INFO_SID, 32, 'sha256');
this.k1 = hkdf.expand(sha256, prk, INFO_KEY1, 32);
this.k2 = hkdf.expand(sha256, prk, INFO_KEY2, 32);
this.sid = hkdf.expand(sha256, prk, INFO_SID, 32);
this.seq = 0;
@ -151,8 +152,8 @@ BIP151Stream.prototype.rekey = function rekey(k1, k2) {
assert(this.sid, 'Cannot rekey before initialization.');
if (!k1) {
this.k1 = digest.root256(this.sid, this.k1);
this.k2 = digest.root256(this.sid, this.k2);
this.k1 = hash256.root(this.sid, this.k1);
this.k2 = hash256.root(this.sid, this.k2);
} else {
this.k1 = k1;
this.k2 = k2;
@ -263,8 +264,8 @@ BIP151Stream.prototype.auth = function auth(data) {
* @returns {Buffer}
*/
BIP151Stream.prototype.finish = function finish() {
this.tag = this.aead.finish();
BIP151Stream.prototype.final = function final() {
this.tag = this.aead.final();
return this.tag;
};
@ -608,7 +609,7 @@ BIP151.prototype.packet = function packet(cmd, body) {
this.output.encryptSize(msg);
this.output.encrypt(payload);
this.output.finish().copy(msg, 4 + payloadSize);
this.output.final().copy(msg, 4 + payloadSize);
this.output.sequence();
return msg;
@ -719,7 +720,7 @@ BIP151.prototype.parse = function parse(data) {
// This ensures the cipher state isn't altered
// if the payload integrity has been compromised.
this.input.auth(payload);
this.input.finish();
this.input.final();
if (!this.input.verify(tag)) {
this.input.sequence();

View File

@ -16,8 +16,8 @@ const BufferReader = require('../utils/reader');
const StaticWriter = require('../utils/staticwriter');
const encoding = require('../utils/encoding');
const consensus = require('../protocol/consensus');
const digest = require('../crypto/digest');
const siphash256 = require('../crypto/siphash').siphash256;
const digest = require('bcrypto/lib/digest');
const siphash256 = require('bcrypto/lib/siphash').siphash256;
const AbstractBlock = require('../primitives/abstractblock');
const TX = require('../primitives/tx');
const Headers = require('../primitives/headers');

View File

@ -9,7 +9,7 @@
const assert = require('assert');
const Network = require('../protocol/network');
const digest = require('../crypto/digest');
const digest = require('bcrypto/lib/digest');
/**
* Protocol packet framer

View File

@ -13,7 +13,7 @@ const assert = require('assert');
const EventEmitter = require('events');
const Network = require('../protocol/network');
const util = require('../utils/util');
const digest = require('../crypto/digest');
const digest = require('bcrypto/lib/digest');
const common = require('./common');
const packets = require('./packets');

View File

@ -21,7 +21,7 @@ const BIP151 = require('./bip151');
const BIP152 = require('./bip152');
const Bloom = require('../utils/bloom');
const RollingFilter = require('../utils/rollingfilter');
const secp256k1 = require('../crypto/secp256k1');
const secp256k1 = require('bcrypto/lib/secp256k1');
const Lock = require('../utils/lock');
const Network = require('../protocol/network');
const Peer = require('./peer');

View File

@ -10,7 +10,7 @@ const assert = require('assert');
const EventEmitter = require('events');
const bsock = require('bsock');
const util = require('../utils/util');
const digest = require('../crypto/digest');
const digest = require('bcrypto/lib/digest');
const BufferWriter = require('../utils/writer');
function ProxySocket(uri) {

View File

@ -13,7 +13,7 @@ const util = require('../utils/util');
const Network = require('../protocol/network');
const Logger = require('./logger');
const WorkerPool = require('../workers/workerpool');
const secp256k1 = require('../crypto/secp256k1');
const secp256k1 = require('bcrypto/lib/secp256k1');
const native = require('../native');
const Config = require('./config');

View File

@ -9,7 +9,7 @@
const assert = require('assert');
const util = require('../utils/util');
const digest = require('../crypto/digest');
const digest = require('bcrypto/lib/digest');
const BufferReader = require('../utils/reader');
const StaticWriter = require('../utils/staticwriter');
const InvItem = require('./invitem');

View File

@ -11,7 +11,7 @@ const assert = require('assert');
const Network = require('../protocol/network');
const encoding = require('../utils/encoding');
const util = require('../utils/util');
const digest = require('../crypto/digest');
const digest = require('bcrypto/lib/digest');
const BufferReader = require('../utils/reader');
const StaticWriter = require('../utils/staticwriter');
const base58 = require('../utils/base58');

View File

@ -10,8 +10,8 @@
const assert = require('assert');
const util = require('../utils/util');
const encoding = require('../utils/encoding');
const digest = require('../crypto/digest');
const merkle = require('../crypto/merkle');
const hash256 = require('bcrypto/lib/hash256');
const merkle = require('bcrypto/lib/merkle');
const consensus = require('../protocol/consensus');
const AbstractBlock = require('./abstractblock');
const BufferReader = require('../utils/reader');
@ -280,7 +280,7 @@ Block.prototype.createMerkleRoot = function createMerkleRoot(enc) {
for (const tx of this.txs)
leaves.push(tx.hash());
const [root, malleated] = merkle.createRoot(leaves);
const [root, malleated] = merkle.createRoot(hash256, leaves);
if (malleated)
return null;
@ -317,12 +317,12 @@ Block.prototype.createCommitmentHash = function createCommitmentHash(enc) {
leaves.push(tx.witnessHash());
}
const [root] = merkle.createRoot(leaves);
const [root] = merkle.createRoot(hash256, leaves);
// Note: malleation check ignored here.
// assert(!malleated);
const hash = digest.root256(root, nonce);
const hash = hash256.root(root, nonce);
return enc === 'hex'
? hash.toString('hex')

View File

@ -9,7 +9,7 @@
const assert = require('assert');
const encoding = require('../utils/encoding');
const digest = require('../crypto/digest');
const digest = require('bcrypto/lib/digest');
const Network = require('../protocol/network');
const BufferReader = require('../utils/reader');
const StaticWriter = require('../utils/staticwriter');
@ -17,7 +17,7 @@ const base58 = require('../utils/base58');
const Script = require('../script/script');
const Address = require('./address');
const Output = require('./output');
const secp256k1 = require('../crypto/secp256k1');
const secp256k1 = require('bcrypto/lib/secp256k1');
/**
* Represents a key ring which amounts to an address.

View File

@ -12,7 +12,7 @@ const util = require('../utils/util');
const BufferReader = require('../utils/reader');
const StaticWriter = require('../utils/staticwriter');
const encoding = require('../utils/encoding');
const digest = require('../crypto/digest');
const hash256 = require('bcrypto/lib/hash256');
const consensus = require('../protocol/consensus');
const AbstractBlock = require('./abstractblock');
const Headers = require('./headers');
@ -238,7 +238,7 @@ MerkleBlock.prototype.extractTree = function extractTree() {
right = left;
}
return digest.root256(left, right);
return hash256.root(left, right);
};
if (totalTX === 0)
@ -571,7 +571,7 @@ MerkleBlock.fromMatches = function fromMatches(block, matches) {
else
right = left;
return digest.root256(left, right);
return hash256.root(left, right);
};
const traverse = (height, pos, leaves, matches) => {

View File

@ -10,8 +10,8 @@
const assert = require('assert');
const util = require('../utils/util');
const encoding = require('../utils/encoding');
const digest = require('../crypto/digest');
const secp256k1 = require('../crypto/secp256k1');
const digest = require('bcrypto/lib/digest');
const secp256k1 = require('bcrypto/lib/secp256k1');
const Amount = require('../btc/amount');
const Network = require('../protocol/network');
const Script = require('../script/script');

View File

@ -12,7 +12,7 @@
*/
const assert = require('assert');
const BN = require('../crypto/bn');
const BN = require('bcrypto/lib/bn');
/**
* One bitcoin in satoshis.

View File

@ -11,7 +11,7 @@
* @module protocol/networks
*/
const BN = require('../crypto/bn');
const BN = require('bcrypto/lib/bn');
const network = exports;

View File

@ -13,7 +13,7 @@
const assert = require('assert');
const util = require('../utils/util');
const secp256k1 = require('../crypto/secp256k1');
const secp256k1 = require('bcrypto/lib/secp256k1');
const ScriptNum = require('./scriptnum');
/**

View File

@ -11,8 +11,8 @@ const assert = require('assert');
const consensus = require('../protocol/consensus');
const policy = require('../protocol/policy');
const util = require('../utils/util');
const digest = require('../crypto/digest');
const merkle = require('../crypto/merkle');
const digest = require('bcrypto/lib/digest');
const merkle = require('bcrypto/lib/merkle');
const BufferWriter = require('../utils/writer');
const BufferReader = require('../utils/reader');
const StaticWriter = require('../utils/staticwriter');
@ -23,7 +23,7 @@ const ScriptError = require('./scripterror');
const ScriptNum = require('./scriptnum');
const common = require('./common');
const encoding = require('../utils/encoding');
const secp256k1 = require('../crypto/secp256k1');
const secp256k1 = require('bcrypto/lib/secp256k1');
const Address = require('../primitives/address');
const opcodes = common.opcodes;
const scriptTypes = common.types;

View File

@ -8,7 +8,7 @@
const assert = require('assert');
const util = require('../utils/util');
const secp256k1 = require('../crypto/secp256k1');
const secp256k1 = require('bcrypto/lib/secp256k1');
/**
* Signature cache.

View File

@ -1,548 +0,0 @@
/*!
* asn1.js - asn1 parsing for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*
* Parts of this software are based on asn1.js.
* https://github.com/indutny/asn1.js
*
* Copyright Fedor Indutny, 2013.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
'use strict';
const BufferReader = require('./reader');
/**
* @exports utils/asn1
*/
const ASN1 = exports;
/**
* Read next tag.
* @param {BufferReader} br
* @returns {Object}
*/
ASN1.readTag = function readTag(br) {
let type = br.readU8();
const primitive = (type & 0x20) === 0;
if ((type & 0x1f) === 0x1f) {
let oct = type;
type = 0;
while ((oct & 0x80) === 0x80) {
oct = br.readU8();
type <<= 7;
type |= oct & 0x7f;
}
} else {
type &= 0x1f;
}
return {
type: type,
primitive: primitive,
size: ASN1.readSize(br, primitive)
};
};
/**
* Read tag size.
* @param {BufferReader} br
* @param {Boolean} primitive
* @returns {Number}
* @throws on indefinite size
*/
ASN1.readSize = function readSize(br, primitive) {
let size = br.readU8();
// Indefinite form
if (!primitive && size === 0x80)
throw new Error('Indefinite size.');
// Definite form
if ((size & 0x80) === 0) {
// Short form
return size;
}
// Long form
const bytes = size & 0x7f;
if (bytes > 3)
throw new Error('Length octet is too long.');
size = 0;
for (let i = 0; i < bytes; i++) {
size <<= 8;
size |= br.readU8();
}
return size;
};
/**
* Read implicit SEQ.
* @param {BufferReader} br
* @returns {Buffer}
*/
ASN1.readSeq = function readSeq(br) {
const tag = ASN1.implicit(br, 0x10);
return br.readBytes(tag.size);
};
/**
* Read next tag and assert implicit.
* @param {BufferReader} br
* @param {Number} type
* @returns {Object}
* @throws on unexpected tag
*/
ASN1.implicit = function implicit(br, type) {
const tag = ASN1.readTag(br);
if (tag.type !== type)
throw new Error(`Unexpected tag: ${tag.type}.`);
return tag;
};
/**
* Read implicit tag.
* @param {BufferReader} br
* @param {Number} type
* @returns {Boolean}
*/
ASN1.explicit = function explicit(br, type) {
const offset = br.offset;
const tag = ASN1.readTag(br);
if (tag.type !== type) {
br.offset = offset;
return false;
}
return true;
};
/**
* Read next implicit SEQ and return a new reader.
* @param {BufferReader} br
* @returns {BufferReader}
*/
ASN1.seq = function seq(br) {
return new BufferReader(ASN1.readSeq(br), true);
};
/**
* Read implicit int.
* @param {BufferReader} br
* @param {Boolean?} cast
* @returns {Buffer|Number}
*/
ASN1.readInt = function readInt(br, cast) {
const tag = ASN1.implicit(br, 0x02);
const num = br.readBytes(tag.size);
if (cast)
return num.readUIntBE(0, num.length);
return num;
};
/**
* Read explicit int.
* @param {BufferReader} br
* @param {Number} type
* @param {Boolean?} readNum
* @returns {Buffer|Number} `-1` on not present.
*/
ASN1.readExplicitInt = function readExplicitInt(br, type, readNum) {
if (!ASN1.explicit(br, type))
return -1;
return ASN1.readInt(br, readNum);
};
/**
* Read and align an implicit bitstr.
* @param {BufferReader} br
* @returns {Buffer}
*/
ASN1.readBitstr = function readBitstr(br) {
const tag = ASN1.implicit(br, 0x03);
const str = br.readBytes(tag.size);
return ASN1.alignBitstr(str);
};
/**
* Read an implicit string (any type).
* @param {BufferReader} br
* @returns {String}
*/
ASN1.readString = function readString(br) {
const tag = ASN1.readTag(br);
switch (tag.type) {
case 0x03: { // bitstr
const str = br.readBytes(tag.size);
return ASN1.alignBitstr(str).toString('utf8');
}
// Note:
// Fuck all these.
case 0x04: // octstr
case 0x12: // numstr
case 0x13: // prinstr
case 0x14: // t61str
case 0x15: // videostr
case 0x16: // ia5str
case 0x19: // graphstr
case 0x0c: // utf8str
case 0x1a: // iso646str
case 0x1b: // genstr
case 0x1c: // unistr
case 0x1d: // charstr
case 0x1e: { // bmpstr
return br.readString('utf8', tag.size);
}
default: {
throw new Error(`Unexpected tag: ${tag.type}.`);
}
}
};
/**
* Align a bitstr.
* @param {Buffer} data
* @returns {Buffer}
*/
ASN1.alignBitstr = function alignBitstr(data) {
const padding = data[0];
const bits = (data.length - 1) * 8 - padding;
const buf = data.slice(1);
const shift = 8 - (bits % 8);
if (shift === 8 || buf.length === 0)
return buf;
const out = Buffer.allocUnsafe(buf.length);
out[0] = buf[0] >>> shift;
for (let i = 1; i < buf.length; i++) {
out[i] = buf[i - 1] << (8 - shift);
out[i] |= buf[i] >>> shift;
}
return out;
};
/**
* Read an entire certificate.
* @param {BufferReader} br
* @returns {Object}
*/
ASN1.readCert = function readCert(br) {
const buf = br;
buf.start();
br = ASN1.seq(buf);
return {
tbs: ASN1.readTBS(br),
sigAlg: ASN1.readAlgIdent(br),
sig: ASN1.readBitstr(br),
raw: buf.endData(true)
};
};
/**
* Read only the TBS certificate.
* @param {BufferReader} br
* @returns {Object}
*/
ASN1.readTBS = function readTBS(br) {
const buf = br;
buf.start();
br = ASN1.seq(buf);
return {
version: ASN1.readExplicitInt(br, 0x00, true),
serial: ASN1.readInt(br),
sig: ASN1.readAlgIdent(br),
issuer: ASN1.readName(br),
validity: ASN1.readValidity(br),
subject: ASN1.readName(br),
pubkey: ASN1.readPubkey(br),
raw: buf.endData(true)
};
};
/**
* Read an implicit pubkey.
* @param {BufferReader} br
* @returns {Object}
*/
ASN1.readPubkey = function readPubkey(br) {
br = ASN1.seq(br);
return {
alg: ASN1.readAlgIdent(br),
pubkey: ASN1.readBitstr(br)
};
};
/**
* Read implicit name.
* @param {BufferReader} br
* @returns {Object[]}
*/
ASN1.readName = function readName(br) {
const values = [];
br = ASN1.seq(br);
while (br.left()) {
ASN1.implicit(br, 0x11); // set
ASN1.implicit(br, 0x10); // seq
values.push({
type: ASN1.readOID(br),
value: ASN1.readString(br)
});
}
return values;
};
/**
* Read implicit validity timerange.
* @param {BufferReader} br
* @returns {Object}
*/
ASN1.readValidity = function readValidity(br) {
br = ASN1.seq(br);
return {
notBefore: ASN1.readTime(br),
notAfter: ASN1.readTime(br)
};
};
/**
* Read implicit timestamp.
* @param {BufferReader} br
* @returns {Number}
*/
ASN1.readTime = function readTime(br) {
const tag = ASN1.readTag(br);
const str = br.readString('ascii', tag.size);
let year, mon, day, hour, min, sec;
switch (tag.type) {
case 0x17: // utctime
year = str.slice(0, 2) | 0;
mon = str.slice(2, 4) | 0;
day = str.slice(4, 6) | 0;
hour = str.slice(6, 8) | 0;
min = str.slice(8, 10) | 0;
sec = str.slice(10, 12) | 0;
if (year < 70)
year = 2000 + year;
else
year = 1900 + year;
break;
case 0x18: // gentime
year = str.slice(0, 4) | 0;
mon = str.slice(4, 6) | 0;
day = str.slice(6, 8) | 0;
hour = str.slice(8, 10) | 0;
min = str.slice(10, 12) | 0;
sec = str.slice(12, 14) | 0;
break;
default:
throw new Error(`Unexpected tag: ${tag.type}.`);
}
return Date.UTC(year, mon - 1, day, hour, min, sec, 0) / 1000;
};
/**
* Read and format OID to string.
* @param {BufferReader} br
* @returns {String}
*/
ASN1.readOID = function readOID(br) {
const tag = ASN1.implicit(br, 0x06);
const data = br.readBytes(tag.size);
return ASN1.formatOID(data);
};
/**
* Format an OID buffer to a string.
* @param {Buffer} data
* @returns {String}
*/
ASN1.formatOID = function formatOID(data) {
const br = new BufferReader(data);
const ids = [];
let ident = 0;
let subident = 0;
while (br.left()) {
subident = br.readU8();
ident <<= 7;
ident |= subident & 0x7f;
if ((subident & 0x80) === 0) {
ids.push(ident);
ident = 0;
}
}
if (subident & 0x80)
ids.push(ident);
const first = (ids[0] / 40) | 0;
const second = ids[0] % 40;
const result = [first, second].concat(ids.slice(1));
return result.join('.');
};
/**
* Read algorithm identifier.
* @param {BufferReader} br
* @returns {Object}
*/
ASN1.readAlgIdent = function readAlgIdent(br) {
let params = null;
br = ASN1.seq(br);
const alg = ASN1.readOID(br);
if (br.left() > 0) {
const tag = ASN1.readTag(br);
params = br.readBytes(tag.size);
if (params.length === 0)
params = null;
}
return {
alg: alg,
params: params
};
};
/**
* Read RSA public key.
* @param {BufferReader} br
* @returns {Object}
*/
ASN1.readRSAPublic = function readRSAPublic(br) {
br = ASN1.seq(br);
return {
modulus: ASN1.readInt(br),
publicExponent: ASN1.readInt(br)
};
};
/**
* Read RSA private key.
* @param {BufferReader} br
* @returns {Object}
*/
ASN1.readRSAPrivate = function readRSAPrivate(br) {
br = ASN1.seq(br);
return {
version: ASN1.readInt(br, true),
modulus: ASN1.readInt(br),
publicExponent: ASN1.readInt(br),
privateExponent: ASN1.readInt(br),
prime1: ASN1.readInt(br),
prime2: ASN1.readInt(br),
exponent1: ASN1.readInt(br),
exponent2: ASN1.readInt(br),
coefficient: ASN1.readInt(br)
};
};
/**
* Read RSA public key from buffer.
* @param {Buffer} data
* @returns {Object}
*/
ASN1.parseRSAPublic = function parseRSAPublic(data) {
return ASN1.readRSAPublic(new BufferReader(data, true));
};
/**
* Read RSA private key from buffer.
* @param {Buffer} data
* @returns {Object}
*/
ASN1.parseRSAPrivate = function parseRSAPrivate(data) {
return ASN1.readRSAPrivate(new BufferReader(data, true));
};
/**
* Read certificate from buffer.
* @param {Buffer} data
* @returns {Object}
*/
ASN1.parseCert = function parseCert(data) {
return ASN1.readCert(new BufferReader(data, true));
};
/**
* Read TBS certificate from buffer.
* @param {Buffer} data
* @returns {Object}
*/
ASN1.parseTBS = function parseTBS(data) {
return ASN1.readTBS(new BufferReader(data, true));
};

View File

@ -345,13 +345,13 @@ AsyncEmitter.prototype.fire = async function fire(type) {
AsyncEmitter.prototype.tryFire = async function tryFire(type) {
try {
await this.emit.apply(this, arguments);
await this.fire.apply(this, arguments);
} catch (e) {
if (type === 'error')
return;
try {
await this.emit('error', e);
await this.fire('error', e);
} catch (e) {
;
}

View File

@ -8,8 +8,8 @@
const assert = require('assert');
const {U64} = require('./int64');
const digest = require('../crypto/digest');
const siphash = require('../crypto/siphash');
const hash256 = require('bcrypto/lib/hash256');
const siphash = require('bcrypto/lib/siphash');
const DUMMY = Buffer.alloc(0);
const EOF = new U64(-1);
@ -27,12 +27,12 @@ function GCSFilter() {
}
GCSFilter.prototype.hash = function hash(enc) {
const h = digest.hash256(this.data);
const h = hash256.digest(this.data);
return enc === 'hex' ? h.toString('hex') : h;
};
GCSFilter.prototype.header = function header(prev) {
return digest.root256(this.hash(), prev);
return hash256.root(this.hash(), prev);
};
GCSFilter.prototype.match = function match(key, data) {

View File

@ -10,7 +10,6 @@
* @module utils
*/
exports.ASN1 = require('./asn1');
// exports.AsyncEmitter = require('./asyncemitter');
exports.AsyncObject = require('./asyncobject');
exports.base32 = require('./base32');
@ -31,7 +30,6 @@ exports.LRU = require('./lru');
exports.MappedLock = require('./mappedlock');
exports.murmur3 = require('./murmur3');
exports.nfkd = require('./nfkd');
exports.PEM = require('./pem');
exports.ProtoWriter = require('./protowriter');
exports.ProtoReader = require('./protoreader');
exports.RBT = require('./rbt');

View File

@ -1,148 +0,0 @@
/*!
* pem.js - pem parsing for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const assert = require('assert');
/**
* @exports utils/pem
*/
const PEM = exports;
/**
* Parse PEM into separated chunks.
* @param {String} pem
* @returns {Object[]}
* @throws on parse error
*/
PEM.parse = function parse(pem) {
const chunks = [];
let chunk = '';
let tag;
while (pem.length) {
let m;
m = /^-----BEGIN ([^\-]+)-----/.exec(pem);
if (m) {
pem = pem.substring(m[0].length);
tag = m[1];
continue;
}
m = /^-----END ([^\-]+)-----/.exec(pem);
if (m) {
pem = pem.substring(m[0].length);
assert(tag === m[1], 'Tag mismatch.');
const type = tag.split(' ')[0].toLowerCase();
const data = Buffer.from(chunk, 'base64');
chunks.push({
tag: tag,
type: type,
data: data
});
chunk = '';
tag = null;
continue;
}
m = /^[a-zA-Z0-9\+=\/]+/.exec(pem);
if (m) {
pem = pem.substring(m[0].length);
chunk += m[0];
continue;
}
m = /^\s+/.exec(pem);
if (m) {
pem = pem.substring(m[0].length);
continue;
}
throw new Error('PEM parse error.');
}
assert(chunks.length !== 0, 'PEM parse error.');
assert(!tag, 'Un-ended tag.');
assert(chunk.length === 0, 'Trailing data.');
return chunks;
};
/**
* Decode PEM into a manageable format.
* @param {String} pem
* @returns {Object}
* @throws on parse error
*/
PEM.decode = function decode(pem) {
const chunks = PEM.parse(pem);
const body = chunks[0];
const extra = chunks[1];
let params = null;
if (extra) {
if (extra.tag.indexOf('PARAMETERS') !== -1)
params = extra.data;
}
let alg = null;
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
};
};
/**
* Encode DER to PEM.
* @param {Buffer} der
* @param {String} type - e.g. "ec".
* @param {String?} suffix - e.g. "public key".
* @returns {String}
*/
PEM.encode = function encode(der, type, suffix) {
let pem = '';
if (suffix)
type += ' ' + suffix;
type = type.toUpperCase();
der = der.toString('base64');
for (let i = 0; i < der.length; i += 64)
pem += der.slice(i, i + 64) + '\n';
return ''
+ `-----BEGIN ${type}-----\n`
+ pem
+ `-----END ${type}-----\n`;
};

View File

@ -9,7 +9,7 @@
const {NodeClient} = require('bclient');
const TX = require('../primitives/tx');
const digest = require('../crypto/digest');
const digest = require('bcrypto/lib/digest');
const util = require('../utils/util');
class WalletClient extends NodeClient {

View File

@ -15,9 +15,9 @@ const base58 = require('../utils/base58');
const MTX = require('../primitives/mtx');
const Outpoint = require('../primitives/outpoint');
const Script = require('../script/script');
const digest = require('../crypto/digest');
const random = require('../crypto/random');
const ccmp = require('../crypto/ccmp');
const digest = require('bcrypto/lib/digest');
const random = require('bcrypto/lib/random');
const ccmp = require('bcrypto/lib/ccmp');
const Network = require('../protocol/network');
const Validator = require('../utils/validator');
const Address = require('../primitives/address');

View File

@ -10,11 +10,12 @@ const assert = require('assert');
const Network = require('../protocol/network');
const util = require('../utils/util');
const Lock = require('../utils/lock');
const random = require('../crypto/random');
const cleanse = require('../crypto/cleanse');
const aes = require('../crypto/aes');
const pbkdf2 = require('../crypto/pbkdf2');
const scrypt = require('../crypto/scrypt');
const random = require('bcrypto/lib/random');
const cleanse = require('bcrypto/lib/cleanse');
const aes = require('bcrypto/lib/aes');
const sha256 = require('bcrypto/lib/sha256');
const pbkdf2 = require('bcrypto/lib/pbkdf2');
const scrypt = require('bcrypto/lib/scrypt');
const BufferReader = require('../utils/reader');
const StaticWriter = require('../utils/staticwriter');
const encoding = require('../utils/encoding');
@ -265,7 +266,7 @@ MasterKey.prototype.derive = async function derive(passwd) {
switch (this.alg) {
case MasterKey.alg.PBKDF2:
return await pbkdf2.deriveAsync(passwd, salt, N, 32, 'sha256');
return await pbkdf2.deriveAsync(sha256, passwd, salt, N, 32);
case MasterKey.alg.SCRYPT:
return await scrypt.deriveAsync(passwd, salt, N, r, p, 32);
default:

View File

@ -53,7 +53,8 @@ plugin.init = function init(node) {
port: config.uint('wallet-port'),
spv: node.spv,
verify: node.spv,
listen: false
listen: true,
plugin: true
});
wdb.http.attach('/wallet', node.http);

View File

@ -10,7 +10,7 @@ const assert = require('assert');
const bweb = require('bweb');
const fs = require('../utils/fs');
const util = require('../utils/util');
const digest = require('../crypto/digest');
const digest = require('bcrypto/lib/digest');
const Amount = require('../btc/amount');
const Script = require('../script/script');
const Address = require('../primitives/address');

View File

@ -13,8 +13,8 @@ const Network = require('../protocol/network');
const util = require('../utils/util');
const encoding = require('../utils/encoding');
const Lock = require('../utils/lock');
const digest = require('../crypto/digest');
const cleanse = require('../crypto/cleanse');
const digest = require('bcrypto/lib/digest');
const cleanse = require('bcrypto/lib/cleanse');
const BufferReader = require('../utils/reader');
const StaticWriter = require('../utils/staticwriter');
const base58 = require('../utils/base58');

View File

@ -14,8 +14,8 @@ const util = require('../utils/util');
const Lock = require('../utils/lock');
const MappedLock = require('../utils/mappedlock');
const encoding = require('../utils/encoding');
const ccmp = require('../crypto/ccmp');
const aes = require('../crypto/aes');
const ccmp = require('bcrypto/lib/ccmp');
const aes = require('bcrypto/lib/aes');
const Network = require('../protocol/network');
const Path = require('./path');
const common = require('./common');
@ -130,7 +130,7 @@ WalletDB.prototype._init = function _init() {
*/
WalletDB.prototype._open = async function _open() {
if (this.options.listen)
if (!this.options.plugin)
await this.logger.open();
await this.db.open();
@ -160,7 +160,8 @@ WalletDB.prototype._open = async function _open() {
this.primary = wallet;
this.rpc.wallet = wallet;
await this.http.open();
if (this.options.listen)
await this.http.open();
};
/**
@ -171,7 +172,9 @@ WalletDB.prototype._open = async function _open() {
WalletDB.prototype._close = async function _close() {
await this.disconnect();
await this.http.close();
if (this.options.listen)
await this.http.close();
for (const wallet of this.wallets.values()) {
await wallet.destroy();
@ -180,7 +183,7 @@ WalletDB.prototype._close = async function _close() {
await this.db.close();
if (this.options.listen)
if (!this.options.plugin)
await this.logger.close();
};
@ -2043,6 +2046,7 @@ function WalletOptions(options) {
this.ssl = false;
this.host = '127.0.0.1';
this.port = this.network.rpcPort + 2;
this.plugin = false;
this.listen = false;
if (options)
@ -2169,6 +2173,11 @@ WalletOptions.prototype.fromOptions = function fromOptions(options) {
this.port = options.port;
}
if (options.plugin != null) {
assert(typeof options.plugin === 'boolean');
this.plugin = options.plugin;
}
if (options.listen != null) {
assert(typeof options.listen === 'boolean');
this.listen = options.listen;

View File

@ -6,8 +6,8 @@
'use strict';
const secp256k1 = require('../crypto/secp256k1');
const {derive} = require('../crypto/scrypt');
const secp256k1 = require('bcrypto/lib/secp256k1');
const {derive} = require('bcrypto/lib/scrypt');
const hashcash = require('../mining/mine');
const packets = require('./packets');

View File

@ -19,8 +19,8 @@ const assert = require('assert');
const encoding = require('../lib/utils/encoding');
const co = require('../lib/utils/co');
const util = require('../lib/utils/util');
const digest = require('../lib/crypto/digest');
const BN = require('../lib/crypto/bn');
const digest = require('bcrypto/lib/digest');
const BN = require('bcrypto/lib/bn');
const StaticWriter = require('../lib/utils/staticwriter');
const BufferReader = require('../lib/utils/reader');
const OldCoins = require('./coins/coins');

View File

@ -7,7 +7,7 @@
'use strict';
const assert = require('assert');
const secp256k1 = require('../lib/crypto/secp256k1');
const secp256k1 = require('bcrypto/lib/secp256k1');
/*
* Compression

View File

@ -3,10 +3,10 @@
const assert = require('assert');
const encoding = require('../lib/utils/encoding');
const BufferReader = require('../lib/utils/reader');
const digest = require('../lib/crypto/digest');
const digest = require('bcrypto/lib/digest');
const util = require('../lib/utils/util');
const LDB = require('../lib/db/ldb');
const BN = require('../lib/crypto/bn');
const BN = require('bcrypto/lib/bn');
const DUMMY = Buffer.from([0]);
let file = process.argv[2];
let batch;

View File

@ -23,18 +23,16 @@
"node": ">=7.6.0"
},
"dependencies": {
"bn.js": "4.11.8",
"elliptic": "6.4.0",
"n64": "0.0.18",
"breq": "^0.0.1",
"bclient": "^0.0.1",
"bweb": "^0.0.1",
"bsock": "^0.0.1"
"bsock": "^0.0.1",
"bcrypto": "^0.0.1"
},
"optionalDependencies": {
"bcoin-native": "0.0.23",
"leveldown": "1.7.2",
"secp256k1": "3.3.0"
"leveldown": "1.7.2"
},
"devDependencies": {
"babel-core": "^6.25.0",

View File

@ -8,8 +8,8 @@ const Input = require('../lib/primitives/input');
const Output = require('../lib/primitives/output');
const Outpoint = require('../lib/primitives/outpoint');
const TX = require('../lib/primitives/tx');
const random = require('../lib/crypto/random');
const secp256k1 = require('../lib/crypto/secp256k1');
const random = require('bcrypto/lib/random');
const secp256k1 = require('bcrypto/lib/secp256k1');
const flags = Script.flags;
let consensus = null;

View File

@ -1,49 +0,0 @@
/* eslint-env mocha */
/* eslint prefer-arrow-callback: "off" */
'use strict';
const assert = require('./util/assert');
const aes = require('../lib/crypto/aes');
const key = Buffer.from(
'3a0c0bf669694ac7685e6806eeadee8e56c9b9bd22c3caa81c718ed4bbf809a1',
'hex');
const iv = Buffer.from('6dd26d9045b73c377a9ed2ffeca72ffd', 'hex');
describe('AES', function() {
it('should encrypt and decrypt with 2 blocks', () => {
const data = Buffer.from(
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
'hex');
const expected = Buffer.from(''
+ '83de502a9c83112ca6383f2214a892a0cdad5ab2b3e192e'
+ '9921ddb126b25262c41f1dcff4d67ccfb40e4116e5a4569c1',
'hex');
const ciphertext = aes.encipher(data, key, iv);
assert.bufferEqual(ciphertext, expected);
const plaintext = aes.decipher(ciphertext, key, iv);
assert.bufferEqual(plaintext, data);
});
it('should encrypt and decrypt with uneven blocks', () => {
const data = Buffer.from(
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855010203',
'hex');
const expected = Buffer.from(''
+ '83de502a9c83112ca6383f2214a892a0cdad5ab2b3e192e9'
+ '921ddb126b25262c5211801019a30c0c6f795296923e0af8',
'hex');
const ciphertext = aes.encipher(data, key, iv);
assert.bufferEqual(ciphertext, expected);
const plaintext = aes.decipher(ciphertext, key, iv);
assert.bufferEqual(plaintext, data);
});
});

View File

@ -4,7 +4,7 @@
'use strict';
const assert = require('./util/assert');
const secp256k1 = require('../lib/crypto/secp256k1');
const secp256k1 = require('bcrypto/lib/secp256k1');
const BIP150 = require('../lib/net/bip150');
const BIP151 = require('../lib/net/bip151');

View File

@ -1,235 +0,0 @@
/* eslint-env mocha */
/* eslint prefer-arrow-callback: "off" */
'use strict';
const assert = require('./util/assert');
const ChaCha20 = require('../lib/crypto/chacha20');
const Poly1305 = require('../lib/crypto/poly1305');
const AEAD = require('../lib/crypto/aead');
function testChaCha(options) {
const key = Buffer.from(options.key, 'hex');
const nonce = Buffer.from(options.nonce, 'hex');
const plain = Buffer.from(options.plain, 'hex');
const ciphertext = Buffer.from(options.ciphertext, 'hex');
const counter = options.counter;
const ctx1 = new ChaCha20();
ctx1.init(key, nonce, counter);
const plainenc = Buffer.from(plain);
ctx1.encrypt(plainenc);
assert.bufferEqual(plainenc, ciphertext);
const ctx2 = new ChaCha20();
ctx2.init(key, nonce, counter);
ctx2.encrypt(ciphertext);
assert.bufferEqual(plain, ciphertext);
}
function testAEAD(options) {
const plain = Buffer.from(options.plain, 'hex');
const aad = Buffer.from(options.aad, 'hex');
const key = Buffer.from(options.key, 'hex');
const nonce = Buffer.from(options.nonce, 'hex');
const pk = Buffer.from(options.pk, 'hex');
const ciphertext = Buffer.from(options.ciphertext, 'hex');
const tag = Buffer.from(options.tag, 'hex');
const ctx1 = new AEAD();
ctx1.init(key, nonce);
assert.strictEqual(ctx1.chacha20.getCounter(), 1);
assert.bufferEqual(ctx1.polyKey, pk);
ctx1.aad(aad);
const plainenc = Buffer.from(plain);
ctx1.encrypt(plainenc);
assert.bufferEqual(plainenc, ciphertext);
assert.bufferEqual(ctx1.finish(), tag);
const ctx2 = new AEAD();
ctx2.init(key, nonce);
assert.strictEqual(ctx2.chacha20.getCounter(), 1);
assert.bufferEqual(ctx2.polyKey, pk);
ctx2.aad(aad);
ctx2.decrypt(ciphertext);
assert.bufferEqual(ciphertext, plain);
assert.bufferEqual(ctx2.finish(), tag);
}
describe('ChaCha20 / Poly1305 / AEAD', function() {
it('should perform chacha20', () => {
testChaCha({
key: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
nonce: '000000000000004a00000000',
plain: ''
+ '4c616469657320616e642047656e746c656d656e206f6620746865206'
+ '36c617373206f66202739393a204966204920636f756c64206f6666657220796'
+ 'f75206f6e6c79206f6e652074697020666f7220746865206675747572652c207'
+ '3756e73637265656e20776f756c642062652069742e',
ciphertext: ''
+ '6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afcc'
+ 'fd9fae0bf91b65c5524733ab8f593dabcd62b3571639d624e65152ab'
+ '8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d'
+ '16ccf806818ce91ab77937365af90bbf74a35be6b40b8eedf2785e42874d',
counter: 1
});
});
it('should perform chacha20', () => {
testChaCha({
key: '0000000000000000000000000000000000000000000000000000000000000000',
nonce: '000000000000000000000000',
plain: ''
+ '0000000000000000000000000000000000000000000000000000000000000000'
+ '0000000000000000000000000000000000000000000000000000000000000000',
ciphertext: ''
+ '76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b77'
+ '0dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669'
+ 'b2ee6586',
counter: 0
});
});
it('should perform chacha20', () => {
testChaCha({
key: '0000000000000000000000000000000000000000000000000000000000000001',
nonce: '000000000000000000000002',
plain: ''
+ '416e79207375626d697373696f6e20746f20746865204945544620696e'
+ '74656e6465642062792074686520436f6e7472696275746f7220666f722'
+ '07075626c69636174696f6e20617320616c6c206f722070617274206f'
+ '6620616e204945544620496e7465726e65742d4472616674206f7220524'
+ '64320616e6420616e792073746174656d656e74206d6164652077697468696'
+ 'e2074686520636f6e74657874206f6620616e2049455446206163746976'
+ '69747920697320636f6e7369646572656420616e20224945544620436f6'
+ 'e747269627574696f6e222e20537563682073746174656d656e747320696e'
+ '636c756465206f72616c2073746174656d656e747320696e204945544620'
+ '73657373696f6e732c2061732077656c6c206173207772697474656e2061'
+ '6e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d'
+ '61646520617420616e792074696d65206f7220706c6163652c2077686963'
+ '68206172652061646472657373656420746f',
ciphertext: ''
+ 'a3fbf07df3fa2fde4f376ca23e82737041605d9f4f4f57bd8cff2c1d'
+ '4b7955ec2a97948bd3722915c8f3d337f7d370050e9e96d647b7c39f'
+ '56e031ca5eb6250d4042e02785ececfa4b4bb5e8ead0440e20b6e8db'
+ '09d881a7c6132f420e52795042bdfa7773d8a9051447b3291ce1411c'
+ '680465552aa6c405b7764d5e87bea85ad00f8449ed8f72d0d662ab05'
+ '2691ca66424bc86d2df80ea41f43abf937d3259dc4b2d0dfb48a6c91'
+ '39ddd7f76966e928e635553ba76c5c879d7b35d49eb2e62b0871cdac'
+ '638939e25e8a1e0ef9d5280fa8ca328b351c3c765989cbcf3daa8b6c'
+ 'cc3aaf9f3979c92b3720fc88dc95ed84a1be059c6499b9fda236e7e8'
+ '18b04b0bc39c1e876b193bfe5569753f88128cc08aaa9b63d1a16f80'
+ 'ef2554d7189c411f5869ca52c5b83fa36ff216b9c1d30062bebcfd'
+ '2dc5bce0911934fda79a86f6e698ced759c3ff9b6477338f3da4f9'
+ 'cd8514ea9982ccafb341b2384dd902f3d1ab7ac61dd29c6f21ba5b'
+ '862f3730e37cfdc4fd806c22f221',
counter: 1
});
});
it('should perform chacha20', () => {
testChaCha({
key: '1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0',
nonce: '000000000000000000000002',
plain: ''
+ '2754776173206272696c6c69672c20616e642074686520736c6974687920746f76'
+ '65730a446964206779726520616e642067696d626c6520696e207468'
+ '6520776162653a0a416c6c206d696d73792077657265207468652062'
+ '6f726f676f7665732c0a416e6420746865206d6f6d65207261746873'
+ '206f757467726162652e',
ciphertext: ''
+ '62e6347f95ed87a45ffae7426f27a1df5fb69110044c0d73118effa95b01e5cf16'
+ '6d3df2d721caf9b21e5fb14c616871fd84c54f9d65b283196c7fe4f6'
+ '0553ebf39c6402c42234e32a356b3e764312a61a5532055716ead696'
+ '2568f87d3f3f7704c6a8d1bcd1bf4d50d6154b6da731b187b58dfd72'
+ '8afa36757a797ac188d1',
counter: 42
});
});
it('should perform poly1305', () => {
const expected = Buffer.from('ddb9da7ddd5e52792730ed5cda5f90a4', 'hex');
const key = Buffer.allocUnsafe(32);
const msg = Buffer.allocUnsafe(73);
for (let i = 0; i < key.length; i++)
key[i] = i + 221;
for (let i = 0; i < msg.length; i++)
msg[i] = i + 121;
const mac = Poly1305.auth(msg, key);
assert(Poly1305.verify(mac, expected));
assert.bufferEqual(mac, expected);
});
it('should perform poly1305', () => {
const key = Buffer.from(''
+ '85d6be7857556d337f4452fe42d506a'
+ '80103808afb0db2fd4abff6af4149f51b',
'hex');
const msg = Buffer.from('Cryptographic Forum Research Group', 'ascii');
const tag = Buffer.from('a8061dc1305136c6c22b8baf0c0127a9', 'hex');
const mac = Poly1305.auth(msg, key);
assert(Poly1305.verify(mac, tag));
mac[0] = 0;
assert(!Poly1305.verify(mac, tag));
});
it('should create an AEAD and encrypt', () => {
testAEAD({
plain: ''
+ '4c616469657320616e642047656e746c656d656e206f662074686520636c6'
+ '17373206f66202739393a204966204920636f756c64206f666665722'
+ '0796f75206f6e6c79206f6e652074697020666f72207468652066757'
+ '47572652c2073756e73637265656e20776f756c642062652069742e',
aad: '50515253c0c1c2c3c4c5c6c7',
key: '808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f',
nonce: '07000000' + '4041424344454647',
pk: '7bac2b252db447af09b67a55a4e955840ae1d6731075d9eb2a9375783ed553ff',
ciphertext: ''
+ 'd31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee6'
+ '2d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a'
+ '5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad67'
+ '5945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116',
tag: '1ae10b594f09e26a7e902ecbd0600691'
});
});
it('should create an AEAD and encrypt', () => {
testAEAD({
key: '1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0',
ciphertext: ''
+ '64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8'
+ 'cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03'
+ 'b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d3'
+ '3bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b35063836069'
+ '07b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a'
+ '4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b004'
+ '7718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa7'
+ '6991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e61'
+ '7d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6'
+ 'f2c29a6ad5cb4022b02709b',
nonce: '000000000102030405060708',
aad: 'f33388860000000000004e91',
tag: 'eead9d67890cbb22392336fea1851f38',
pk: 'bdf04aa95ce4de8995b14bb6a18fecaf26478f50c054f563dbc0a21e261572aa',
plain: ''
+ '496e7465726e65742d4472616674732061726520647261667420646f63756'
+ 'd656e74732076616c696420666f722061206d6178696d756d206f662'
+ '0736978206d6f6e74687320616e64206d61792062652075706461746'
+ '5642c207265706c616365642c206f72206f62736f6c6574656420627'
+ '9206f7468657220646f63756d656e747320617420616e792074696d6'
+ '52e20497420697320696e617070726f70726961746520746f2075736'
+ '520496e7465726e65742d447261667473206173207265666572656e6'
+ '365206d6174657269616c206f7220746f2063697465207468656d206'
+ 'f74686572207468616e206173202fe2809c776f726b20696e2070726'
+ 'f67726573732e2fe2809d'
});
});
});

View File

@ -5,7 +5,7 @@
const assert = require('./util/assert');
const consensus = require('../lib/protocol/consensus');
const BN = require('../lib/crypto/bn');
const BN = require('bcrypto/lib/bn');
describe('Consensus', function() {
it('should calculate reward properly', () => {

View File

@ -5,7 +5,7 @@
const assert = require('./util/assert');
const GCSFilter = require('../lib/utils/gcs');
const random = require('../lib/crypto/random');
const random = require('bcrypto/lib/random');
const Outpoint = require('../lib/primitives/outpoint');
const Address = require('../lib/primitives/address');
const common = require('./util/common');

View File

@ -6,7 +6,8 @@
const assert = require('./util/assert');
const HD = require('../lib/hd');
const base58 = require('../lib/utils/base58');
const pbkdf2 = require('../lib/crypto/pbkdf2');
const pbkdf2 = require('bcrypto/lib/pbkdf2');
const sha512 = require('bcrypto/lib/sha512');
const vectors = require('./data/hd.json');
const vector1 = vectors.vector1;
const vector2 = vectors.vector2;
@ -21,8 +22,11 @@ function base58Equal(a, b) {
describe('HD', function() {
it('should create a pbkdf2 seed', () => {
const seed = pbkdf2.derive(
vectors.phrase, 'mnemonicfoo', 2048, 64, 'sha512');
const seed = pbkdf2.derive(sha512,
Buffer.from(vectors.phrase),
Buffer.from('mnemonicfoo'),
2048,
64);
assert.strictEqual(seed.toString('hex'), vectors.seed);
});

View File

@ -1,84 +0,0 @@
/* eslint-env mocha */
/* eslint prefer-arrow-callback: "off" */
'use strict';
const assert = require('./util/assert');
const hkdf = require('../lib/crypto/hkdf');
describe('HKDF', function() {
it('should do proper hkdf (1)', () => {
// https://tools.ietf.org/html/rfc5869
const alg = 'sha256';
const ikm = Buffer.from(
'0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', 'hex');
const salt = Buffer.from('000102030405060708090a0b0c', 'hex');
const info = Buffer.from('f0f1f2f3f4f5f6f7f8f9', 'hex');
const len = 42;
const prkE = Buffer.from(
'077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5',
'hex');
const okmE = Buffer.from(''
+ '3cb25f25faacd57a90434f64d0362f2a2d2d0a90'
+ 'cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865',
'hex');
const prk = hkdf.extract(ikm, salt, alg);
const okm = hkdf.expand(prk, info, len, alg);
assert.bufferEqual(prk, prkE);
assert.bufferEqual(okm, okmE);
});
it('should do proper hkdf (2)', () => {
const alg = 'sha256';
const ikm = Buffer.from(''
+ '000102030405060708090a0b0c0d0e0f'
+ '101112131415161718191a1b1c1d1e1f'
+ '202122232425262728292a2b2c2d2e2f'
+ '303132333435363738393a3b3c3d3e3f'
+ '404142434445464748494a4b4c4d4e4f',
'hex');
const salt = Buffer.from(''
+ '606162636465666768696a6b6c6d6e6f'
+ '707172737475767778797a7b7c7d7e7f'
+ '808182838485868788898a8b8c8d8e8f'
+ '909192939495969798999a9b9c9d9e9f'
+ 'a0a1a2a3a4a5a6a7a8a9aaabacadaeaf',
'hex');
const info = Buffer.from(''
+ 'b0b1b2b3b4b5b6b7b8b9babbbcbdbebf'
+ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf'
+ 'd0d1d2d3d4d5d6d7d8d9dadbdcdddedf'
+ 'e0e1e2e3e4e5e6e7e8e9eaebecedeeef'
+ 'f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff',
'hex');
const len = 82;
const prkE = Buffer.from(''
+ '06a6b88c5853361a06104c9ceb35b45c'
+ 'ef760014904671014a193f40c15fc244',
'hex');
const okmE = Buffer.from(''
+ 'b11e398dc80327a1c8e7f78c596a4934'
+ '4f012eda2d4efad8a050cc4c19afa97c'
+ '59045a99cac7827271cb41c65e590e09'
+ 'da3275600c2f09b8367793a9aca3db71'
+ 'cc30c58179ec3e87c14c01d5c1f3434f'
+ '1d87',
'hex');
const prk = hkdf.extract(ikm, salt, alg);
const okm = hkdf.expand(prk, info, len, alg);
assert.bufferEqual(prk, prkE);
assert.bufferEqual(okm, okmE);
});
});

View File

@ -5,7 +5,7 @@
const assert = require('./util/assert');
const encoding = require('../lib/utils/encoding');
const random = require('../lib/crypto/random');
const random = require('bcrypto/lib/random');
const MempoolEntry = require('../lib/mempool/mempoolentry');
const Mempool = require('../lib/mempool/mempool');
const WorkerPool = require('../lib/workers/workerpool');

View File

@ -1,20 +0,0 @@
/* eslint-env mocha */
/* eslint prefer-arrow-callback: "off" */
'use strict';
const assert = require('./util/assert');
const secp256k1 = require('../lib/crypto/secp256k1');
const digest = require('../lib/crypto/digest');
const schnorr = require('../lib/crypto/schnorr');
describe('Schnorr', function() {
it('should do proper schnorr', () => {
const key = secp256k1.generatePrivateKey();
const pub = secp256k1.publicKeyCreate(key, true);
const msg = digest.hash256(Buffer.from('foo', 'ascii'));
const sig = schnorr.sign(msg, key);
assert.strictEqual(schnorr.verify(msg, sig, pub), true);
assert.bufferEqual(schnorr.recover(sig, msg), pub);
});
});

View File

@ -1,93 +0,0 @@
/* eslint-env mocha */
/* eslint prefer-arrow-callback: "off" */
'use strict';
const assert = require('./util/assert');
const scrypt = require('../lib/crypto/scrypt');
describe('Scrypt', function() {
this.timeout(20000);
it('should perform scrypt with N=16', () => {
const pass = Buffer.from('');
const salt = Buffer.from('');
const result = scrypt.derive(pass, salt, 16, 1, 1, 64);
assert.strictEqual(result.toString('hex'), ''
+ '77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3f'
+ 'ede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628'
+ 'cf35e20c38d18906');
});
it('should perform scrypt with N=1024', () => {
const pass = Buffer.from('password');
const salt = Buffer.from('NaCl');
const result = scrypt.derive(pass, salt, 1024, 8, 16, 64);
assert.strictEqual(result.toString('hex'), ''
+ 'fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e773'
+ '76634b3731622eaf30d92e22a3886ff109279d9830dac727afb9'
+ '4a83ee6d8360cbdfa2cc0640');
});
it('should perform scrypt with N=16384', () => {
const pass = Buffer.from('pleaseletmein');
const salt = Buffer.from('SodiumChloride');
const result = scrypt.derive(pass, salt, 16384, 8, 1, 64);
assert.strictEqual(result.toString('hex'), ''
+ '7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b54'
+ '3f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d'
+ '651e40dfcf017b45575887');
});
// Only enable if you want to wait a while.
// it('should perform scrypt with N=1048576', () => {
// let pass = Buffer.from('pleaseletmein');
// let salt = Buffer.from('SodiumChloride');
// let result = scrypt.derive(pass, salt, 1048576, 8, 1, 64);
// assert.strictEqual(result.toString('hex'), ''
// + '2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5'
// + 'ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049'
// + 'e8a952fbcbf45c6fa77a41a4');
// });
it('should perform scrypt with N=16 (async)', async () => {
const pass = Buffer.from('');
const salt = Buffer.from('');
const result = await scrypt.deriveAsync(pass, salt, 16, 1, 1, 64);
assert.strictEqual(result.toString('hex'), ''
+ '77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3f'
+ 'ede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628'
+ 'cf35e20c38d18906');
});
it('should perform scrypt with N=1024 (async)', async () => {
const pass = Buffer.from('password');
const salt = Buffer.from('NaCl');
const result = await scrypt.deriveAsync(pass, salt, 1024, 8, 16, 64);
assert.strictEqual(result.toString('hex'), ''
+ 'fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e773'
+ '76634b3731622eaf30d92e22a3886ff109279d9830dac727afb9'
+ '4a83ee6d8360cbdfa2cc0640');
});
it('should perform scrypt with N=16384 (async)', async () => {
const pass = Buffer.from('pleaseletmein');
const salt = Buffer.from('SodiumChloride');
const result = await scrypt.deriveAsync(pass, salt, 16384, 8, 1, 64);
assert.strictEqual(result.toString('hex'), ''
+ '7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b54'
+ '3f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d'
+ '651e40dfcf017b45575887');
});
// Only enable if you want to wait a while.
// it('should perform scrypt with N=1048576 (async)', async () => {
// let pass = Buffer.from('pleaseletmein');
// let salt = Buffer.from('SodiumChloride');
// let result = await scrypt.deriveAsync(pass, salt, 1048576, 8, 1, 64);
// assert.strictEqual(result.toString('hex'), ''
// + '2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5'
// + 'ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049'
// + 'e8a952fbcbf45c6fa77a41a4');
// });
});

View File

@ -1,30 +0,0 @@
/* eslint-env mocha */
/* eslint prefer-arrow-callback: "off" */
'use strict';
const assert = require('./util/assert');
const siphash = require('../lib/crypto/siphash');
const siphash256 = siphash.siphash256;
describe('SipHash', function() {
it('should perform siphash with no data', () => {
const data = Buffer.alloc(0);
const key = Buffer.from('000102030405060708090a0b0c0d0e0f', 'hex');
assert.deepStrictEqual(siphash256(data, key), [1919933255, -586281423]);
});
it('should perform siphash with data', () => {
const data = Buffer.from('0001020304050607', 'hex');
const key = Buffer.from('000102030405060708090a0b0c0d0e0f', 'hex');
assert.deepStrictEqual(siphash256(data, key), [-1812597383, -1701632926]);
});
it('should perform siphash with uint256', () => {
const data = Buffer.from(
'000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
'hex');
const key = Buffer.from('000102030405060708090a0b0c0d0e0f', 'hex');
assert.deepStrictEqual(siphash256(data, key), [1898402095, 1928494286]);
});
});

View File

@ -6,7 +6,7 @@
const assert = require('./util/assert');
const util = require('../lib/utils/util');
const encoding = require('../lib/utils/encoding');
const random = require('../lib/crypto/random');
const random = require('bcrypto/lib/random');
const consensus = require('../lib/protocol/consensus');
const TX = require('../lib/primitives/tx');
const Output = require('../lib/primitives/output');

Some files were not shown because too many files have changed in this diff Show More