refactor: crypto.

This commit is contained in:
Christopher Jeffrey 2017-06-27 06:34:22 -07:00
parent 63e6a97de3
commit d4cc22e1c5
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
82 changed files with 3228 additions and 3418 deletions

View File

@ -1,7 +1,7 @@
'use strict';
var Address = require('../lib/primitives/address');
var crypto = require('../lib/crypto/crypto');
var random = require('../lib/crypto/random');
var bench = require('./bench');
var i, end, addr;
@ -10,7 +10,7 @@ var addrs = [];
end = bench('serialize');
for (i = 0; i < 100000; i++) {
addr = Address.fromProgram(0, crypto.randomBytes(20));
addr = Address.fromProgram(0, random.randomBytes(20));
addrs.push(addr.toBech32());
}
end(i);

View File

@ -1,13 +1,14 @@
'use strict';
var chachapoly = require('../lib/crypto/chachapoly');
var crypto = require('../lib/crypto/crypto');
var ChaCha20 = require('../lib/crypto/chacha20');
var Poly1305 = require('../lib/crypto/poly1305');
var digest = require('../lib/crypto/digest');
var bench = require('./bench');
var i, chacha, iv, poly, key, data, end;
console.log('note: rate measured in kb/s');
chacha = new chachapoly.ChaCha20();
chacha = new ChaCha20();
key = Buffer.allocUnsafe(32);
key.fill(2);
iv = Buffer.from('0102030405060708', 'hex');
@ -20,7 +21,7 @@ for (i = 0; i < 1000000; i++)
chacha.encrypt(data);
end(i * 32 / 1024);
poly = new chachapoly.Poly1305();
poly = new Poly1305();
key = Buffer.allocUnsafe(32);
key.fill(2);
poly.init(key);
@ -45,5 +46,5 @@ end(i * 32 / 1024);
// For reference:
end = bench('sha256');
for (i = 0; i < 1000000; i++)
crypto.hash256(data);
digest.hash256(data);
end(i * 32 / 1024);

View File

@ -1,7 +1,7 @@
'use strict';
var assert = require('assert');
var crypto = require('../lib/crypto/crypto');
var random = require('../lib/crypto/random');
var Script = require('../lib/script/script');
var bench = require('./bench');
var opcodes = Script.opcodes;
@ -24,7 +24,7 @@ Script.fromPubkeyhashOld = function fromScripthash(hash) {
hashes = [];
for (i = 0; i < 100000; i++)
hashes.push(crypto.randomBytes(20));
hashes.push(random.randomBytes(20));
end = bench('old');
for (i = 0; i < hashes.length; i++)

View File

@ -9,7 +9,7 @@ var MTX = require('../lib/primitives/mtx');
var Coin = require('../lib/primitives/coin');
var CoinView = require('../lib/coins/coinview');
var encoding = require('../lib/utils/encoding');
var crypto = require('../lib/crypto/crypto');
var random = require('../lib/crypto/random');
var bench = require('./bench');
var json = require('../test/data/block300025.json');
@ -117,11 +117,11 @@ for (i = 0; i < 100; i++) {
},
script: [
Buffer.allocUnsafe(9),
crypto.randomBytes(33)
random.randomBytes(33)
]
});
tx.addOutput({
address: Address.fromHash(crypto.randomBytes(20)),
address: Address.fromHash(random.randomBytes(20)),
value: 0
});
}

View File

@ -1,14 +1,14 @@
'use strict';
var bench = require('./bench');
var crypto = require('../lib/crypto/crypto');
var random = require('../lib/crypto/random');
var WalletDB = require('../lib/wallet/walletdb');
var MTX = require('../lib/primitives/mtx');
var Outpoint = require('../lib/primitives/outpoint');
var walletdb;
function dummy() {
var hash = crypto.randomBytes(32).toString('hex');
var hash = random.randomBytes(32).toString('hex');
return new Outpoint(hash, 0);
}

View File

@ -4,7 +4,7 @@ var net = require('net');
var EventEmitter = require('events').EventEmitter;
var IOServer = require('socket.io');
var util = require('../lib/utils/util');
var crypto = require('../lib/crypto/crypto');
var digest = require('../lib/crypto/digest');
var IP = require('../lib/utils/ip');
var BufferWriter = require('../lib/utils/writer');
@ -100,7 +100,7 @@ WSProxy.prototype._handleConnect = function _handleConnect(ws, port, host, nonce
pow.writeString(host, 'ascii');
pow = pow.render();
if (crypto.hash256(pow).compare(this.target) > 0) {
if (digest.hash256(pow).compare(this.target) > 0) {
this.log('Client did not solve proof of work (%s).', state.host);
ws.emit('tcp close');
ws.disconnect();

View File

@ -1,13 +1,13 @@
'use strict';
var crypto = require('bcoin/lib/crypto/crypto');
var random = require('bcoin/lib/crypto/random');
var WalletDB = require('bcoin/lib/wallet/walletdb');
var MTX = require('bcoin/lib/primitives/mtx');
var Outpoint = require('bcoin/lib/primitives/outpoint');
var walletdb;
function dummy() {
var hash = crypto.randomBytes(32).toString('hex');
var hash = random.randomBytes(32).toString('hex');
return new Outpoint(hash, 0);
}

View File

@ -8,7 +8,7 @@
var assert = require('assert');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var x509 = require('./x509');
var PEM = require('../utils/pem');
var protobuf = require('../utils/protobuf');
@ -195,7 +195,7 @@ PaymentRequest.prototype.signatureData = function signatureData() {
PaymentRequest.prototype.signatureHash = function signatureHash() {
var alg = this.getAlgorithm();
return crypto.hash(alg.hash, this.signatureData());
return digest.hash(alg.hash, this.signatureData());
};
/**

View File

@ -10,7 +10,7 @@ var assert = require('assert');
var ASN1 = require('../utils/asn1');
var PEM = require('../utils/pem');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var pk = require('./pk');
var certs = require('./certs');
@ -127,7 +127,7 @@ x509.getCAName = function getCAName(cert) {
*/
x509.isTrusted = function isTrusted(cert) {
var fingerprint = crypto.sha256(cert.raw);
var fingerprint = digest.sha256(cert.raw);
var hash = fingerprint.toString('hex');
return x509.trusted[hash] === true;
};
@ -155,7 +155,7 @@ x509.setTrust = function setTrust(certs) {
cert = x509.parse(cert);
hash = crypto.sha256(cert.raw);
hash = digest.sha256(cert.raw);
hash = hash.toString('hex');
x509.trusted[hash] = true;

View File

@ -11,7 +11,7 @@ var assert = require('assert');
var BN = require('../crypto/bn');
var consensus = require('../protocol/consensus');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var encoding = require('../utils/encoding');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
@ -405,7 +405,7 @@ ChainEntry.prototype.toRaw = function toRaw() {
ChainEntry.prototype.fromRaw = function fromRaw(data) {
var br = new BufferReader(data, true);
var hash = crypto.hash256(br.readBytes(80));
var hash = digest.hash256(br.readBytes(80));
br.seek(-80);

174
lib/crypto/aead.js Normal file
View File

@ -0,0 +1,174 @@
/*!
* aead.js - aead for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var assert = require('assert');
var ChaCha20 = require('./chacha20');
var 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) {
var 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(aad) {
assert(this.cipherLen === 0, 'Cannot update aad.');
this.poly1305.update(aad);
this.aadLen += aad.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() {
var len = Buffer.allocUnsafe(16);
var 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) {
var pad;
size %= 16;
if (size === 0)
return;
pad = Buffer.allocUnsafe(16 - size);
pad.fill(0);
this.poly1305.update(pad);
};
/*
* Expose
*/
module.exports = AEAD;

1329
lib/crypto/aes-browser.js Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,177 +0,0 @@
/*!
* backend-browser.js - browser crypto backend for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var assert = require('assert');
var hashjs = require('hash.js');
var aes = require('./aes');
var sha256 = require('./sha256');
var crypto = global.crypto || global.msCrypto || {};
var subtle = crypto.subtle && crypto.subtle.importKey ? crypto.subtle : {};
var backend = exports;
/*
* Hashing
*/
backend.hash = function hash(alg, data) {
var hash;
if (alg === 'sha256')
return sha256.digest(data);
hash = hashjs[alg];
assert(hash != null, 'Unknown algorithm.');
return Buffer.from(hash().update(data).digest());
};
backend.ripemd160 = function ripemd160(data) {
return backend.hash('ripemd160', data);
};
backend.sha1 = function sha1(data) {
return backend.hash('sha1', data);
};
backend.sha256 = function _sha256(data) {
return sha256.digest(data);
};
backend.hash160 = function hash160(data) {
return backend.hash('ripemd160', sha256.digest(data));
};
backend.hash256 = function hash256(data) {
return sha256.hash256(data);
};
backend.hmac = function _hmac(alg, data, key) {
var hash = hashjs[alg];
var hmac;
assert(hash != null, 'Unknown algorithm.');
hmac = hashjs.hmac(hash, key);
return Buffer.from(hmac.update(data).digest());
};
/*
* Key Derivation
*/
backend.pbkdf2 = function pbkdf2(key, salt, iter, len, alg) {
var size = backend.hash(alg, Buffer.alloc(0)).length;
var blocks = Math.ceil(len / size);
var out = Buffer.allocUnsafe(len);
var buf = Buffer.allocUnsafe(salt.length + 4);
var block = Buffer.allocUnsafe(size);
var pos = 0;
var i, j, k, mac;
salt.copy(buf, 0);
for (i = 0; i < blocks; i++) {
buf.writeUInt32BE(i + 1, salt.length, true);
mac = backend.hmac(alg, buf, key);
mac.copy(block, 0);
for (j = 1; j < iter; j++) {
mac = backend.hmac(alg, mac, key);
for (k = 0; k < size; k++)
block[k] ^= mac[k];
}
block.copy(out, pos);
pos += size;
}
return out;
};
backend.pbkdf2Async = function pbkdf2Async(key, salt, iter, len, alg) {
var algo = { name: 'PBKDF2' };
var use = ['deriveBits'];
var name = backend.getHash(alg);
var length = len * 8;
var options, promise;
options = {
name: 'PBKDF2',
salt: salt,
iterations: iter,
hash: name
};
promise = subtle.importKey('raw', key, algo, false, use);
return promise.then(function(key) {
return subtle.deriveBits(options, key, length);
}).then(function(result) {
return Buffer.from(result);
});
};
if (!subtle.deriveBits)
backend.pbkdf2Async = backend.pbkdf2;
/*
* Ciphers
*/
backend.encipher = function encipher(data, key, iv) {
return aes.cbc.encrypt(data, key, iv);
};
backend.decipher = function decipher(data, key, iv) {
try {
return aes.cbc.decrypt(data, key, iv);
} catch (e) {
throw new Error('Bad key for decryption.');
}
};
/*
* Misc
*/
backend.randomBytes = function randomBytes(n) {
var data = new Uint8Array(n);
crypto.getRandomValues(data);
return Buffer.from(data.buffer);
};
if (!crypto.getRandomValues) {
// Out of luck here. Use bad randomness for now.
backend.randomBytes = function randomBytes(n) {
var data = Buffer.allocUnsafe(n);
var i;
for (i = 0; i < data.length; i++)
data[i] = Math.floor(Math.random() * 256);
return data;
};
}
backend.getHash = 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);
}
};
backend.crypto = crypto;
backend.subtle = subtle;

View File

@ -1,102 +0,0 @@
/*!
* backend.js - crypto backend for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var util = require('../utils/util');
var co = require('../utils/co');
var crypto = require('crypto');
var native = require('../utils/native').binding;
var backend = exports;
if (!crypto.pbkdf2Sync)
throw new Error('This modules requires node.js v0.11.0 or above.');
/*
* Hashing
*/
backend.hash = function hash(alg, data) {
return crypto.createHash(alg).update(data).digest();
};
backend.ripemd160 = function ripemd160(data) {
return backend.hash('ripemd160', data);
};
backend.sha1 = function sha1(data) {
return backend.hash('sha1', data);
};
backend.sha256 = function sha256(data) {
return backend.hash('sha256', data);
};
backend.hash160 = function hash160(data) {
return backend.ripemd160(backend.sha256(data));
};
backend.hash256 = function hash256(data) {
return backend.sha256(backend.sha256(data));
};
backend.hmac = function hmac(alg, data, key) {
var hmac = crypto.createHmac(alg, key);
return hmac.update(data).digest();
};
if (native) {
backend.hash = native.hash;
backend.hmac = native.hmac;
backend.ripemd160 = native.ripemd160;
backend.sha1 = native.sha1;
backend.sha256 = native.sha256;
backend.hash160 = native.hash160;
backend.hash256 = native.hash256;
}
/*
* Key Derivation
*/
backend.pbkdf2 = function pbkdf2(key, salt, iter, len, alg) {
return crypto.pbkdf2Sync(key, salt, iter, len, alg);
};
backend.pbkdf2Async = function pbkdf2Async(key, salt, iter, len, alg) {
return new Promise(function(resolve, reject) {
crypto.pbkdf2(key, salt, iter, len, alg, co.wrap(resolve, reject));
});
};
/*
* Ciphers
*/
backend.encipher = function encipher(data, key, iv) {
var cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
return util.concat(cipher.update(data), cipher.final());
};
backend.decipher = function decipher(data, key, iv) {
var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
try {
return util.concat(decipher.update(data), decipher.final());
} catch (e) {
throw new Error('Bad key for decryption.');
}
};
if (native) {
backend.encipher = native.encipher;
backend.decipher = native.decipher;
}
/*
* Misc
*/
backend.randomBytes = crypto.randomBytes;

View File

@ -6,4 +6,14 @@
'use strict';
/**
* @module crypto.BN
*/
/**
* bn.js
* @constructor
* @see https://github.com/indutny/bn.js
*/
module.exports = require('bn.js');

39
lib/crypto/ccmp.js Normal file
View File

@ -0,0 +1,39 @@
/*!
* ccmp.js - constant-time compare for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* 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) {
var i, res;
if (!Buffer.isBuffer(a))
return false;
if (!Buffer.isBuffer(b))
return false;
if (b.length === 0)
return a.length === 0;
res = a.length ^ b.length;
for (i = 0; i < a.length; i++)
res |= a[i] ^ b[i % b.length];
return res === 0;
};

209
lib/crypto/chacha20.js Normal file
View File

@ -0,0 +1,209 @@
/*!
* chacha20.js - chacha20 for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var assert = require('assert');
var native = require('../utils/native').binding;
var 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) {
var i, j;
for (i = 0; i < data.length; i++) {
if (this.pos >= 64) {
for (j = 0; j < 16; j++)
this.stream[j] = this.state[j];
for (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 (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) {
var lo, hi;
if (!counter)
counter = 0;
lo = counter % 0x100000000;
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() {
var lo = this.state[12];
var 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,667 +0,0 @@
/*!
* chachapoly.js - chacha20/poly1305 for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var assert = require('assert');
var native = require('../utils/native').binding;
var BIG_ENDIAN = new Int8Array(new Int16Array([1]).buffer)[0] === 0;
/**
* @module crypto/chachapoly
*/
/**
* ChaCha20 (used for bip151)
* @see https://tools.ietf.org/html/rfc7539#section-2
* @alias module:crypto/chachapoly.ChaCha20
* @constructor
*/
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) {
var i, j;
for (i = 0; i < data.length; i++) {
if (this.pos >= 64) {
for (j = 0; j < 16; j++)
this.stream[j] = this.state[j];
for (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 (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) {
var lo, hi;
if (!counter)
counter = 0;
lo = counter % 0x100000000;
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() {
var lo = this.state[12];
var 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));
}
/**
* Poly1305 (used for bip151)
* @see https://github.com/floodyberry/poly1305-donna
* @see https://tools.ietf.org/html/rfc7539#section-2.5
* @alias module:crypto/chachapoly.Poly1305
* @constructor
*/
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) {
var t0, t1, t2, t3, t4, t5, t6, t7, i;
// r &= 0xffffffc0ffffffc0ffffffc0fffffff
t0 = key.readUInt16LE(0, true);
t1 = key.readUInt16LE(2, true);
t2 = key.readUInt16LE(4, true);
t3 = key.readUInt16LE(6, true);
t4 = key.readUInt16LE(8, true);
t5 = key.readUInt16LE(10, true);
t6 = key.readUInt16LE(12, true);
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 (i = 0; i < 10; i++)
this.h[i] = 0;
// save pad for later
for (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) {
var hibit = this.fin ? 0 : (1 << 11); // 1 << 128
var d = new Uint32Array(10);
var i, j, t0, t1, t2, t3, t4, t5, t6, t7, c;
while (bytes >= 16) {
// h += m[i]
t0 = data.readUInt16LE(m + 0, true);
t1 = data.readUInt16LE(m + 2, true);
t2 = data.readUInt16LE(m + 4, true);
t3 = data.readUInt16LE(m + 6, true);
t4 = data.readUInt16LE(m + 8, true);
t5 = data.readUInt16LE(m + 10, true);
t6 = data.readUInt16LE(m + 12, true);
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
for (i = 0, c = 0; i < 10; i++) {
d[i] = c;
for (j = 0; j < 10; j++) {
d[i] += this.h[j] * (j <= i
? this.r[i - j]
: 5 * this.r[i + 10 - j]);
// 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 (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) {
var bytes = data.length;
var m = 0;
var i, want;
// handle leftover
if (this.leftover) {
want = 16 - this.leftover;
if (want > bytes)
want = bytes;
for (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) {
want = bytes & ~(16 - 1);
this.blocks(data, want, m);
m += want;
bytes -= want;
}
// store leftover
if (bytes) {
for (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() {
var mac = Buffer.allocUnsafe(16);
var g = new Uint16Array(10);
var c, mask, f, i;
// process the remaining block
if (this.leftover) {
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
c = this.h[1] >>> 13;
this.h[1] &= 0x1fff;
for (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 (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
mask = (c ^ 1) - 1;
for (i = 0; i < 10; i++)
g[i] &= mask;
mask = ~mask;
for (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)
f = this.h[0] + this.pad[0];
this.h[0] = f;
for (i = 1; i < 8; i++) {
f = this.h[i] + this.pad[i] + (f >>> 16);
this.h[i] = f;
}
for (i = 0; i < 8; i++)
mac.writeUInt16LE(this.h[i], i * 2, true);
// zero out the state
for (i = 0; i < 10; i++)
this.h[i] = 0;
for (i = 0; i < 10; i++)
this.r[i] = 0;
for (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) {
var 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) {
var dif = 0;
var i;
// Compare in constant time.
for (i = 0; i < 16; i++)
dif |= mac1[i] ^ mac2[i];
dif = (dif - 1) >>> 31;
return (dif & 1) !== 0;
};
if (native)
Poly1305 = native.Poly1305;
/**
* AEAD (used for bip151)
* @exports AEAD
* @see https://github.com/openssh/openssh-portable
* @see https://tools.ietf.org/html/rfc7539#section-2.8
* @alias module:crypto/chachapoly.AEAD
* @constructor
*/
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) {
var 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(aad) {
assert(this.cipherLen === 0, 'Cannot update aad.');
this.poly1305.update(aad);
this.aadLen += aad.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() {
var len = Buffer.allocUnsafe(16);
var 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) {
var pad;
size %= 16;
if (size === 0)
return;
pad = Buffer.allocUnsafe(16 - size);
pad.fill(0);
this.poly1305.update(pad);
};
/*
* Expose
*/
exports.ChaCha20 = ChaCha20;
exports.Poly1305 = Poly1305;
exports.AEAD = AEAD;

34
lib/crypto/cleanse.js Normal file
View File

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

View File

@ -1,451 +0,0 @@
/*!
* crypto.js - crypto 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';
var backend = require('./backend');
var native = require('../utils/native').binding;
var scrypt = require('./scrypt');
/**
* @exports crypto/crypto
* @ignore
*/
var crypto = exports;
/**
* Hash with chosen algorithm.
* @function
* @param {String} alg
* @param {Buffer} data
* @returns {Buffer}
*/
crypto.hash = backend.hash;
/**
* Hash with ripemd160.
* @function
* @param {Buffer} data
* @returns {Buffer}
*/
crypto.ripemd160 = backend.ripemd160;
/**
* Hash with sha1.
* @function
* @param {Buffer} data
* @returns {Buffer}
*/
crypto.sha1 = backend.sha1;
/**
* Hash with sha256.
* @function
* @param {Buffer} data
* @returns {Buffer}
*/
crypto.sha256 = backend.sha256;
/**
* Hash with sha256 and ripemd160 (OP_HASH160).
* @function
* @param {Buffer} data
* @returns {Buffer}
*/
crypto.hash160 = backend.hash160;
/**
* Hash with sha256 twice (OP_HASH256).
* @function
* @param {Buffer} data
* @returns {Buffer}
*/
crypto.hash256 = backend.hash256;
/**
* Create an HMAC.
* @function
* @param {String} alg
* @param {Buffer} data
* @param {Buffer} key
* @returns {Buffer} HMAC
*/
crypto.hmac = backend.hmac;
/**
* Perform key derivation using PBKDF2.
* @function
* @param {Buffer} key
* @param {Buffer} salt
* @param {Number} iter
* @param {Number} len
* @param {String} alg
* @returns {Buffer}
*/
crypto.pbkdf2 = backend.pbkdf2;
/**
* Execute pbkdf2 asynchronously.
* @function
* @param {Buffer} key
* @param {Buffer} salt
* @param {Number} iter
* @param {Number} len
* @param {String} alg
* @returns {Promise}
*/
crypto.pbkdf2Async = backend.pbkdf2Async;
/**
* Perform key derivation using scrypt.
* @function
* @param {Buffer} passwd
* @param {Buffer} salt
* @param {Number} N
* @param {Number} r
* @param {Number} p
* @param {Number} len
* @returns {Buffer}
*/
crypto.scrypt = scrypt.scrypt;
/**
* Execute scrypt asynchronously.
* @function
* @param {Buffer} passwd
* @param {Buffer} salt
* @param {Number} N
* @param {Number} r
* @param {Number} p
* @param {Number} len
* @returns {Promise}
*/
crypto.scryptAsync = scrypt.scryptAsync;
/**
* Perform hkdf extraction.
* @param {Buffer} ikm
* @param {Buffer} key
* @param {String} alg
* @returns {Buffer}
*/
crypto.hkdfExtract = function hkdfExtract(ikm, key, alg) {
return crypto.hmac(alg, ikm, key);
};
/**
* Perform hkdf expansion.
* @param {Buffer} prk
* @param {Buffer} info
* @param {Number} len
* @param {String} alg
* @returns {Buffer}
*/
crypto.hkdfExpand = function hkdfExpand(prk, info, len, alg) {
var size = crypto.hash(alg, Buffer.alloc(0)).length;
var blocks = Math.ceil(len / size);
var i, okm, buf, out;
if (blocks > 255)
throw new Error('Too many blocks.');
okm = Buffer.allocUnsafe(len);
if (blocks === 0)
return okm;
buf = Buffer.allocUnsafe(size + info.length + 1);
// First round:
info.copy(buf, size);
buf[buf.length - 1] = 1;
out = crypto.hmac(alg, buf.slice(size), prk);
out.copy(okm, 0);
for (i = 1; i < blocks; i++) {
out.copy(buf, 0);
buf[buf.length - 1]++;
out = crypto.hmac(alg, buf, prk);
out.copy(okm, i * size);
}
return okm;
};
/**
* Build a merkle tree from leaves.
* Note that this will mutate the `leaves` array!
* @param {Buffer[]} leaves
* @returns {MerkleTree}
*/
crypto.createMerkleTree = function createMerkleTree(leaves) {
var nodes = leaves;
var size = leaves.length;
var malleated = false;
var i, j, k, hash, left, right, lr;
if (size === 0) {
hash = Buffer.allocUnsafe(32);
hash.fill(0);
nodes.push(hash);
return new MerkleTree(nodes, malleated);
}
lr = Buffer.allocUnsafe(64);
for (j = 0; size > 1; size = ((size + 1) / 2) | 0) {
for (i = 0; i < size; i += 2) {
k = Math.min(i + 1, size - 1);
left = nodes[j + i];
right = nodes[j + k];
if (k === i + 1 && k + 1 === size
&& left.equals(right)) {
malleated = true;
}
left.copy(lr, 0);
right.copy(lr, 32);
hash = crypto.hash256(lr);
nodes.push(hash);
}
j += size;
}
return new MerkleTree(nodes, malleated);
};
if (native)
crypto.createMerkleTree = native.createMerkleTree;
/**
* Calculate merkle root from leaves.
* @param {Buffer[]} leaves
* @returns {MerkleRoot}
*/
crypto.createMerkleRoot = function createMerkleRoot(leaves) {
var tree = crypto.createMerkleTree(leaves);
var hash = tree.nodes[tree.nodes.length - 1];
var malleated = tree.malleated;
return new MerkleRoot(hash, malleated);
};
/**
* Collect a merkle branch at vector index.
* @param {Number} index
* @param {Buffer[]} leaves
* @returns {Buffer[]} branch
*/
crypto.createMerkleBranch = function createMerkleBranch(index, leaves) {
var size = leaves.length;
var tree = crypto.createMerkleTree(leaves);
var branch = [];
var j = 0;
var i;
for (; size > 1; size = (size + 1) / 2 | 0) {
i = Math.min(index ^ 1, size - 1);
branch.push(tree.nodes[j + i]);
index >>>= 1;
j += size;
}
return branch;
};
/**
* Check a merkle branch at vector index.
* @param {Buffer} hash
* @param {Buffer[]} branch
* @param {Number} index
* @returns {Buffer} Hash.
*/
crypto.verifyMerkleBranch = function verifyMerkleBranch(hash, branch, index) {
var i, otherside, lr;
if (branch.length === 0)
return hash;
lr = Buffer.allocUnsafe(64);
for (i = 0; i < branch.length; i++) {
otherside = branch[i];
if (index & 1) {
otherside.copy(lr, 0);
hash.copy(lr, 32);
} else {
hash.copy(lr, 0);
otherside.copy(lr, 32);
}
hash = crypto.hash256(lr);
index >>>= 1;
}
return hash;
};
if (native)
crypto.verifyMerkleBranch = native.verifyMerkleBranch;
/**
* Encrypt with aes-256-cbc.
* @function
* @param {Buffer} data
* @param {Buffer} key - 256 bit key.
* @param {Buffer} iv - 128 bit initialization vector.
* @returns {Buffer}
*/
crypto.encipher = backend.encipher;
/**
* Decrypt with aes-256-cbc.
* @function
* @param {Buffer} data
* @param {Buffer} key - 256 bit key.
* @param {Buffer} iv - 128 bit initialization vector.
* @returns {Buffer}
*/
crypto.decipher = backend.decipher;
/**
* memcmp in constant time (can only return true or false).
* This protects us against timing attacks when
* comparing an input against a secret string.
* @see https://cryptocoding.net/index.php/Coding_rules
* @see `$ man 3 memcmp` (NetBSD's consttime_memequal)
* @param {Buffer} a
* @param {Buffer} b
* @returns {Boolean}
*/
crypto.ccmp = function ccmp(a, b) {
var i, res;
if (!Buffer.isBuffer(a))
return false;
if (!Buffer.isBuffer(b))
return false;
if (b.length === 0)
return a.length === 0;
res = a.length ^ b.length;
for (i = 0; i < a.length; i++)
res |= a[i] ^ b[i % b.length];
return res === 0;
};
/**
* A maybe-secure memzero.
* @param {Buffer} data
*/
crypto.cleanse = function cleanse(data) {
var ctr = crypto._counter;
var i;
for (i = 0; i < data.length; i++) {
data[i] = ctr & 0xff;
ctr += i;
}
crypto._counter = ctr >>> 0;
};
crypto._counter = 0;
if (native)
crypto.cleanse = native.cleanse;
/**
* Generate some random bytes.
* @function
* @param {Number} size
* @returns {Buffer}
*/
crypto.randomBytes = backend.randomBytes;
/**
* Generate a random uint32.
* Probably more cryptographically sound than
* `Math.random()`.
* @function
* @returns {Number}
*/
crypto.randomInt = function randomInt() {
return crypto.randomBytes(4).readUInt32LE(0, true);
};
/**
* Generate a random number within a range.
* Probably more cryptographically sound than
* `Math.random()`.
* @function
* @param {Number} min - Inclusive.
* @param {Number} max - Exclusive.
* @returns {Number}
*/
crypto.randomRange = function randomRange(min, max) {
var num = crypto.randomInt();
return Math.floor((num / 0x100000000) * (max - min) + min);
};
/**
* Merkle Tree
* @constructor
* @ignore
* @param {Buffer[]} nodes
* @param {Boolean} malleated
*/
function MerkleTree(nodes, malleated) {
this.nodes = nodes;
this.malleated = malleated;
}
/**
* Merkle Root
* @constructor
* @ignore
* @param {Buffer} hash
* @param {Boolean} malleated
*/
function MerkleRoot(hash, malleated) {
this.hash = hash;
this.malleated = malleated;
}

View File

@ -0,0 +1,105 @@
/*!
* 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
*/
var assert = require('assert');
var hashjs = require('hash.js');
var sha256 = require('./sha256');
/**
* Hash with chosen algorithm.
* @param {String} alg
* @param {Buffer} data
* @returns {Buffer}
*/
exports.hash = function _hash(alg, data) {
var hash;
if (alg === 'sha256')
return sha256.digest(data);
hash = hashjs[alg];
assert(hash != null, 'Unknown algorithm.');
return Buffer.from(hash().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);
};
/**
* Create an HMAC.
* @param {String} alg
* @param {Buffer} data
* @param {Buffer} key
* @returns {Buffer} HMAC
*/
exports.hmac = function _hmac(alg, data, key) {
var hash = hashjs[alg];
var hmac;
assert(hash != null, 'Unknown algorithm.');
hmac = hashjs.hmac(hash, key);
return Buffer.from(hmac.update(data).digest());
};

98
lib/crypto/digest.js Normal file
View File

@ -0,0 +1,98 @@
/*!
* 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
*/
var crypto = require('crypto');
var native = require('../utils/native').binding;
/**
* 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));
};
/**
* Create an HMAC.
* @param {String} alg
* @param {Buffer} data
* @param {Buffer} key
* @returns {Buffer} HMAC
*/
exports.hmac = function hmac(alg, data, key) {
var hmac = crypto.createHmac(alg, key);
return hmac.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;
}

View File

@ -12,7 +12,7 @@
var assert = require('assert');
var elliptic = require('elliptic');
var backend = require('./backend');
var digest = require('./digest');
/**
* Verify ECDSA signature.
@ -34,7 +34,7 @@ exports.verify = function verify(curve, alg, msg, sig, key) {
assert(Buffer.isBuffer(key));
ec = elliptic.ec(curve);
hash = backend.hash(alg, msg);
hash = digest.hash(alg, msg);
try {
return ec.verify(hash, sig, key);
@ -62,7 +62,7 @@ exports.sign = function sign(curve, alg, msg, key) {
assert(Buffer.isBuffer(key));
ec = elliptic.ec(curve);
hash = backend.hash(alg, msg);
hash = digest.hash(alg, msg);
sig = ec.sign(hash, key, { canonical: true });

65
lib/crypto/hkdf.js Normal file
View File

@ -0,0 +1,65 @@
/*!
* hkdf.js - hkdf for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto/hkdf
*/
var 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) {
var size = digest.hash(alg, Buffer.alloc(0)).length;
var blocks = Math.ceil(len / size);
var i, okm, buf, out;
if (blocks > 255)
throw new Error('Too many blocks.');
okm = Buffer.allocUnsafe(len);
if (blocks === 0)
return okm;
buf = Buffer.allocUnsafe(size + info.length + 1);
// First round:
info.copy(buf, size);
buf[buf.length - 1] = 1;
out = digest.hmac(alg, buf.slice(size), prk);
out.copy(okm, 0);
for (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

@ -8,7 +8,7 @@
'use strict';
var assert = require('assert');
var backend = require('./backend');
var digest = require('./digest');
/*
* Constants
@ -73,8 +73,8 @@ HmacDRBG.prototype.iterate = function iterate() {
this.V.copy(data, 0);
data[HASH_SIZE] = 0x00;
this.K = backend.hmac(HASH_ALG, data, this.K);
this.V = backend.hmac(HASH_ALG, this.V, this.K);
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) {
@ -87,13 +87,13 @@ HmacDRBG.prototype.update = function update(seed) {
data[HASH_SIZE] = 0x00;
seed.copy(data, HASH_SIZE + 1);
this.K = backend.hmac(HASH_ALG, data, this.K);
this.V = backend.hmac(HASH_ALG, this.V, this.K);
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 = backend.hmac(HASH_ALG, data, this.K);
this.V = backend.hmac(HASH_ALG, this.V, this.K);
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) {
@ -104,7 +104,7 @@ HmacDRBG.prototype.generate = function generate(len) {
throw new Error('Reseed is required.');
while (pos < len) {
this.V = backend.hmac(HASH_ALG, this.V, this.K);
this.V = digest.hmac(HASH_ALG, this.V, this.K);
this.V.copy(data, pos);
pos += HASH_SIZE;
}

View File

@ -1,349 +1,50 @@
/*!
* crypto/index.js - crypto for bcoin
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto
*/
var crypto = require('./crypto');
/**
* Crypto module.
* @ignore
*/
exports.crypto = crypto;
/**
* Hash with chosen algorithm.
* @function
* @param {String} alg
* @param {Buffer} data
* @returns {Buffer}
*/
exports.hash = crypto.hash;
/**
* Hash with ripemd160.
* @function
* @param {Buffer} data
* @returns {Buffer}
*/
exports.ripemd160 = crypto.ripemd160;
/**
* Hash with sha1.
* @function
* @param {Buffer} data
* @returns {Buffer}
*/
exports.sha1 = crypto.sha1;
/**
* Hash with sha256.
* @function
* @param {Buffer} data
* @returns {Buffer}
*/
exports.sha256 = crypto.sha256;
/**
* Hash with sha256 and ripemd160 (OP_HASH160).
* @function
* @param {Buffer} data
* @returns {Buffer}
*/
exports.hash160 = crypto.hash160;
/**
* Hash with sha256 twice (OP_HASH256).
* @function
* @param {Buffer} data
* @returns {Buffer}
*/
exports.hash256 = crypto.hash256;
/**
* Create an HMAC.
* @function
* @param {String} alg
* @param {Buffer} data
* @param {Buffer} key
* @returns {Buffer} HMAC
*/
exports.hmac = crypto.hmac;
/**
* Perform key derivation using PBKDF2.
* @function
* @param {Buffer} key
* @param {Buffer} salt
* @param {Number} iter
* @param {Number} len
* @param {String} alg
* @returns {Buffer}
*/
exports.pbkdf2 = crypto.pbkdf2;
/**
* Execute pbkdf2 asynchronously.
* @function
* @param {Buffer} key
* @param {Buffer} salt
* @param {Number} iter
* @param {Number} len
* @param {String} alg
* @returns {Promise}
*/
exports.pbkdf2Async = crypto.pbkdf2Async;
/**
* Perform key derivation using scrypt.
* @function
* @param {Buffer} passwd
* @param {Buffer} salt
* @param {Number} N
* @param {Number} r
* @param {Number} p
* @param {Number} len
* @returns {Buffer}
*/
exports.scrypt = crypto.scrypt;
/**
* Execute scrypt asynchronously.
* @function
* @param {Buffer} passwd
* @param {Buffer} salt
* @param {Number} N
* @param {Number} r
* @param {Number} p
* @param {Number} len
* @returns {Promise}
*/
exports.scryptAsync = crypto.scryptAsync;
/**
* Perform hkdf extraction.
* @function
* @param {Buffer} ikm
* @param {Buffer} key
* @param {String} alg
* @returns {Buffer}
*/
exports.hkdfExtract = crypto.hkdfExtract;
/**
* Perform hkdf expansion.
* @function
* @param {Buffer} prk
* @param {Buffer} info
* @param {Number} len
* @param {String} alg
* @returns {Buffer}
*/
exports.hkdfExpand = crypto.hkdfExpand;
/**
* Build a merkle tree from leaves.
* Note that this will mutate the `leaves` array!
* @function
* @param {Buffer[]} leaves
* @returns {MerkleTree}
*/
exports.createMerkleTree = crypto.createMerkleTree;
/**
* Calculate merkle root from leaves.
* @function
* @param {Buffer[]} leaves
* @returns {MerkleRoot}
*/
exports.createMerkleRoot = crypto.createMerkleRoot;
/**
* Collect a merkle branch at vector index.
* @function
* @param {Number} index
* @param {Buffer[]} leaves
* @returns {Buffer[]} branch
*/
exports.createMerkleBranch = crypto.createMerkleBranch;
/**
* Check a merkle branch at vector index.
* @function
* @param {Buffer} hash
* @param {Buffer[]} branch
* @param {Number} index
* @returns {Buffer} Hash.
*/
exports.verifyMerkleBranch = crypto.verifyMerkleBranch;
/**
* Encrypt with aes-256-cbc.
* @function
* @param {Buffer} data
* @param {Buffer} key - 256 bit key.
* @param {Buffer} iv - 128 bit initialization vector.
* @returns {Buffer}
*/
exports.encipher = crypto.encipher;
/**
* Decrypt with aes-256-cbc.
* @function
* @param {Buffer} data
* @param {Buffer} key - 256 bit key.
* @param {Buffer} iv - 128 bit initialization vector.
* @returns {Buffer}
*/
exports.decipher = crypto.decipher;
/**
* memcmp in constant time (can only return true or false).
* This protects us against timing attacks when
* comparing an input against a secret string.
* @function
* @see https://cryptocoding.net/index.php/Coding_rules
* @see `$ man 3 memcmp` (NetBSD's consttime_memequal)
* @param {Buffer} a
* @param {Buffer} b
* @returns {Boolean}
*/
exports.ccmp = crypto.ccmp;
/**
* A maybe-secure memzero.
* @function
* @param {Buffer} data
*/
exports.cleanse = crypto.cleanse;
/**
* Generate some random bytes.
* @function
* @param {Number} size
* @returns {Buffer}
*/
exports.randomBytes = crypto.randomBytes;
/**
* Generate a random uint32.
* Probably more cryptographically sound than
* `Math.random()`.
* @function
* @returns {Number}
*/
exports.randomInt = crypto.randomInt;
/**
* Generate a random number within a range.
* Probably more cryptographically sound than
* `Math.random()`.
* @function
* @param {Number} min - Inclusive.
* @param {Number} max - Exclusive.
* @returns {Number}
*/
exports.randomRange = crypto.randomRange;
/**
* chachapoly module
* @see module:crypto/chachapoly
*/
exports.chachapoly = require('./chachapoly');
/**
* ChaCha20
* @see module:crypto/chachapoly.ChaCha20
*/
exports.ChaCha20 = exports.chachapoly.ChaCha20;
/**
* Poly1305
* @see module:crypto/chachapoly.Poly1305
*/
exports.Poly1305 = exports.chachapoly.Poly1305;
/**
* AEAD
* @see module:crypto/chachapoly.AEAD
*/
exports.AEAD = exports.chachapoly.AEAD;
/**
* BN
* @see https://github.com/indutny/bn.js
*/
var digest = require('./digest');
var random = require('./random');
var aes = require('./aes');
exports.aes = require('./aes');
exports.AEAD = require('./aead');
exports.BN = require('./bn');
/**
* RSA
* @see module:crypto/rsa
*/
exports.rsa = require('./rsa');
/**
* ECDSA
* @see module:crypto/ecdsa
*/
exports.ccmp = require('./ccmp');
exports.ChaCha20 = require('./chacha20');
exports.cleanse = require('./cleanse');
exports.digest = require('./digest');
exports.ecdsa = require('./ecdsa');
/**
* secp256k1 module
* @see module:crypto/secp256k1
*/
exports.secp256k1 = require('./secp256k1');
/**
* schnorr module
* @see module:crypto/schnorr
*/
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');
/**
* siphash module
* @see module:crypto/siphash
*/
exports.scrypt = require('./scrypt');
exports.secp256k1 = require('./secp256k1');
exports.siphash = require('./siphash');
/**
* siphash256
* @see module:crypto/siphash.siphash256
*/
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.hmac = digest.hmac;
exports.siphash256 = exports.siphash.siphash256;
exports.encipher = aes.encipher;
exports.decipher = aes.decipher;
exports.randomBytes = random.randomBytes;
exports.randomInt = random.randomInt;
exports.randomRange = random.randomRange;

164
lib/crypto/merkle.js Normal file
View File

@ -0,0 +1,164 @@
/*!
* 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
*/
var digest = require('./digest');
var native = require('../utils/native').binding;
/**
* Build a merkle tree from leaves.
* Note that this will mutate the `leaves` array!
* @param {Buffer[]} leaves
* @returns {MerkleTree}
*/
exports.createTree = function createTree(leaves) {
var nodes = leaves;
var size = leaves.length;
var malleated = false;
var i, j, k, hash, left, right, lr;
if (size === 0) {
hash = Buffer.allocUnsafe(32);
hash.fill(0);
nodes.push(hash);
return new MerkleTree(nodes, malleated);
}
lr = Buffer.allocUnsafe(64);
for (j = 0; size > 1; size = ((size + 1) / 2) | 0) {
for (i = 0; i < size; i += 2) {
k = Math.min(i + 1, size - 1);
left = nodes[j + i];
right = nodes[j + k];
if (k === i + 1 && k + 1 === size
&& left.equals(right)) {
malleated = true;
}
left.copy(lr, 0);
right.copy(lr, 32);
hash = digest.hash256(lr);
nodes.push(hash);
}
j += size;
}
return new MerkleTree(nodes, malleated);
};
if (native)
exports.createTree = native.createMerkleTree;
/**
* Calculate merkle root from leaves.
* @param {Buffer[]} leaves
* @returns {MerkleRoot}
*/
exports.createRoot = function createRoot(leaves) {
var tree = exports.createTree(leaves);
var hash = tree.nodes[tree.nodes.length - 1];
var malleated = tree.malleated;
return new MerkleRoot(hash, malleated);
};
/**
* Collect a merkle branch at vector index.
* @param {Number} index
* @param {Buffer[]} leaves
* @returns {Buffer[]} branch
*/
exports.createBranch = function createBranch(index, leaves) {
var size = leaves.length;
var tree = exports.createTree(leaves);
var branch = [];
var j = 0;
var i;
for (; size > 1; size = (size + 1) / 2 | 0) {
i = Math.min(index ^ 1, size - 1);
branch.push(tree.nodes[j + i]);
index >>>= 1;
j += size;
}
return branch;
};
/**
* Check a merkle branch at vector index.
* @param {Buffer} hash
* @param {Buffer[]} branch
* @param {Number} index
* @returns {Buffer} Hash.
*/
exports.verifyBranch = function verifyBranch(hash, branch, index) {
var i, otherside, lr;
if (branch.length === 0)
return hash;
lr = Buffer.allocUnsafe(64);
for (i = 0; i < branch.length; i++) {
otherside = branch[i];
if (index & 1) {
otherside.copy(lr, 0);
hash.copy(lr, 32);
} else {
hash.copy(lr, 0);
otherside.copy(lr, 32);
}
hash = digest.hash256(lr);
index >>>= 1;
}
return hash;
};
if (native)
exports.verifyBranch = native.verifyMerkleBranch;
/**
* Merkle Tree
* @constructor
* @ignore
* @param {Buffer[]} nodes
* @param {Boolean} malleated
*/
function MerkleTree(nodes, malleated) {
this.nodes = nodes;
this.malleated = malleated;
}
/**
* Merkle Root
* @constructor
* @ignore
* @param {Buffer} hash
* @param {Boolean} malleated
*/
function MerkleRoot(hash, malleated) {
this.hash = hash;
this.malleated = malleated;
}

View File

@ -0,0 +1,108 @@
/*!
* 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
*/
var digest = require('./digest');
var crypto = global.crypto || global.msCrypto || {};
var subtle = crypto.subtle && crypto.subtle.importKey ? 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) {
var size = digest.hash(alg, Buffer.alloc(0)).length;
var blocks = Math.ceil(len / size);
var out = Buffer.allocUnsafe(len);
var buf = Buffer.allocUnsafe(salt.length + 4);
var block = Buffer.allocUnsafe(size);
var pos = 0;
var i, j, k, mac;
salt.copy(buf, 0);
for (i = 0; i < blocks; i++) {
buf.writeUInt32BE(i + 1, salt.length, true);
mac = digest.hmac(alg, buf, key);
mac.copy(block, 0);
for (j = 1; j < iter; j++) {
mac = digest.hmac(alg, mac, key);
for (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 = function deriveAsync(key, salt, iter, len, alg) {
var algo = { name: 'PBKDF2' };
var use = ['deriveBits'];
var name = getHash(alg);
var length = len * 8;
var options, promise;
options = {
name: 'PBKDF2',
salt: salt,
iterations: iter,
hash: name
};
promise = subtle.importKey('raw', key, algo, false, use);
return promise.then(function(key) {
return subtle.deriveBits(options, key, length);
}).then(function(result) {
return Buffer.from(result);
});
};
if (!subtle.deriveBits)
exports.pbkdf2Async = exports.pbkdf2;
/*
* 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);
}
}

44
lib/crypto/pbkdf2.js Normal file
View File

@ -0,0 +1,44 @@
/*!
* pbkdf2.js - pbkdf2 for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto.pbkdf2
*/
var co = require('../utils/co');
var 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(function(resolve, reject) {
crypto.pbkdf2(key, salt, iter, len, alg, co.wrap(resolve, reject));
});
};

309
lib/crypto/poly1305.js Normal file
View File

@ -0,0 +1,309 @@
/*!
* poly1305.js - poly1305 for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var native = require('../utils/native').binding;
/**
* Poly1305 (used for bip151)
* @alias module:crypto.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) {
var t0, t1, t2, t3, t4, t5, t6, t7, i;
// r &= 0xffffffc0ffffffc0ffffffc0fffffff
t0 = key.readUInt16LE(0, true);
t1 = key.readUInt16LE(2, true);
t2 = key.readUInt16LE(4, true);
t3 = key.readUInt16LE(6, true);
t4 = key.readUInt16LE(8, true);
t5 = key.readUInt16LE(10, true);
t6 = key.readUInt16LE(12, true);
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 (i = 0; i < 10; i++)
this.h[i] = 0;
// save pad for later
for (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) {
var hibit = this.fin ? 0 : (1 << 11); // 1 << 128
var d = new Uint32Array(10);
var i, j, t0, t1, t2, t3, t4, t5, t6, t7, c;
while (bytes >= 16) {
// h += m[i]
t0 = data.readUInt16LE(m + 0, true);
t1 = data.readUInt16LE(m + 2, true);
t2 = data.readUInt16LE(m + 4, true);
t3 = data.readUInt16LE(m + 6, true);
t4 = data.readUInt16LE(m + 8, true);
t5 = data.readUInt16LE(m + 10, true);
t6 = data.readUInt16LE(m + 12, true);
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
for (i = 0, c = 0; i < 10; i++) {
d[i] = c;
for (j = 0; j < 10; j++) {
d[i] += this.h[j] * (j <= i
? this.r[i - j]
: 5 * this.r[i + 10 - j]);
// 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 (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) {
var bytes = data.length;
var m = 0;
var i, want;
// handle leftover
if (this.leftover) {
want = 16 - this.leftover;
if (want > bytes)
want = bytes;
for (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) {
want = bytes & ~(16 - 1);
this.blocks(data, want, m);
m += want;
bytes -= want;
}
// store leftover
if (bytes) {
for (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() {
var mac = Buffer.allocUnsafe(16);
var g = new Uint16Array(10);
var c, mask, f, i;
// process the remaining block
if (this.leftover) {
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
c = this.h[1] >>> 13;
this.h[1] &= 0x1fff;
for (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 (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
mask = (c ^ 1) - 1;
for (i = 0; i < 10; i++)
g[i] &= mask;
mask = ~mask;
for (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)
f = this.h[0] + this.pad[0];
this.h[0] = f;
for (i = 1; i < 8; i++) {
f = this.h[i] + this.pad[i] + (f >>> 16);
this.h[i] = f;
}
for (i = 0; i < 8; i++)
mac.writeUInt16LE(this.h[i], i * 2, true);
// zero out the state
for (i = 0; i < 10; i++)
this.h[i] = 0;
for (i = 0; i < 10; i++)
this.r[i] = 0;
for (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) {
var 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) {
var dif = 0;
var i;
// Compare in constant time.
for (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

@ -0,0 +1,64 @@
/*!
* 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
*/
var crypto = global.crypto || global.msCrypto || {};
/**
* Generate some random bytes.
* @param {Number} size
* @returns {Buffer}
*/
exports.randomBytes = function randomBytes(n) {
var data = new Uint8Array(n);
crypto.getRandomValues(data);
return Buffer.from(data.buffer);
};
if (!crypto.getRandomValues) {
// Out of luck here. Use bad randomness for now.
exports.randomBytes = function randomBytes(n) {
var data = Buffer.allocUnsafe(n);
var i;
for (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) {
var num = exports.randomInt();
return Math.floor((num / 0x100000000) * (max - min) + min);
};

44
lib/crypto/random.js Normal file
View File

@ -0,0 +1,44 @@
/*!
* random.js - randomness for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto.random
*/
var crypto = require('crypto');
/*
* Misc
*/
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) {
var num = exports.randomInt();
return Math.floor((num / 0x100000000) * (max - min) + min);
};

View File

@ -9,7 +9,8 @@
var assert = require('assert');
var BN = require('./bn');
var ASN1 = require('../utils/asn1');
var backend = require('./backend');
var digest = require('./digest');
var ccmp = require('./ccmp');
/**
* @exports crypto/rsa
@ -55,7 +56,7 @@ rsa.verify = function verify(alg, msg, sig, key) {
if (!prefix)
throw new Error('Unknown PKCS prefix.');
hash = backend.hash(alg, msg);
hash = digest.hash(alg, msg);
len = prefix.length + hash.length;
pub = ASN1.parseRSAPublic(key);
@ -71,8 +72,8 @@ rsa.verify = function verify(alg, msg, sig, key) {
ok = ceq(em[0], 0x00);
ok &= ceq(em[1], 0x01);
ok &= backend.ccmp(em.slice(k - hash.length, k), hash);
ok &= backend.ccmp(em.slice(k - len, k - hash.length), prefix);
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 (i = 2; i < k - len - 1; i++)
@ -101,7 +102,7 @@ rsa.sign = function sign(alg, msg, key) {
if (!prefix)
throw new Error('Unknown PKCS prefix.');
hash = backend.hash(alg, msg);
hash = digest.hash(alg, msg);
len = prefix.length + hash.length;
priv = ASN1.parseRSAPrivate(key);

View File

@ -11,7 +11,7 @@ var elliptic = require('elliptic');
var Signature = require('elliptic/lib/elliptic/ec/signature');
var BN = require('./bn');
var HmacDRBG = require('./hmac-drbg');
var sha256 = require('./backend').sha256;
var sha256 = require('./digest').sha256;
var curve = elliptic.ec('secp256k1').curve;
var POOL64 = Buffer.allocUnsafe(64);

View File

@ -35,19 +35,17 @@
/**
* @module crypto/scrypt
* @ignore
*/
var co = require('../utils/co');
var backend = require('./backend');
var pbkdf2 = require('./pbkdf2');
var native = require('../utils/native').binding;
var U32Array = typeof Uint32Array === 'function' ? Uint32Array : Array;
/**
* 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.scrypt
* @alias module:crypto/scrypt.derive
* @param {Buffer} passwd
* @param {Buffer} salt
* @param {Number} N
@ -57,7 +55,7 @@ var U32Array = typeof Uint32Array === 'function' ? Uint32Array : Array;
* @returns {Buffer}
*/
function scrypt(passwd, salt, N, r, p, len) {
function derive(passwd, salt, N, r, p, len) {
var i, B, V, XY;
if (r * p >= (1 << 30))
@ -72,20 +70,63 @@ function scrypt(passwd, salt, N, r, p, len) {
XY = Buffer.allocUnsafe(256 * r);
V = Buffer.allocUnsafe(128 * r * N);
B = backend.pbkdf2(passwd, salt, 1, p * 128 * r, 'sha256');
B = pbkdf2.derive(passwd, salt, 1, p * 128 * r, 'sha256');
for (i = 0; i < p; i++)
smix(B, i * 128 * r, r, N, V, XY);
return backend.pbkdf2(passwd, B, 1, len, 'sha256');
return pbkdf2.derive(passwd, B, 1, len, 'sha256');
}
if (native)
scrypt = native.scrypt;
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) {
var i, B, V, XY;
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');
XY = Buffer.allocUnsafe(256 * r);
V = Buffer.allocUnsafe(128 * r * N);
B = await pbkdf2.deriveAsync(passwd, salt, 1, p * 128 * r, 'sha256');
for (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) {
var B32 = new U32Array(16);
var x = new U32Array(16);
var B32 = new Uint32Array(16);
var x = new Uint32Array(16);
var i;
for (i = 0; i < 16; i++)
@ -192,54 +233,6 @@ function smix(B, Bo, r, N, V, XY) {
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 (var i = 0; i < len; i++)
dest[s1 + i] ^= src[s2 + i];
}
/**
* Asynchronous scrypt implementation.
* @alias module:crypto/scrypt.scryptAsync
* @function
* @param {Buffer} passwd
* @param {Buffer} salt
* @param {Number} N
* @param {Number} r
* @param {Number} p
* @param {Number} len
* @returns {Promise}
*/
async function scryptAsync(passwd, salt, N, r, p, len) {
var i, B, V, XY;
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');
XY = Buffer.allocUnsafe(256 * r);
V = Buffer.allocUnsafe(128 * r * N);
B = await backend.pbkdf2Async(passwd, salt, 1, p * 128 * r, 'sha256');
for (i = 0; i < p; i++)
await smixAsync(B, i * 128 * r, r, N, V, XY);
return await backend.pbkdf2Async(passwd, B, 1, len, 'sha256');
}
if (native)
scryptAsync = native.scryptAsync;
async function smixAsync(B, Bo, r, N, V, XY) {
var X = XY;
var Y = XY;
@ -264,12 +257,18 @@ async function smixAsync(B, Bo, r, N, V, XY) {
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 (var i = 0; i < len; i++)
dest[s1 + i] ^= src[s2 + i];
}
/*
* Expose
*/
exports = scrypt;
exports.scrypt = scrypt;
exports.scryptAsync = scryptAsync;
module.exports = exports;
exports.derive = derive;
exports.deriveAsync = deriveAsync;

View File

@ -8,7 +8,7 @@
'use strict';
var assert = require('assert');
var backend = require('./backend');
var random = require('./random');
var secp256k1 = require('secp256k1');
/**
@ -47,7 +47,7 @@ ec.generatePrivateKey = function generatePrivateKey() {
var priv;
do {
priv = backend.randomBytes(32);
priv = random.randomBytes(32);
} while (!secp256k1.privateKeyVerify(priv));
return priv;

View File

@ -1,3 +1,9 @@
/*!
* hd/index.js - hd keys for bcoin
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
module.exports = require('./hd');

View File

@ -8,7 +8,10 @@
var assert = require('assert');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var cleanse = require('../crypto/cleanse');
var random = require('../crypto/random');
var pbkdf2 = require('../crypto/pbkdf2');
var StaticWriter = require('../utils/staticwriter');
var BufferReader = require('../utils/reader');
var encoding = require('../utils/encoding');
@ -123,7 +126,7 @@ Mnemonic.prototype.destroy = function destroy() {
this.bits = common.MIN_ENTROPY;
this.language = 'english';
if (this.entropy) {
crypto.cleanse(this.entropy);
cleanse(this.entropy);
this.entropy = null;
}
this.phrase = null;
@ -147,7 +150,7 @@ Mnemonic.prototype.toSeed = function toSeed(passphrase) {
phrase = nfkd(this.getPhrase());
passwd = nfkd('mnemonic' + passphrase);
return crypto.pbkdf2(
return pbkdf2.derive(
Buffer.from(phrase, 'utf8'),
Buffer.from(passwd, 'utf8'),
2048, 64, 'sha512');
@ -160,7 +163,7 @@ Mnemonic.prototype.toSeed = function toSeed(passphrase) {
Mnemonic.prototype.getEntropy = function getEntropy() {
if (!this.entropy)
this.entropy = crypto.randomBytes(this.bits / 8);
this.entropy = random.randomBytes(this.bits / 8);
assert(this.bits / 8 === this.entropy.length);
@ -194,7 +197,7 @@ Mnemonic.prototype.getPhrase = function getPhrase() {
// the checksum bits.
entropy = Buffer.allocUnsafe(Math.ceil(bits / 8));
ent.copy(entropy, 0);
crypto.sha256(ent).copy(entropy, ent.length);
digest.sha256(ent).copy(entropy, ent.length);
// Build the mnemonic by reading
// 11 bit indexes from the entropy.
@ -268,7 +271,7 @@ Mnemonic.prototype.fromPhrase = function fromPhrase(phrase) {
entropy = ent.slice(0, ent.length - cbytes);
ent = ent.slice(ent.length - cbytes);
chk = crypto.sha256(entropy);
chk = digest.sha256(entropy);
for (i = 0; i < cbits; i++) {
bit = i % 8;

View File

@ -8,7 +8,9 @@
var assert = require('assert');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var cleanse = require('../crypto/cleanse');
var random = require('../crypto/random');
var secp256k1 = require('../crypto/secp256k1');
var Network = require('../protocol/network');
var StaticWriter = require('../utils/staticwriter');
@ -149,13 +151,13 @@ HDPrivateKey.prototype.destroy = function destroy(pub) {
this.depth = 0;
this.childIndex = 0;
crypto.cleanse(this.parentFingerPrint);
crypto.cleanse(this.chainCode);
crypto.cleanse(this.privateKey);
crypto.cleanse(this.publicKey);
cleanse(this.parentFingerPrint);
cleanse(this.chainCode);
cleanse(this.privateKey);
cleanse(this.publicKey);
if (this.fingerPrint) {
crypto.cleanse(this.fingerPrint);
cleanse(this.fingerPrint);
this.fingerPrint = null;
}
@ -208,7 +210,7 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
data = bw.render();
hash = crypto.hmac('sha512', data, this.chainCode);
hash = digest.hmac('sha512', data, this.chainCode);
left = hash.slice(0, 32);
right = hash.slice(32, 64);
@ -219,7 +221,7 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
}
if (!this.fingerPrint)
this.fingerPrint = crypto.hash160(this.publicKey).slice(0, 4);
this.fingerPrint = digest.hash160(this.publicKey).slice(0, 4);
child = new HDPrivateKey();
child.network = this.network;
@ -465,7 +467,7 @@ HDPrivateKey.prototype.fromSeed = function fromSeed(seed, network) {
throw new Error('Entropy not in range.');
}
hash = crypto.hmac('sha512', seed, common.SEED_SALT);
hash = digest.hmac('sha512', seed, common.SEED_SALT);
left = hash.slice(0, 32);
right = hash.slice(32, 64);
@ -583,7 +585,7 @@ HDPrivateKey.fromKey = function fromKey(key, entropy, network) {
HDPrivateKey.generate = function generate(network) {
var key = secp256k1.generatePrivateKey();
var entropy = crypto.randomBytes(32);
var entropy = random.randomBytes(32);
return HDPrivateKey.fromKey(key, entropy, network);
};

View File

@ -8,7 +8,8 @@
var assert = require('assert');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var cleanse = require('../crypto/cleanse');
var secp256k1 = require('../crypto/secp256k1');
var Network = require('../protocol/network');
var StaticWriter = require('../utils/staticwriter');
@ -129,12 +130,12 @@ HDPublicKey.prototype.destroy = function destroy() {
this.depth = 0;
this.childIndex = 0;
crypto.cleanse(this.parentFingerPrint);
crypto.cleanse(this.chainCode);
crypto.cleanse(this.publicKey);
cleanse(this.parentFingerPrint);
cleanse(this.chainCode);
cleanse(this.publicKey);
if (this.fingerPrint) {
crypto.cleanse(this.fingerPrint);
cleanse(this.fingerPrint);
this.fingerPrint = null;
}
@ -175,7 +176,7 @@ HDPublicKey.prototype.derive = function derive(index, hardened) {
bw.writeU32BE(index);
data = bw.render();
hash = crypto.hmac('sha512', data, this.chainCode);
hash = digest.hmac('sha512', data, this.chainCode);
left = hash.slice(0, 32);
right = hash.slice(32, 64);
@ -186,7 +187,7 @@ HDPublicKey.prototype.derive = function derive(index, hardened) {
}
if (!this.fingerPrint)
this.fingerPrint = crypto.hash160(this.publicKey).slice(0, 4);
this.fingerPrint = digest.hash160(this.publicKey).slice(0, 4);
child = new HDPublicKey();
child.network = this.network;

View File

@ -19,7 +19,8 @@ var co = require('../utils/co');
var Validator = require('../utils/validator');
var List = require('../utils/list');
var fs = require('../utils/fs');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var ccmp = require('../crypto/ccmp');
var ListItem = List.Item;
/**
@ -198,14 +199,14 @@ HTTPBase.prototype.basicAuth = function basicAuth(options) {
if (typeof user === 'string')
user = Buffer.from(user, 'utf8');
assert(Buffer.isBuffer(user));
user = crypto.hash256(user);
user = digest.hash256(user);
}
if (typeof pass === 'string')
pass = Buffer.from(pass, 'utf8');
assert(Buffer.isBuffer(pass));
pass = crypto.hash256(pass);
pass = digest.hash256(pass);
if (!realm)
realm = 'server';
@ -220,7 +221,7 @@ HTTPBase.prototype.basicAuth = function basicAuth(options) {
return async function(req, res) {
var auth = req.headers['authorization'];
var parts, username, password, digest;
var parts, username, password, hash;
if (!auth)
return fail(res);
@ -240,17 +241,17 @@ HTTPBase.prototype.basicAuth = function basicAuth(options) {
password = parts.join(':');
if (user) {
digest = Buffer.from(username, 'utf8');
digest = crypto.hash256(digest);
hash = Buffer.from(username, 'utf8');
hash = digest.hash256(hash);
if (!crypto.ccmp(digest, user))
if (!ccmp(hash, user))
return fail(res);
}
digest = Buffer.from(password, 'utf8');
digest = crypto.hash256(digest);
hash = Buffer.from(password, 'utf8');
hash = digest.hash256(hash);
if (!crypto.ccmp(digest, pass))
if (!ccmp(hash, pass))
return fail(res);
req.username = username;

View File

@ -8,7 +8,8 @@
var util = require('../utils/util');
var co = require('../utils/co');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var ccmp = require('../crypto/ccmp');
var assert = require('assert');
var common = require('../blockchain/common');
var secp256k1 = require('../crypto/secp256k1');
@ -2065,16 +2066,16 @@ RPC.prototype.verifyMessage = async function verifyMessage(args, help) {
addr = parseAddress(b58, this.network);
msg = Buffer.from(MAGIC_STRING + msg, 'utf8');
msg = crypto.hash256(msg);
msg = digest.hash256(msg);
key = secp256k1.recover(msg, sig, 0, true);
if (!key)
return false;
key = crypto.hash160(key);
key = digest.hash160(key);
return crypto.ccmp(key, addr.hash);
return ccmp(key, addr.hash);
};
RPC.prototype.signMessageWithPrivkey = async function signMessageWithPrivkey(args, help) {
@ -2090,7 +2091,7 @@ RPC.prototype.signMessageWithPrivkey = async function signMessageWithPrivkey(arg
key = parseSecret(key, this.network);
msg = Buffer.from(MAGIC_STRING + msg, 'utf8');
msg = crypto.hash256(msg);
msg = digest.hash256(msg);
sig = key.sign(msg);

View File

@ -15,7 +15,9 @@ var Amount = require('../btc/amount');
var Bloom = require('../utils/bloom');
var TX = require('../primitives/tx');
var Outpoint = require('../primitives/outpoint');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var random = require('../crypto/random');
var ccmp = require('../crypto/ccmp');
var Network = require('../protocol/network');
var Validator = require('../utils/validator');
var pkg = require('../pkg');
@ -389,7 +391,7 @@ HTTPServer.prototype.handleSocket = function handleSocket(socket) {
throw new Error('Already authed.');
if (!this.options.noAuth) {
if (!crypto.ccmp(hash256(key), hash))
if (!ccmp(hash256(key), hash))
throw new Error('Bad key.');
}
@ -739,7 +741,7 @@ function HTTPOptions(options) {
this.network = Network.primary;
this.logger = null;
this.node = null;
this.apiKey = base58.encode(crypto.randomBytes(20));
this.apiKey = base58.encode(random.randomBytes(20));
this.apiHash = hash256(this.apiKey);
this.noAuth = false;
@ -854,7 +856,7 @@ function hash256(data) {
if (data.length > 200)
return Buffer.alloc(0);
return crypto.hash256(Buffer.from(data, 'utf8'));
return digest.hash256(Buffer.from(data, 'utf8'));
}
function enforce(value, msg) {

View File

@ -11,7 +11,7 @@ var AsyncObject = require('../utils/asyncobject');
var common = require('../blockchain/common');
var policy = require('../protocol/policy');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var random = require('../crypto/random');
var errors = require('../protocol/errors');
var Bloom = require('../utils/bloom');
var Address = require('../primitives/address');
@ -1667,7 +1667,7 @@ Mempool.prototype.limitOrphans = function limitOrphans() {
if (this.totalOrphans < this.options.maxOrphans)
return false;
index = crypto.randomRange(0, hashes.length);
index = random.randomRange(0, hashes.length);
hash = hashes[index];
this.logger.debug('Removing orphan %s from mempool.', util.revHex(hash));

View File

@ -7,7 +7,7 @@
'use strict';
var assert = require('assert');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
/**
* Hash until the nonce overflows.
@ -27,7 +27,7 @@ function mine(data, target, min, max) {
// The heart and soul of the miner: match the target.
while (nonce <= max) {
// Hash and test against the next target.
if (rcmp(crypto.hash256(data), target) <= 0)
if (rcmp(digest.hash256(data), target) <= 0)
return nonce;
// Increment the nonce to get a different hash.

View File

@ -9,7 +9,8 @@
var assert = require('assert');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var merkle = require('../crypto/merkle');
var BN = require('../crypto/bn');
var StaticWriter = require('../utils/staticwriter');
var Address = require('../primitives/address');
@ -181,13 +182,13 @@ BlockTemplate.prototype.getWitnessHash = function getWitnessHash() {
leaves.push(item.tx.witnessHash());
}
root = crypto.createMerkleRoot(leaves);
root = merkle.createRoot(leaves);
assert(!root.malleated);
data = util.concat(root.hash, nonce);
return crypto.hash256(data);
return digest.hash256(data);
};
/**
@ -389,7 +390,7 @@ BlockTemplate.prototype.getRawCoinbase = function getRawCoinbase(nonce1, nonce2)
BlockTemplate.prototype.getRoot = function getRoot(nonce1, nonce2) {
var raw = this.getRawCoinbase(nonce1, nonce2);
var hash = crypto.hash256(raw);
var hash = digest.hash256(raw);
return this.tree.withFirst(hash);
};
@ -426,7 +427,7 @@ BlockTemplate.prototype.getHeader = function getHeader(root, ts, nonce) {
BlockTemplate.prototype.getProof = function getProof(nonce1, nonce2, ts, nonce) {
var root = this.getRoot(nonce1, nonce2);
var data = this.getHeader(root, ts, nonce);
var hash = crypto.hash256(data);
var hash = digest.hash256(data);
return new BlockProof(hash, root, nonce1, nonce2, ts, nonce);
};
@ -705,7 +706,7 @@ MerkleTree.prototype.withFirst = function withFirst(hash) {
for (i = 0; i < this.steps.length; i++) {
step = this.steps[i];
data = util.concat(hash, step);
hash = crypto.hash256(data);
hash = digest.hash256(data);
}
return hash;
@ -773,7 +774,7 @@ MerkleTree.prototype.fromLeaves = function fromLeaves(leaves) {
for (i = 2; i < len; i += 2) {
data = util.concat(leaves[i], leaves[i + 1]);
hash = crypto.hash256(data);
hash = digest.hash256(data);
hashes.push(hash);
}

View File

@ -13,7 +13,9 @@ var path = require('path');
var EventEmitter = require('events').EventEmitter;
var util = require('../utils/util');
var co = require('../utils/co');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var random = require('../crypto/random');
var ccmp = require('../crypto/ccmp');
var packets = require('./packets');
var secp256k1 = require('../crypto/secp256k1');
var StaticWriter = require('../utils/staticwriter');
@ -131,7 +133,7 @@ BIP150.prototype.challenge = function challenge(hash) {
msg = this.hash(this.input.sid, type, this.publicKey);
if (!crypto.ccmp(hash, msg))
if (!ccmp(hash, msg))
return encoding.ZERO_SIG64;
if (this.isAuthed()) {
@ -165,7 +167,7 @@ BIP150.prototype.reply = function reply(data) {
throw new Error('Auth failure.');
if (!this.peerIdentity)
return crypto.randomBytes(32);
return random.randomBytes(32);
sig = secp256k1.toDER(data);
msg = this.hash(this.output.sid, type, this.peerIdentity);
@ -173,7 +175,7 @@ BIP150.prototype.reply = function reply(data) {
result = secp256k1.verify(msg, sig, this.peerIdentity);
if (!result)
return crypto.randomBytes(32);
return random.randomBytes(32);
if (this.isAuthed()) {
this.auth = true;
@ -257,7 +259,7 @@ BIP150.prototype.rekey = function rekey(sid, key, req, res) {
key.copy(seed, 32);
req.copy(seed, 64);
res.copy(seed, 97);
return crypto.hash256(seed);
return digest.hash256(seed);
};
/**
@ -301,7 +303,7 @@ BIP150.prototype.hash = function hash(sid, ch, key) {
sid.copy(data, 0);
data[32] = ch.charCodeAt(0);
key.copy(data, 33);
return crypto.hash256(data);
return digest.hash256(data);
};
/**
@ -325,7 +327,7 @@ BIP150.prototype.findAuthorized = function findAuthorized(hash) {
// XXX Do we really need a constant
// time compare here? Do it just to
// be safe I guess.
if (crypto.ccmp(msg, hash))
if (ccmp(msg, hash))
return key;
}
};
@ -454,7 +456,7 @@ BIP150.address = function address(key) {
var bw = new StaticWriter(27);
bw.writeU8(0x0f);
bw.writeU16BE(0xff01);
bw.writeBytes(crypto.hash160(key));
bw.writeBytes(digest.hash160(key));
bw.writeChecksum();
return base58.encode(bw.render());
};

View File

@ -12,14 +12,17 @@
'use strict';
var assert = require('assert');
var EventEmitter = require('events').EventEmitter;
var util = require('../utils/util');
var co = require('../utils/co');
var crypto = require('../crypto/crypto');
var assert = require('assert');
var chachapoly = require('../crypto/chachapoly');
var packets = require('./packets');
var digest = require('../crypto/digest');
var ChaCha20 = require('../crypto/chacha20');
var Poly1305 = require('../crypto/poly1305');
var AEAD = require('../crypto/aead');
var hkdf = require('../crypto/hkdf');
var secp256k1 = require('../crypto/secp256k1');
var packets = require('./packets');
var StaticWriter = require('../utils/staticwriter');
var BufferReader = require('../utils/reader');
var encoding = require('../utils/encoding');
@ -74,8 +77,8 @@ function BIP151Stream(cipher) {
this.cipher = cipher;
}
this.chacha = new chachapoly.ChaCha20();
this.aead = new chachapoly.AEAD();
this.chacha = new ChaCha20();
this.aead = new AEAD();
this.tag = null;
this.seq = 0;
this.iv = Buffer.allocUnsafe(8);
@ -100,10 +103,10 @@ BIP151Stream.prototype.init = function init(publicKey) {
bw.writeBytes(this.secret);
bw.writeU8(this.cipher);
this.prk = crypto.hkdfExtract(bw.render(), HKDF_SALT, 'sha256');
this.k1 = crypto.hkdfExpand(this.prk, INFO_KEY1, 32, 'sha256');
this.k2 = crypto.hkdfExpand(this.prk, INFO_KEY2, 32, 'sha256');
this.sid = crypto.hkdfExpand(this.prk, INFO_SID, 32, 'sha256');
this.prk = hkdf.extract(bw.render(), HKDF_SALT, 'sha256');
this.k1 = hkdf.expand(this.prk, INFO_KEY1, 32, 'sha256');
this.k2 = hkdf.expand(this.prk, INFO_KEY2, 32, 'sha256');
this.sid = hkdf.expand(this.prk, INFO_SID, 32, 'sha256');
this.seq = 0;
@ -153,10 +156,10 @@ BIP151Stream.prototype.rekey = function rekey(k1, k2) {
this.sid.copy(seed, 0);
this.k1.copy(seed, 32);
this.k1 = crypto.hash256(seed);
this.k1 = digest.hash256(seed);
this.k2.copy(seed, 32);
this.k2 = crypto.hash256(seed);
this.k2 = digest.hash256(seed);
} else {
this.k1 = k1;
this.k2 = k2;
@ -279,7 +282,7 @@ BIP151Stream.prototype.finish = function finish() {
*/
BIP151Stream.prototype.verify = function verify(tag) {
return chachapoly.Poly1305.verify(this.tag, tag);
return Poly1305.verify(this.tag, tag);
};
/**

View File

@ -17,7 +17,7 @@ var BufferWriter = require('../utils/writer');
var StaticWriter = require('../utils/staticwriter');
var encoding = require('../utils/encoding');
var consensus = require('../protocol/consensus');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var siphash256 = require('../crypto/siphash').siphash256;
var AbstractBlock = require('../primitives/abstractblock');
var TX = require('../primitives/tx');
@ -412,7 +412,7 @@ CompactBlock.prototype.hasIndex = function hasIndex(index) {
CompactBlock.prototype.initKey = function initKey() {
var data = util.concat(this.abbr(), this.keyNonce);
var hash = crypto.sha256(data);
var hash = digest.sha256(data);
this.sipKey = hash.slice(0, 16);
};

View File

@ -9,7 +9,7 @@
var assert = require('assert');
var Network = require('../protocol/network');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
/**
* Protocol packet framer
@ -55,7 +55,7 @@ Framer.prototype.packet = function packet(cmd, payload, checksum) {
packet.writeUInt32LE(payload.length, 16, true);
if (!checksum)
checksum = crypto.hash256(payload);
checksum = digest.hash256(payload);
// Checksum
checksum.copy(packet, 20, 0, 4);

View File

@ -11,7 +11,7 @@ var assert = require('assert');
var EventEmitter = require('events').EventEmitter;
var Network = require('../protocol/network');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var common = require('./common');
var packets = require('./packets');
@ -98,7 +98,7 @@ Parser.prototype.parse = function parse(data) {
return;
}
checksum = crypto.hash256(data).readUInt32LE(0, true);
checksum = digest.hash256(data).readUInt32LE(0, true);
if (checksum !== this.header.checksum) {
this.waiting = 24;

View File

@ -1,7 +1,7 @@
'use strict';
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var BufferWriter = require('../utils/writer');
var assert = require('assert');
var EventEmitter = require('events').EventEmitter;
@ -129,7 +129,7 @@ ProxySocket.prototype.connect = function connect(port, host) {
nonce++;
assert(nonce <= 0xffffffff, 'Could not create socket.');
pow.writeUInt32LE(nonce, 0, true);
} while (crypto.hash256(pow).compare(this.target) > 0);
} while (digest.hash256(pow).compare(this.target) > 0);
util.log('Solved proof of work: %d', nonce);
}

View File

@ -9,7 +9,7 @@
var assert = require('assert');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var StaticWriter = require('../utils/staticwriter');
var InvItem = require('./invitem');
var encoding = require('../utils/encoding');
@ -160,7 +160,7 @@ AbstractBlock.prototype.hash = function hash(enc) {
var hex;
if (!hash) {
hash = crypto.hash256(this.abbr());
hash = digest.hash256(this.abbr());
if (!this.mutable)
this._hash = hash;
}

View File

@ -11,7 +11,7 @@ var assert = require('assert');
var Network = require('../protocol/network');
var encoding = require('../utils/encoding');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var base58 = require('../utils/base58');
@ -411,7 +411,7 @@ Address.fromBech32 = function fromBech32(data, network) {
Address.prototype.fromScript = function fromScript(script) {
if (script.isPubkey()) {
this.hash = crypto.hash160(script.get(0));
this.hash = digest.hash160(script.get(0));
this.type = Address.types.PUBKEYHASH;
this.version = -1;
return this;
@ -471,14 +471,14 @@ Address.prototype.fromWitness = function fromWitness(witness) {
// We're pretty much screwed here
// since we can't get the version.
if (witness.isPubkeyhashInput()) {
this.hash = crypto.hash160(witness.get(1));
this.hash = digest.hash160(witness.get(1));
this.type = Address.types.WITNESS;
this.version = 0;
return this;
}
if (witness.isScripthashInput()) {
this.hash = crypto.sha256(witness.get(witness.length - 1));
this.hash = digest.sha256(witness.get(witness.length - 1));
this.type = Address.types.WITNESS;
this.version = 0;
return this;
@ -493,14 +493,14 @@ Address.prototype.fromWitness = function fromWitness(witness) {
Address.prototype.fromInputScript = function fromInputScript(script) {
if (script.isPubkeyhashInput()) {
this.hash = crypto.hash160(script.get(1));
this.hash = digest.hash160(script.get(1));
this.type = Address.types.PUBKEYHASH;
this.version = -1;
return this;
}
if (script.isScripthashInput()) {
this.hash = crypto.hash160(script.get(script.length - 1));
this.hash = digest.hash160(script.get(script.length - 1));
this.type = Address.types.SCRIPTHASH;
this.version = -1;
return this;

View File

@ -10,7 +10,8 @@
var assert = require('assert');
var util = require('../utils/util');
var encoding = require('../utils/encoding');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var merkle = require('../crypto/merkle');
var consensus = require('../protocol/consensus');
var AbstractBlock = require('./abstractblock');
var VerifyResult = require('../protocol/errors').VerifyResult;
@ -293,7 +294,7 @@ Block.prototype.createMerkleRoot = function createMerkleRoot(enc) {
leaves.push(tx.hash());
}
root = crypto.createMerkleRoot(leaves);
root = merkle.createRoot(leaves);
if (root.malleated)
return null;
@ -333,14 +334,14 @@ Block.prototype.createCommitmentHash = function createCommitmentHash(enc) {
leaves.push(tx.witnessHash());
}
root = crypto.createMerkleRoot(leaves);
root = merkle.createRoot(leaves);
// Note: malleation check ignored here.
// assert(!root.malleated);
data = util.concat(root.hash, nonce);
hash = crypto.hash256(data);
hash = digest.hash256(data);
return enc === 'hex'
? hash.toString('hex')

View File

@ -9,7 +9,7 @@
var assert = require('assert');
var encoding = require('../utils/encoding');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var Network = require('../protocol/network');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
@ -418,7 +418,7 @@ KeyRing.prototype.getProgram = function getProgram() {
if (!this._program) {
if (!this.script) {
hash = crypto.hash160(this.publicKey);
hash = digest.hash160(this.publicKey);
program = Script.fromProgram(0, hash);
} else {
hash = this.script.sha256();
@ -564,7 +564,7 @@ KeyRing.prototype.getScriptAddress = function getScriptAddress(enc) {
KeyRing.prototype.getKeyHash = function getKeyHash(enc) {
if (!this._keyHash)
this._keyHash = crypto.hash160(this.publicKey);
this._keyHash = digest.hash160(this.publicKey);
return enc === 'hex'
? this._keyHash.toString('hex')

View File

@ -9,7 +9,7 @@
var assert = require('assert');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var AbstractBlock = require('./abstractblock');
var VerifyResult = require('../protocol/errors').VerifyResult;
var BufferReader = require('../utils/reader');
@ -243,7 +243,7 @@ MerkleBlock.prototype.extractTree = function extractTree() {
left.copy(buf, 0);
right.copy(buf, 32);
return crypto.hash256(buf);
return digest.hash256(buf);
}
if (totalTX === 0)
@ -602,7 +602,7 @@ MerkleBlock.fromMatches = function fromMatches(block, matches) {
left.copy(buf, 0);
right.copy(buf, 32);
return crypto.hash256(buf);
return digest.hash256(buf);
}
function traverse(height, pos, leaves, matches) {

View File

@ -10,7 +10,7 @@
var assert = require('assert');
var util = require('../utils/util');
var encoding = require('../utils/encoding');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var secp256k1 = require('../crypto/secp256k1');
var Amount = require('../btc/amount');
var Network = require('../protocol/network');
@ -188,7 +188,7 @@ TX.prototype.hash = function _hash(enc) {
var hex;
if (!hash) {
hash = crypto.hash256(this.toNormal());
hash = digest.hash256(this.toNormal());
if (!this.mutable)
this._hash = hash;
}
@ -222,7 +222,7 @@ TX.prototype.witnessHash = function witnessHash(enc) {
return this.hash(enc);
if (!hash) {
hash = crypto.hash256(this.toRaw());
hash = digest.hash256(this.toRaw());
if (!this.mutable)
this._whash = hash;
}
@ -563,7 +563,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
// Append the hash type.
bw.writeU32(type);
return crypto.hash256(bw.render());
return digest.hash256(bw.render());
};
/**
@ -644,7 +644,7 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, value, type
input.prevout.toWriter(bw);
}
prevouts = crypto.hash256(bw.render());
prevouts = digest.hash256(bw.render());
if (!this.mutable)
this._hashPrevouts = prevouts;
@ -664,7 +664,7 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, value, type
bw.writeU32(input.sequence);
}
sequences = crypto.hash256(bw.render());
sequences = digest.hash256(bw.render());
if (!this.mutable)
this._hashSequence = sequences;
@ -690,14 +690,14 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, value, type
output.toWriter(bw);
}
outputs = crypto.hash256(bw.render());
outputs = digest.hash256(bw.render());
if (!this.mutable)
this._hashOutputs = outputs;
}
} else if ((type & 0x1f) === Script.hashType.SINGLE && index < this.outputs.length) {
output = this.outputs[index];
outputs = crypto.hash256(output.toRaw());
outputs = digest.hash256(output.toRaw());
}
input = this.inputs[index];
@ -717,7 +717,7 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, value, type
bw.writeU32(this.locktime);
bw.writeU32(type);
return crypto.hash256(bw.render());
return digest.hash256(bw.render());
};
/**

View File

@ -12,7 +12,8 @@ var BN = require('../crypto/bn');
var consensus = require('../protocol/consensus');
var policy = require('../protocol/policy');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var merkle = require('../crypto/merkle');
var BufferWriter = require('../utils/writer');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
@ -1058,35 +1059,35 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
if (stack.length === 0)
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
stack.push(crypto.ripemd160(stack.pop()));
stack.push(digest.ripemd160(stack.pop()));
break;
}
case opcodes.OP_SHA1: {
if (stack.length === 0)
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
stack.push(crypto.sha1(stack.pop()));
stack.push(digest.sha1(stack.pop()));
break;
}
case opcodes.OP_SHA256: {
if (stack.length === 0)
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
stack.push(crypto.sha256(stack.pop()));
stack.push(digest.sha256(stack.pop()));
break;
}
case opcodes.OP_HASH160: {
if (stack.length === 0)
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
stack.push(crypto.hash160(stack.pop()));
stack.push(digest.hash160(stack.pop()));
break;
}
case opcodes.OP_HASH256: {
if (stack.length === 0)
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
stack.push(crypto.hash256(stack.pop()));
stack.push(digest.hash256(stack.pop()));
break;
}
case opcodes.OP_CODESEPARATOR: {
@ -1836,7 +1837,7 @@ Script.prototype.getAddress = function getAddress() {
*/
Script.prototype.hash160 = function hash160(enc) {
var hash = crypto.hash160(this.toRaw());
var hash = digest.hash160(this.toRaw());
if (enc === 'hex')
hash = hash.toString('hex');
return hash;
@ -1849,7 +1850,7 @@ Script.prototype.hash160 = function hash160(enc) {
*/
Script.prototype.sha256 = function sha256(enc) {
var hash = crypto.sha256(this.toRaw());
var hash = digest.sha256(this.toRaw());
if (enc === 'hex')
hash = hash.toString('hex');
return hash;
@ -2083,7 +2084,7 @@ Script.prototype.forWitness = function() {
return this;
if (this.isPubkey()) {
hash = crypto.hash160(this.get(0));
hash = digest.hash160(this.get(0));
return Script.fromProgram(0, hash);
}
@ -2923,7 +2924,7 @@ Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i, val
witnessScript = stack.pop();
if (!crypto.sha256(witnessScript).equals(program.data))
if (!digest.sha256(witnessScript).equals(program.data))
throw new ScriptError('WITNESS_PROGRAM_MISMATCH');
redeem = new Script(witnessScript);
@ -3073,15 +3074,15 @@ Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i, va
if ((scripts.written + script.length) > consensus.MAX_SCRIPT_SIZE)
throw new ScriptError('SCRIPT_SIZE');
}
scriptRoot.writeBytes(crypto.hash256(script));
scriptRoot.writeBytes(digest.hash256(script));
scripts.writeBytes(script);
}
scriptRoot = crypto.hash256(scriptRoot.render());
scriptRoot = crypto.verifyMerkleBranch(scriptRoot, path, pos);
scriptRoot = digest.hash256(scriptRoot.render());
scriptRoot = merkle.verifyBranch(scriptRoot, path, pos);
mastRoot.writeBytes(scriptRoot);
mastRoot = crypto.hash256(mastRoot.render());
mastRoot = digest.hash256(mastRoot.render());
if (!mastRoot.equals(program.data))
throw new ScriptError('WITNESS_PROGRAM_MISMATCH');

View File

@ -8,7 +8,7 @@
var assert = require('assert');
var Int64 = require('./int64');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var siphash24 = require('../crypto/siphash');
var SCRATCH = Buffer.allocUnsafe(64);
var DUMMY = Buffer.allocUnsafe(0);
@ -28,7 +28,7 @@ function GCSFilter() {
}
GCSFilter.prototype.hash = function _hash(enc) {
var hash = crypto.hash256(this.data);
var hash = digest.hash256(this.data);
return enc === 'hex' ? hash.toString('hex') : hash;
};
@ -37,7 +37,7 @@ GCSFilter.prototype.header = function header(prev) {
var hash = this.hash();
hash.copy(data, 0);
prev.copy(data, 32);
return crypto.hash256(data);
return digest.hash256(data);
};
GCSFilter.prototype.match = function match(key, data) {

View File

@ -9,7 +9,7 @@
var assert = require('assert');
var encoding = require('./encoding');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
/**
* An object that allows reading of buffers in a sane manner.
@ -673,7 +673,7 @@ BufferReader.prototype.readNullString = function readNullString(enc) {
BufferReader.prototype.createChecksum = function createChecksum() {
var start = this.stack[this.stack.length - 1] || 0;
var data = this.data.slice(start, this.offset);
return crypto.hash256(data).readUInt32LE(0, true);
return digest.hash256(data).readUInt32LE(0, true);
};
/**

View File

@ -8,7 +8,7 @@
var assert = require('assert');
var encoding = require('./encoding');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
/**
* Statically allocated buffer writer.
@ -417,7 +417,7 @@ StaticWriter.prototype.writeNullString = function writeNullString(value, enc) {
StaticWriter.prototype.writeChecksum = function writeChecksum() {
var data = this.data.slice(0, this.written);
var hash = crypto.hash256(data);
var hash = digest.hash256(data);
hash.copy(this.data, this.written, 0, 4);
this.written += 4;
};

View File

@ -9,7 +9,7 @@
var assert = require('assert');
var encoding = require('./encoding');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
/*
* Constants
@ -101,7 +101,7 @@ BufferWriter.prototype.render = function render(keep) {
case BYTES: off += op.value.copy(data, off); break;
case STR: off += data.write(op.value, off, op.enc); break;
case CHECKSUM:
off += crypto.hash256(data.slice(0, off)).copy(data, off, 0, 4);
off += digest.hash256(data.slice(0, off)).copy(data, off, 0, 4);
break;
case FILL:
data.fill(op.value, off, off + op.size);

View File

@ -14,7 +14,9 @@ var base58 = require('../utils/base58');
var MTX = require('../primitives/mtx');
var Outpoint = require('../primitives/outpoint');
var Script = require('../script/script');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var random = require('../crypto/random');
var ccmp = require('../crypto/ccmp');
var Network = require('../protocol/network');
var Validator = require('../utils/validator');
var common = require('./common');
@ -887,7 +889,7 @@ HTTPServer.prototype.handleSocket = function handleSocket(socket) {
if (!self.options.noAuth) {
hash = hash256(key);
if (!crypto.ccmp(hash, self.options.apiHash))
if (!ccmp(hash, self.options.apiHash))
throw new Error('Bad key.');
}
@ -973,7 +975,7 @@ function HTTPOptions(options) {
this.network = Network.primary;
this.logger = null;
this.walletdb = null;
this.apiKey = base58.encode(crypto.randomBytes(20));
this.apiKey = base58.encode(random.randomBytes(20));
this.apiHash = hash256(this.apiKey);
this.serviceHash = this.apiHash;
this.noAuth = false;
@ -1094,7 +1096,7 @@ function hash256(data) {
if (data.length > 200)
return Buffer.alloc(0);
return crypto.hash256(Buffer.from(data, 'utf8'));
return digest.hash256(Buffer.from(data, 'utf8'));
}
function enforce(value, msg) {

View File

@ -9,7 +9,11 @@
var assert = require('assert');
var util = require('../utils/util');
var Lock = require('../utils/lock');
var crypto = require('../crypto/crypto');
var random = require('../crypto/random');
var cleanse = require('../crypto/cleanse');
var aes = require('../crypto/aes');
var pbkdf2 = require('../crypto/pbkdf2');
var scrypt = require('../crypto/scrypt');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var encoding = require('../utils/encoding');
@ -199,7 +203,7 @@ MasterKey.prototype._unlock = async function _unlock(passphrase, timeout) {
assert(this.encrypted);
key = await this.derive(passphrase);
data = crypto.decipher(this.ciphertext, key, this.iv);
data = aes.decipher(this.ciphertext, key, this.iv);
this.fromKeyRaw(data);
@ -259,9 +263,9 @@ MasterKey.prototype.derive = async function derive(passwd) {
switch (this.alg) {
case MasterKey.alg.PBKDF2:
return await crypto.pbkdf2Async(passwd, salt, N, 32, 'sha256');
return await pbkdf2.deriveAsync(passwd, salt, N, 32, 'sha256');
case MasterKey.alg.SCRYPT:
return await crypto.scryptAsync(passwd, salt, N, r, p, 32);
return await scrypt.deriveAsync(passwd, salt, N, r, p, 32);
default:
throw new Error('Unknown algorithm: ' + this.alg);
}
@ -281,7 +285,7 @@ MasterKey.prototype.encipher = function encipher(data, iv) {
if (typeof iv === 'string')
iv = Buffer.from(iv, 'hex');
return crypto.encipher(data, this.aesKey, iv.slice(0, 16));
return aes.encipher(data, this.aesKey, iv.slice(0, 16));
};
/**
@ -298,7 +302,7 @@ MasterKey.prototype.decipher = function decipher(data, iv) {
if (typeof iv === 'string')
iv = Buffer.from(iv, 'hex');
return crypto.decipher(data, this.aesKey, iv.slice(0, 16));
return aes.decipher(data, this.aesKey, iv.slice(0, 16));
};
/**
@ -338,7 +342,7 @@ MasterKey.prototype._lock = function lock() {
}
if (this.aesKey) {
crypto.cleanse(this.aesKey);
cleanse(this.aesKey);
this.aesKey = null;
}
};
@ -386,7 +390,7 @@ MasterKey.prototype._decrypt = async function decrypt(passphrase, clean) {
this._lock();
key = await this.derive(passphrase);
data = crypto.decipher(this.ciphertext, key, this.iv);
data = aes.decipher(this.ciphertext, key, this.iv);
this.fromKeyRaw(data);
this.encrypted = false;
@ -394,7 +398,7 @@ MasterKey.prototype._decrypt = async function decrypt(passphrase, clean) {
this.ciphertext = null;
if (!clean) {
crypto.cleanse(key);
cleanse(key);
return;
}
@ -433,12 +437,12 @@ MasterKey.prototype._encrypt = async function encrypt(passphrase, clean) {
throw new Error('No passphrase provided.');
data = this.toKeyRaw();
iv = crypto.randomBytes(16);
iv = random.randomBytes(16);
this.stop();
key = await this.derive(passphrase);
data = crypto.encipher(data, key, iv);
data = aes.encipher(data, key, iv);
this.key = null;
this.mnemonic = null;
@ -447,7 +451,7 @@ MasterKey.prototype._encrypt = async function encrypt(passphrase, clean) {
this.ciphertext = data;
if (!clean) {
crypto.cleanse(key);
cleanse(key);
return;
}

View File

@ -9,7 +9,7 @@
var assert = require('assert');
var fs = require('../utils/fs');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var Amount = require('../btc/amount');
var Script = require('../script/script');
var Address = require('../primitives/address');
@ -1484,7 +1484,7 @@ RPC.prototype.signMessage = async function signMessage(args, help) {
throw new RPCError(errs.WALLET_UNLOCK_NEEDED, 'Wallet is locked.');
msg = Buffer.from(MAGIC_STRING + msg, 'utf8');
msg = crypto.hash256(msg);
msg = digest.hash256(msg);
sig = ring.sign(msg);

View File

@ -13,7 +13,8 @@ var Network = require('../protocol/network');
var util = require('../utils/util');
var encoding = require('../utils/encoding');
var Lock = require('../utils/lock');
var crypto = require('../crypto/crypto');
var digest = require('../crypto/digest');
var cleanse = require('../crypto/cleanse');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var base58 = require('../utils/base58');
@ -408,12 +409,12 @@ Wallet.prototype._encrypt = async function encrypt(passphrase) {
try {
await this.db.encryptKeys(this, key);
} catch (e) {
crypto.cleanse(key);
cleanse(key);
this.drop();
throw e;
}
crypto.cleanse(key);
cleanse(key);
this.save();
@ -450,12 +451,12 @@ Wallet.prototype._decrypt = async function decrypt(passphrase) {
try {
await this.db.decryptKeys(this, key);
} catch (e) {
crypto.cleanse(key);
cleanse(key);
this.drop();
throw e;
}
crypto.cleanse(key);
cleanse(key);
this.save();
@ -621,7 +622,7 @@ Wallet.prototype.getID = function getID() {
bw.writeBytes(key.publicKey);
bw.writeU32(this.network.magic);
hash = crypto.hash160(bw.render());
hash = digest.hash160(bw.render());
bw = new StaticWriter(27);
bw.writeU8(0x03);
@ -653,7 +654,7 @@ Wallet.prototype.getToken = function getToken(nonce) {
bw.writeBytes(key.privateKey);
bw.writeU32(nonce);
return crypto.hash256(bw.render());
return digest.hash256(bw.render());
};
/**

View File

@ -13,7 +13,8 @@ var util = require('../utils/util');
var Lock = require('../utils/lock');
var LRU = require('../utils/lru');
var encoding = require('../utils/encoding');
var crypto = require('../crypto/crypto');
var ccmp = require('../crypto/ccmp');
var aes = require('../crypto/aes');
var Network = require('../protocol/network');
var Path = require('./path');
var common = require('./common');
@ -1011,7 +1012,7 @@ WalletDB.prototype.auth = async function auth(wid, token) {
}
// Compare in constant time:
if (!crypto.ccmp(token, wallet.token))
if (!ccmp(token, wallet.token))
throw new Error('WDB: Authentication error.');
return wallet;
@ -1422,7 +1423,7 @@ WalletDB.prototype.encryptKeys = async function encryptKeys(wallet, key) {
iv = iv.slice(0, 16);
path = path.clone();
path.data = crypto.encipher(path.data, key, iv);
path.data = aes.encipher(path.data, key, iv);
path.encrypted = true;
wallet.pathCache.push(path.hash, path);
@ -1456,7 +1457,7 @@ WalletDB.prototype.decryptKeys = async function decryptKeys(wallet, key) {
iv = iv.slice(0, 16);
path = path.clone();
path.data = crypto.decipher(path.data, key, iv);
path.data = aes.decipher(path.data, key, iv);
path.encrypted = false;
wallet.pathCache.push(path.hash, path);

View File

@ -175,6 +175,6 @@ jobs.mine = function _mine(data, target, min, max) {
*/
jobs.scrypt = function _scrypt(passwd, salt, N, r, p, len) {
var key = scrypt(passwd, salt, N, r, p, len);
var key = scrypt.derive(passwd, salt, N, r, p, len);
return new packets.ScryptResultPacket(key);
};

View File

@ -3,7 +3,7 @@
var assert = require('assert');
var encoding = require('../lib/utils/encoding');
var BufferReader = require('../lib/utils/reader');
var crypto = require('../lib/crypto/crypto');
var digest = require('../lib/crypto/digest');
var util = require('../lib/utils/util');
var LDB = require('../lib/db/ldb');
var BN = require('../lib/crypto/bn');
@ -42,7 +42,7 @@ async function checkVersion() {
function entryFromRaw(data) {
var p = new BufferReader(data, true);
var hash = crypto.hash256(p.readBytes(80));
var hash = digest.hash256(p.readBytes(80));
var entry = {};
p.seek(-80);

View File

@ -78,9 +78,12 @@
"socket.io": "./browser/empty.js",
"./lib/bcoin": "./lib/bcoin-browser.js",
"./lib/blockchain/layout.js": "./lib/blockchain/layout-browser.js",
"./lib/crypto/backend.js": "./lib/crypto/backend-browser.js",
"./lib/crypto/secp256k1.js": "./lib/crypto/secp256k1-elliptic.js",
"./lib/crypto/aes.js": "./lib/crypto/aes-browser.js",
"./lib/crypto/digest.js": "./lib/crypto/digest-browser.js",
"./lib/crypto/pbkdf2.js": "./lib/crypto/pbkdf2-browser.js",
"./lib/crypto/random.js": "./lib/crypto/random-browser.js",
"./lib/crypto/rsa.js": "./lib/crypto/rsa-browser.js",
"./lib/crypto/secp256k1.js": "./lib/crypto/secp256k1-elliptic.js",
"./lib/db/backends.js": "./lib/db/backends-browser.js",
"./lib/hd/wordlist": "./lib/hd/wordlist-browser.js",
"./lib/http/base": "./browser/empty.js",

View File

@ -1,21 +1,22 @@
var assert = require('assert');
var bcoin = require('../');
var util = bcoin.util;
var Script = bcoin.script;
var Stack = bcoin.stack;
var Witness = bcoin.witness;
var Input = bcoin.input;
var Output = bcoin.output;
var Outpoint = bcoin.outpoint;
var TX = bcoin.tx;
var crypto = bcoin.crypto;
var consensus = bcoin.consensus;
var util = require('../lib/utils/util');
var Script = require('../lib/script/script');
var Stack = require('../lib/script/stack');
var Witness = require('../lib/script/witness');
var Input = require('../lib/primitives/input');
var Output = require('../lib/primitives/output');
var Outpoint = require('../lib/primitives/outpoint');
var TX = require('../lib/primitives/tx');
var digest = require('../lib/crypto/digest');
var random = require('../lib/crypto/random');
var consensus = require('../lib/protocol/consensus');
var MANDATORY = Script.flags.MANDATORY_VERIFY_FLAGS | Script.flags.VERIFY_WITNESS;
var STANDARD = Script.flags.STANDARD_VERIFY_FLAGS;
function randomOutpoint() {
var hash = crypto.randomBytes(32).toString('hex');
var hash = random.randomBytes(32).toString('hex');
return new Outpoint(hash, util.random(0, 0xffffffff));
}
@ -61,7 +62,7 @@ function randomWitness(redeem) {
for (i = 0; i < size; i++) {
len = util.random(0, 100);
witness.push(crypto.randomBytes(len));
witness.push(random.randomBytes(len));
}
if (redeem)
@ -79,7 +80,7 @@ function randomInputScript(redeem) {
for (i = 0; i < size; i++) {
len = util.random(0, 100);
script.push(crypto.randomBytes(len));
script.push(random.randomBytes(len));
}
if (redeem)
@ -92,7 +93,7 @@ function randomInputScript(redeem) {
function randomOutputScript() {
var size = util.random(1, 10000);
return Script.fromRaw(crypto.randomBytes(size));
return Script.fromRaw(random.randomBytes(size));
}
function isPushOnly(script) {
@ -121,11 +122,11 @@ function isPushOnly(script) {
function randomPubkey() {
var len = util.random(0, 2) === 0 ? 33 : 65;
return Script.fromPubkey(crypto.randomBytes(len));
return Script.fromPubkey(random.randomBytes(len));
}
function randomPubkeyhash() {
return Script.fromPubkeyhash(crypto.randomBytes(20));
return Script.fromPubkeyhash(random.randomBytes(20));
}
function randomMultisig() {
@ -136,28 +137,28 @@ function randomMultisig() {
for (i = 0; i < n; i++) {
len = util.random(0, 2) === 0 ? 33 : 65;
keys.push(crypto.randomBytes(len));
keys.push(random.randomBytes(len));
}
return Script.fromMultisig(m, n, keys);
}
function randomScripthash() {
return Script.fromScripthash(crypto.randomBytes(20));
return Script.fromScripthash(random.randomBytes(20));
}
function randomWitnessPubkeyhash() {
return Script.fromProgram(0, crypto.randomBytes(20));
return Script.fromProgram(0, random.randomBytes(20));
}
function randomWitnessScripthash() {
return Script.fromProgram(0, crypto.randomBytes(32));
return Script.fromProgram(0, random.randomBytes(32));
}
function randomProgram() {
var version = util.random(0, 16);
var size = util.random(2, 41);
return Script.fromProgram(version, crypto.randomBytes(size));
return Script.fromProgram(version, random.randomBytes(size));
}
function randomRedeem() {

View File

@ -1,13 +1,14 @@
'use strict';
var assert = require('assert');
var crypto = require('../lib/crypto/crypto');
var digest = require('../lib/crypto/digest');
var aes = require('../lib/crypto/aes');
var pbkdf2 = require('../lib/crypto/pbkdf2');
var nativeCrypto = require('crypto');
describe('AES', function() {
function pbkdf2key(passphrase, iterations, dkLen, ivLen, alg) {
var key = crypto.pbkdf2(passphrase, '', iterations, dkLen + ivLen, 'sha512');
var key = pbkdf2.derive(passphrase, '', iterations, dkLen + ivLen, 'sha512');
return {
key: key.slice(0, dkLen),
iv: key.slice(dkLen, dkLen + ivLen)
@ -69,7 +70,7 @@ describe('AES', function() {
passphrase = Buffer.from(passphrase, 'utf8');
key = pbkdf2key(passphrase, 2048, 32, 16);
return crypto.encipher(data, key.key, key.iv);
return aes.encipher(data, key.key, key.iv);
}
function bdecrypt(data, passphrase) {
@ -85,7 +86,7 @@ describe('AES', function() {
passphrase = Buffer.from(passphrase, 'utf8');
key = pbkdf2key(passphrase, 2048, 32, 16);
return crypto.decipher(data, key.key, key.iv);
return aes.decipher(data, key.key, key.iv);
}
function encrypt(data, passphrase) {
@ -102,7 +103,7 @@ describe('AES', function() {
key = pbkdf2key(passphrase, 2048, 32, 16);
return aes.cbc.encrypt(data, key.key, key.iv);
return aes.encipher(data, key.key, key.iv);
}
function decrypt(data, passphrase) {
@ -119,19 +120,19 @@ describe('AES', function() {
key = pbkdf2key(passphrase, 2048, 32, 16);
return aes.cbc.decrypt(data, key.key, key.iv);
return aes.decipher(data, key.key, key.iv);
}
it('should encrypt and decrypt a hash with 2 blocks', function() {
var hash = crypto.sha256(Buffer.alloc(0));
var hash = digest.sha256(Buffer.alloc(0));
var enchash = encrypt(hash, 'foo');
var dechash = decrypt(enchash, 'foo');
var hash2 = crypto.sha256(Buffer.alloc(0));
var hash2 = digest.sha256(Buffer.alloc(0));
var enchash2 = nencrypt(hash2, 'foo');
var dechash2 = ndecrypt(enchash2, 'foo');
var hash3 = crypto.sha256(Buffer.alloc(0));
var hash3 = digest.sha256(Buffer.alloc(0));
var enchash3 = bencrypt(hash3, 'foo');
var dechash3 = bdecrypt(enchash3, 'foo');
@ -142,11 +143,11 @@ describe('AES', function() {
});
it('should encrypt and decrypt a hash with uneven blocks', function() {
var hash = Buffer.concat([crypto.sha256(Buffer.alloc(0)), Buffer.from([1,2,3])]);
var hash = Buffer.concat([digest.sha256(Buffer.alloc(0)), Buffer.from([1,2,3])]);
var enchash = encrypt(hash, 'foo');
var dechash = decrypt(enchash, 'foo');
var hash2 = Buffer.concat([crypto.sha256(Buffer.alloc(0)), Buffer.from([1,2,3])]);
var hash2 = Buffer.concat([digest.sha256(Buffer.alloc(0)), Buffer.from([1,2,3])]);
var enchash2 = nencrypt(hash2, 'foo');
var dechash2 = ndecrypt(enchash2, 'foo');

View File

@ -1,10 +1,9 @@
'use strict';
var assert = require('assert');
var chachapoly = require('../lib/crypto/chachapoly');
var ChaCha20 = chachapoly.ChaCha20;
var Poly1305 = chachapoly.Poly1305;
var AEAD = chachapoly.AEAD;
var ChaCha20 = require('../lib/crypto/chacha20');
var Poly1305 = require('../lib/crypto/poly1305');
var AEAD = require('../lib/crypto/aead');
describe('ChaCha20 / Poly1305 / AEAD', function() {
function testChaCha(options) {

View File

@ -3,7 +3,7 @@
var assert = require('assert');
var fs = require('../lib/utils/fs');
var GCSFilter = require('../lib/utils/gcs');
var crypto = require('../lib/crypto/crypto');
var random = require('../lib/crypto/random');
var Block = require('../lib/primitives/block');
var Outpoint = require('../lib/primitives/outpoint');
var Address = require('../lib/primitives/address');
@ -12,7 +12,7 @@ var raw = fs.readFileSync(__dirname + '/data/block928927.raw');
var block = Block.fromRaw(raw);
describe('GCS', function() {
var key = crypto.randomBytes(16);
var key = random.randomBytes(16);
var P = 20;
var filter1, filter2, filter3, filter4, filter5;
var contents1, contents2;

View File

@ -3,7 +3,7 @@
var assert = require('assert');
var HD = require('../lib/hd');
var base58 = require('../lib/utils/base58');
var crypto = require('../lib/crypto/crypto');
var pbkdf2 = require('../lib/crypto/pbkdf2');
var vectors = require('./data/hd.json');
var vector1 = vectors.vector1;
var vector2 = vectors.vector2;
@ -21,7 +21,7 @@ describe('HD', function() {
var master, child1, child2, child3, child4, child5, child6;
it('should create a pbkdf2 seed', function() {
var seed = crypto.pbkdf2(vectors.phrase, 'mnemonicfoo', 2048, 64, 'sha512');
var seed = pbkdf2.derive(vectors.phrase, 'mnemonicfoo', 2048, 64, 'sha512');
assert.equal(seed.toString('hex'), vectors.seed);
});

View File

@ -2,7 +2,7 @@
var assert = require('assert');
var encoding = require('../lib/utils/encoding');
var crypto = require('../lib/crypto/crypto');
var random = require('../lib/crypto/random');
var MempoolEntry = require('../lib/mempool/mempoolentry');
var Mempool = require('../lib/mempool/mempool');
var Chain = require('../lib/blockchain/chain');
@ -161,7 +161,7 @@ describe('Mempool', function() {
tx.addOutput(w.getAddress(), 10000);
prev = Script.fromPubkey(kp.publicKey);
prevHash = crypto.randomBytes(32).toString('hex');
prevHash = random.randomBytes(32).toString('hex');
tx.addCoin(dummy(prev, prevHash));
tx.setLocktime(200);
@ -187,7 +187,7 @@ describe('Mempool', function() {
tx.addOutput(w.getAddress(), 10000);
prev = Script.fromPubkey(kp.publicKey);
prevHash = crypto.randomBytes(32).toString('hex');
prevHash = random.randomBytes(32).toString('hex');
tx.addCoin(dummy(prev, prevHash));
tx.setLocktime(200);
@ -220,7 +220,7 @@ describe('Mempool', function() {
tx.addOutput(w.getAddress(), 10000);
prev = Script.fromProgram(0, kp.getKeyHash());
prevHash = crypto.randomBytes(32).toString('hex');
prevHash = random.randomBytes(32).toString('hex');
tx.addCoin(dummy(prev, prevHash));
@ -252,7 +252,7 @@ describe('Mempool', function() {
tx.addOutput(w.getAddress(), 10000);
prev = Script.fromPubkey(kp.publicKey);
prevHash = crypto.randomBytes(32).toString('hex');
prevHash = random.randomBytes(32).toString('hex');
tx.addCoin(dummy(prev, prevHash));
@ -283,7 +283,7 @@ describe('Mempool', function() {
tx.addOutput(w.getAddress(), 10000);
prev = Script.fromProgram(0, kp.getKeyHash());
prevHash = crypto.randomBytes(32).toString('hex');
prevHash = random.randomBytes(32).toString('hex');
tx.addCoin(dummy(prev, prevHash));
@ -310,7 +310,7 @@ describe('Mempool', function() {
tx.addOutput(w.getAddress(), 10000);
prev = Script.fromPubkey(kp.publicKey);
prevHash = crypto.randomBytes(32).toString('hex');
prevHash = random.randomBytes(32).toString('hex');
tx.addCoin(dummy(prev, prevHash));

View File

@ -1,13 +1,13 @@
'use strict';
var assert = require('assert');
var scrypt = require('../lib/crypto/crypto').scrypt;
var scrypt = require('../lib/crypto/scrypt');
describe('Scrypt', function() {
it('should perform scrypt with N=16', function() {
var pass = Buffer.from('');
var salt = Buffer.from('');
var result = scrypt(pass, salt, 16, 1, 1, 64);
var result = scrypt.derive(pass, salt, 16, 1, 1, 64);
assert.equal(result.toString('hex'), ''
+ '77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3f'
+ 'ede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628'
@ -17,7 +17,7 @@ describe('Scrypt', function() {
it('should perform scrypt with N=1024', function() {
var pass = Buffer.from('password');
var salt = Buffer.from('NaCl');
var result = scrypt(pass, salt, 1024, 8, 16, 64);
var result = scrypt.derive(pass, salt, 1024, 8, 16, 64);
assert.equal(result.toString('hex'), ''
+ 'fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e773'
+ '76634b3731622eaf30d92e22a3886ff109279d9830dac727afb9'
@ -27,7 +27,7 @@ describe('Scrypt', function() {
it('should perform scrypt with N=16384', function() {
var pass = Buffer.from('pleaseletmein');
var salt = Buffer.from('SodiumChloride');
var result = scrypt(pass, salt, 16384, 8, 1, 64);
var result = scrypt.derive(pass, salt, 16384, 8, 1, 64);
assert.equal(result.toString('hex'), ''
+ '7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b54'
+ '3f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d'
@ -38,7 +38,7 @@ describe('Scrypt', function() {
// it('should perform scrypt with N=1048576', function() {
// var pass = Buffer.from('pleaseletmein');
// var salt = Buffer.from('SodiumChloride');
// var result = scrypt(pass, salt, 1048576, 8, 1, 64);
// var result = scrypt.derive(pass, salt, 1048576, 8, 1, 64);
// assert.equal(result.toString('hex'), ''
// + '2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5'
// + 'ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049'

View File

@ -3,7 +3,7 @@
var assert = require('assert');
var util = require('../lib/utils/util');
var encoding = require('../lib/utils/encoding');
var crypto = require('../lib/crypto/crypto');
var random = require('../lib/crypto/random');
var consensus = require('../lib/protocol/consensus');
var TX = require('../lib/primitives/tx');
var Coin = require('../lib/primitives/coin');
@ -355,7 +355,7 @@ describe('TX', function() {
});
function createInput(value, view) {
var hash = crypto.randomBytes(32).toString('hex');
var hash = random.randomBytes(32).toString('hex');
var output = new Output();
output.value = value;
view.addOutput(hash, 0, output);

View File

@ -5,7 +5,8 @@ var BN = require('../lib/crypto/bn');
var secp256k1 = require('../lib/crypto/secp256k1');
var base58 = require('../lib/utils/base58');
var encoding = require('../lib/utils/encoding');
var crypto = require('../lib/crypto/crypto');
var digest = require('../lib/crypto/digest');
var hkdf = require('../lib/crypto/hkdf');
var schnorr = require('../lib/crypto/schnorr');
var Amount = require('../lib/btc/amount');
var consensus = require('../lib/protocol/consensus');
@ -271,8 +272,8 @@ describe('Utils', function() {
salt = Buffer.from(salt, 'hex');
info = Buffer.from(info, 'hex');
prk = crypto.hkdfExtract(ikm, salt, alg);
okm = crypto.hkdfExpand(prk, info, len, alg);
prk = hkdf.extract(ikm, salt, alg);
okm = hkdf.expand(prk, info, len, alg);
assert.equal(prk.toString('hex'), prkE);
assert.equal(okm.toString('hex'), okmE);
@ -313,8 +314,8 @@ describe('Utils', function() {
salt = Buffer.from(salt, 'hex');
info = Buffer.from(info, 'hex');
prk = crypto.hkdfExtract(ikm, salt, alg);
okm = crypto.hkdfExpand(prk, info, len, alg);
prk = hkdf.extract(ikm, salt, alg);
okm = hkdf.expand(prk, info, len, alg);
assert.equal(prk.toString('hex'), prkE);
assert.equal(okm.toString('hex'), okmE);
@ -323,7 +324,7 @@ describe('Utils', function() {
it('should do proper schnorr', function() {
var key = secp256k1.generatePrivateKey();
var pub = secp256k1.publicKeyCreate(key, true);
var msg = crypto.hash256(Buffer.from('foo', 'ascii'));
var msg = digest.hash256(Buffer.from('foo', 'ascii'));
var sig = schnorr.sign(msg, key);
assert(schnorr.verify(msg, sig, pub));
assert.deepEqual(schnorr.recover(sig, msg), pub);

View File

@ -4,7 +4,8 @@ var assert = require('assert');
var consensus = require('../lib/protocol/consensus');
var util = require('../lib/utils/util');
var encoding = require('../lib/utils/encoding');
var crypto = require('../lib/crypto/crypto');
var digest = require('../lib/crypto/digest');
var random = require('../lib/crypto/random');
var WalletDB = require('../lib/wallet/walletdb');
var Address = require('../lib/primitives/address');
var MTX = require('../lib/primitives/mtx');
@ -30,8 +31,8 @@ function nextBlock(height) {
if (height == null)
height = globalHeight++;
hash = crypto.hash256(encoding.U32(height)).toString('hex');
prev = crypto.hash256(encoding.U32(height - 1)).toString('hex');
hash = digest.hash256(encoding.U32(height)).toString('hex');
prev = digest.hash256(encoding.U32(height - 1)).toString('hex');
return {
hash: hash,
@ -46,7 +47,7 @@ function nextBlock(height) {
function dummy(hash) {
if (!hash)
hash = crypto.randomBytes(32).toString('hex');
hash = random.randomBytes(32).toString('hex');
return Input.fromOutpoint(new Outpoint(hash, 0));
}