bcoin: use bcrypto. remove crypto module.
This commit is contained in:
parent
c84afad1f6
commit
636d66a5c7
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const Address = require('../lib/primitives/address');
|
||||
const random = require('../lib/crypto/random');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const bench = require('./bench');
|
||||
const addrs = [];
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const ChaCha20 = require('../lib/crypto/chacha20');
|
||||
const Poly1305 = require('../lib/crypto/poly1305');
|
||||
const digest = require('../lib/crypto/digest');
|
||||
const ChaCha20 = require('bcrypto/lib/chacha20');
|
||||
const Poly1305 = require('bcrypto/lib/poly1305');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const bench = require('./bench');
|
||||
|
||||
console.log('note: rate measured in kb/s');
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const merkle = require('../lib/crypto/merkle');
|
||||
const random = require('../lib/crypto/random');
|
||||
const merkle = require('bcrypto/lib/merkle');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const bench = require('./bench');
|
||||
|
||||
const leaves = [];
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const random = require('../lib/crypto/random');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const Script = require('../lib/script/script');
|
||||
const bench = require('./bench');
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ const TX = require('../lib/primitives/tx');
|
||||
const Script = require('../lib/script/script');
|
||||
const MTX = require('../lib/primitives/mtx');
|
||||
const encoding = require('../lib/utils/encoding');
|
||||
const random = require('../lib/crypto/random');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const common = require('../test/util/common');
|
||||
const bench = require('./bench');
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const bench = require('./bench');
|
||||
const random = require('../lib/crypto/random');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const WalletDB = require('../lib/wallet/walletdb');
|
||||
const MTX = require('../lib/primitives/mtx');
|
||||
const Outpoint = require('../lib/primitives/outpoint');
|
||||
|
||||
@ -5,7 +5,7 @@ const net = require('net');
|
||||
const EventEmitter = require('events');
|
||||
const bsock = require('bsock');
|
||||
const util = require('../lib/utils/util');
|
||||
const digest = require('../lib/crypto/digest');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const IP = require('../lib/utils/ip');
|
||||
const BufferWriter = require('../lib/utils/writer');
|
||||
|
||||
|
||||
@ -165,10 +165,7 @@ bcoin.coins = require('./coins');
|
||||
bcoin.coinview = require('./coins/coinview');
|
||||
|
||||
// Crypto
|
||||
bcoin.crypto = require('./crypto');
|
||||
bcoin.bn = require('./crypto/bn');
|
||||
bcoin.secp256k1 = require('./crypto/secp256k1');
|
||||
bcoin.schnorr = require('./crypto/schnorr');
|
||||
bcoin.crypto = require('bcrypto');
|
||||
|
||||
// DB
|
||||
bcoin.db = require('./db');
|
||||
|
||||
@ -202,10 +202,7 @@ bcoin.define('coins', './coins');
|
||||
bcoin.define('coinview', './coins/coinview');
|
||||
|
||||
// Crypto
|
||||
bcoin.define('crypto', './crypto');
|
||||
bcoin.define('bn', './crypto/bn');
|
||||
bcoin.define('secp256k1', './crypto/secp256k1');
|
||||
bcoin.define('schnorr', './crypto/schnorr');
|
||||
bcoin.define('crypto', 'bcrypto');
|
||||
|
||||
// DB
|
||||
bcoin.define('db', './db');
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
const assert = require('assert');
|
||||
const util = require('../utils/util');
|
||||
const digest = require('../crypto/digest');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const x509 = require('./x509');
|
||||
const PEM = require('../utils/pem');
|
||||
const ProtoReader = require('../utils/protoreader');
|
||||
|
||||
@ -10,8 +10,9 @@
|
||||
* @module bip70/pk
|
||||
*/
|
||||
|
||||
const rsa = require('../crypto/rsa');
|
||||
const ecdsa = require('../crypto/ecdsa');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const rsa = require('bcrypto/lib/rsa');
|
||||
const ecdsa = require('bcrypto/lib/ecdsa');
|
||||
|
||||
/**
|
||||
* Verify signature with public key.
|
||||
@ -23,6 +24,7 @@ const ecdsa = require('../crypto/ecdsa');
|
||||
*/
|
||||
|
||||
exports.verify = function verify(hash, msg, sig, key) {
|
||||
hash = digest.get(hash);
|
||||
switch (key.alg) {
|
||||
case 'rsa':
|
||||
return rsa.verify(hash, msg, sig, key.data);
|
||||
@ -42,6 +44,7 @@ exports.verify = function verify(hash, msg, sig, key) {
|
||||
*/
|
||||
|
||||
exports.sign = function sign(hash, msg, key) {
|
||||
hash = digest.get(hash);
|
||||
switch (key.alg) {
|
||||
case 'rsa':
|
||||
return rsa.sign(hash, msg, key.data);
|
||||
|
||||
@ -10,7 +10,7 @@ const assert = require('assert');
|
||||
const ASN1 = require('../utils/asn1');
|
||||
const PEM = require('../utils/pem');
|
||||
const util = require('../utils/util');
|
||||
const digest = require('../crypto/digest');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const pk = require('./pk');
|
||||
const certs = require('./certs');
|
||||
|
||||
|
||||
@ -8,10 +8,10 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const BN = require('../crypto/bn');
|
||||
const BN = require('bcrypto/lib/bn');
|
||||
const consensus = require('../protocol/consensus');
|
||||
const util = require('../utils/util');
|
||||
const digest = require('../crypto/digest');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const encoding = require('../utils/encoding');
|
||||
const BufferReader = require('../utils/reader');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
const assert = require('assert');
|
||||
const secp256k1 = require('../crypto/secp256k1');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
const encoding = require('../utils/encoding');
|
||||
const consensus = require('../protocol/consensus');
|
||||
|
||||
|
||||
@ -1,172 +0,0 @@
|
||||
/*!
|
||||
* aead.js - aead for bcoin
|
||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const ChaCha20 = require('./chacha20');
|
||||
const Poly1305 = require('./poly1305');
|
||||
|
||||
/**
|
||||
* AEAD (used for bip151)
|
||||
* @alias module:crypto.AEAD
|
||||
* @constructor
|
||||
* @see https://github.com/openssh/openssh-portable
|
||||
* @see https://tools.ietf.org/html/rfc7539#section-2.8
|
||||
*/
|
||||
|
||||
function AEAD() {
|
||||
if (!(this instanceof AEAD))
|
||||
return new AEAD();
|
||||
|
||||
this.chacha20 = new ChaCha20();
|
||||
this.poly1305 = new Poly1305();
|
||||
this.aadLen = 0;
|
||||
this.cipherLen = 0;
|
||||
this.polyKey = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the AEAD with a key and iv.
|
||||
* @param {Buffer} key
|
||||
* @param {Buffer} iv - IV / packet sequence number.
|
||||
*/
|
||||
|
||||
AEAD.prototype.init = function init(key, iv) {
|
||||
const polyKey = Buffer.allocUnsafe(32);
|
||||
polyKey.fill(0);
|
||||
|
||||
this.chacha20.init(key, iv);
|
||||
this.chacha20.encrypt(polyKey);
|
||||
this.poly1305.init(polyKey);
|
||||
|
||||
// We need to encrypt a full block
|
||||
// to get the cipher in the correct state.
|
||||
this.chacha20.encrypt(Buffer.allocUnsafe(32));
|
||||
|
||||
// Counter should be one.
|
||||
assert(this.chacha20.getCounter() === 1);
|
||||
|
||||
// Expose for debugging.
|
||||
this.polyKey = polyKey;
|
||||
|
||||
this.aadLen = 0;
|
||||
this.cipherLen = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the aad (will be finalized
|
||||
* on an encrypt/decrypt call).
|
||||
* @param {Buffer} aad
|
||||
*/
|
||||
|
||||
AEAD.prototype.aad = function aad(data) {
|
||||
assert(this.cipherLen === 0, 'Cannot update aad.');
|
||||
this.poly1305.update(data);
|
||||
this.aadLen += data.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encrypt a piece of data.
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
AEAD.prototype.encrypt = function encrypt(data) {
|
||||
if (this.cipherLen === 0)
|
||||
this.pad16(this.aadLen);
|
||||
|
||||
this.chacha20.encrypt(data);
|
||||
this.poly1305.update(data);
|
||||
this.cipherLen += data.length;
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrypt a piece of data.
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
AEAD.prototype.decrypt = function decrypt(data) {
|
||||
if (this.cipherLen === 0)
|
||||
this.pad16(this.aadLen);
|
||||
|
||||
this.cipherLen += data.length;
|
||||
this.poly1305.update(data);
|
||||
this.chacha20.encrypt(data);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Authenticate data without decrypting.
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
AEAD.prototype.auth = function auth(data) {
|
||||
if (this.cipherLen === 0)
|
||||
this.pad16(this.aadLen);
|
||||
|
||||
this.cipherLen += data.length;
|
||||
this.poly1305.update(data);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finalize the aead and generate a MAC.
|
||||
* @returns {Buffer} MAC
|
||||
*/
|
||||
|
||||
AEAD.prototype.finish = function finish() {
|
||||
const len = Buffer.allocUnsafe(16);
|
||||
let lo, hi;
|
||||
|
||||
// The RFC says these are supposed to be
|
||||
// uint32le, but their own fucking test
|
||||
// cases fail unless they are uint64le's.
|
||||
lo = this.aadLen % 0x100000000;
|
||||
hi = (this.aadLen - lo) / 0x100000000;
|
||||
len.writeUInt32LE(lo, 0, true);
|
||||
len.writeUInt32LE(hi, 4, true);
|
||||
|
||||
lo = this.cipherLen % 0x100000000;
|
||||
hi = (this.cipherLen - lo) / 0x100000000;
|
||||
len.writeUInt32LE(lo, 8, true);
|
||||
len.writeUInt32LE(hi, 12, true);
|
||||
|
||||
if (this.cipherLen === 0)
|
||||
this.pad16(this.aadLen);
|
||||
|
||||
this.pad16(this.cipherLen);
|
||||
this.poly1305.update(len);
|
||||
|
||||
return this.poly1305.finish();
|
||||
};
|
||||
|
||||
/**
|
||||
* Pad a chunk before updating mac.
|
||||
* @private
|
||||
* @param {Number} size
|
||||
*/
|
||||
|
||||
AEAD.prototype.pad16 = function pad16(size) {
|
||||
size %= 16;
|
||||
|
||||
if (size === 0)
|
||||
return;
|
||||
|
||||
const pad = Buffer.allocUnsafe(16 - size);
|
||||
pad.fill(0);
|
||||
|
||||
this.poly1305.update(pad);
|
||||
};
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = AEAD;
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,49 +0,0 @@
|
||||
/*!
|
||||
* aes.js - aes for bcoin
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto.aes
|
||||
*/
|
||||
|
||||
const crypto = require('crypto');
|
||||
const native = require('../native').binding;
|
||||
|
||||
/**
|
||||
* Encrypt data with aes 256 cbc.
|
||||
* @param {Buffer} data
|
||||
* @param {Buffer} key
|
||||
* @param {Buffer} iv
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.encipher = function encipher(data, key, iv) {
|
||||
const ctx = crypto.createCipheriv('aes-256-cbc', key, iv);
|
||||
return Buffer.concat([ctx.update(data), ctx.final()]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrypt data with aes 256 cbc.
|
||||
* @param {Buffer} data
|
||||
* @param {Buffer} key
|
||||
* @param {Buffer} iv
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.decipher = function decipher(data, key, iv) {
|
||||
const ctx = crypto.createDecipheriv('aes-256-cbc', key, iv);
|
||||
try {
|
||||
return Buffer.concat([ctx.update(data), ctx.final()]);
|
||||
} catch (e) {
|
||||
throw new Error('Bad key for decryption.');
|
||||
}
|
||||
};
|
||||
|
||||
if (native) {
|
||||
exports.encipher = native.encipher;
|
||||
exports.decipher = native.decipher;
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
/*!
|
||||
* bn.js - big numbers for bcoin
|
||||
* Copyright (c) 2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto.BN
|
||||
*/
|
||||
|
||||
/**
|
||||
* bn.js
|
||||
* @constructor
|
||||
* @see https://github.com/indutny/bn.js
|
||||
*/
|
||||
|
||||
module.exports = require('bn.js');
|
||||
@ -1,36 +0,0 @@
|
||||
/*!
|
||||
* ccmp.js - constant-time compare for bcoin
|
||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
/**
|
||||
* memcmp in constant time (can only return true or false).
|
||||
* This protects us against timing attacks when
|
||||
* comparing an input against a secret string.
|
||||
* @alias module:crypto.ccmp
|
||||
* @see https://cryptocoding.net/index.php/Coding_rules
|
||||
* @see `$ man 3 memcmp` (NetBSD's consttime_memequal)
|
||||
* @param {Buffer} a
|
||||
* @param {Buffer} b
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
module.exports = function ccmp(a, b) {
|
||||
assert(Buffer.isBuffer(a));
|
||||
assert(Buffer.isBuffer(b));
|
||||
|
||||
if (b.length === 0)
|
||||
return a.length === 0;
|
||||
|
||||
let res = a.length ^ b.length;
|
||||
|
||||
for (let i = 0; i < a.length; i++)
|
||||
res |= a[i] ^ b[i % b.length];
|
||||
|
||||
return res === 0;
|
||||
};
|
||||
@ -1,205 +0,0 @@
|
||||
/*!
|
||||
* chacha20.js - chacha20 for bcoin
|
||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const native = require('../native').binding;
|
||||
|
||||
const BIG_ENDIAN = new Int8Array(new Int16Array([1]).buffer)[0] === 0;
|
||||
|
||||
/**
|
||||
* ChaCha20 (used for bip151)
|
||||
* @alias module:crypto.ChaCha20
|
||||
* @constructor
|
||||
* @see https://tools.ietf.org/html/rfc7539#section-2
|
||||
*/
|
||||
|
||||
function ChaCha20() {
|
||||
if (!(this instanceof ChaCha20))
|
||||
return new ChaCha20();
|
||||
|
||||
this.state = new Uint32Array(16);
|
||||
this.stream = new Uint32Array(16);
|
||||
this.bytes = new Uint8Array(this.stream.buffer);
|
||||
|
||||
if (BIG_ENDIAN)
|
||||
this.bytes = Buffer.allocUnsafe(64);
|
||||
|
||||
this.pos = 0;
|
||||
this.ivSize = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize chacha20 with a key, iv, and counter.
|
||||
* @param {Buffer} key
|
||||
* @param {Buffer} iv
|
||||
* @param {Number} counter
|
||||
*/
|
||||
|
||||
ChaCha20.prototype.init = function init(key, iv, counter) {
|
||||
if (key)
|
||||
this.initKey(key);
|
||||
|
||||
if (iv)
|
||||
this.initIV(iv, counter);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set key.
|
||||
* @param {Buffer} key
|
||||
*/
|
||||
|
||||
ChaCha20.prototype.initKey = function initKey(key) {
|
||||
this.state[0] = 0x61707865;
|
||||
this.state[1] = 0x3320646e;
|
||||
this.state[2] = 0x79622d32;
|
||||
this.state[3] = 0x6b206574;
|
||||
|
||||
this.state[4] = key.readUInt32LE(0, true);
|
||||
this.state[5] = key.readUInt32LE(4, true);
|
||||
this.state[6] = key.readUInt32LE(8, true);
|
||||
this.state[7] = key.readUInt32LE(12, true);
|
||||
this.state[8] = key.readUInt32LE(16, true);
|
||||
this.state[9] = key.readUInt32LE(20, true);
|
||||
this.state[10] = key.readUInt32LE(24, true);
|
||||
this.state[11] = key.readUInt32LE(28, true);
|
||||
|
||||
this.state[12] = 0;
|
||||
|
||||
this.pos = 0xffffffff;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set IV and counter.
|
||||
* @param {Buffer} iv
|
||||
* @param {Number} counter
|
||||
*/
|
||||
|
||||
ChaCha20.prototype.initIV = function initIV(iv, counter) {
|
||||
if (iv.length === 8) {
|
||||
this.state[13] = 0;
|
||||
this.state[14] = iv.readUInt32LE(0, true);
|
||||
this.state[15] = iv.readUInt32LE(4, true);
|
||||
} else if (iv.length === 12) {
|
||||
this.state[13] = iv.readUInt32LE(0, true);
|
||||
this.state[14] = iv.readUInt32LE(4, true);
|
||||
this.state[15] = iv.readUInt32LE(8, true);
|
||||
} else {
|
||||
assert(false, 'Bad iv size.');
|
||||
}
|
||||
|
||||
this.ivSize = iv.length * 8;
|
||||
|
||||
this.setCounter(counter);
|
||||
};
|
||||
|
||||
/**
|
||||
* Encrypt/decrypt data.
|
||||
* @param {Buffer} data - Will be mutated.
|
||||
*/
|
||||
|
||||
ChaCha20.prototype.encrypt = function encrypt(data) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (this.pos >= 64) {
|
||||
for (let j = 0; j < 16; j++)
|
||||
this.stream[j] = this.state[j];
|
||||
|
||||
for (let j = 0; j < 10; j++) {
|
||||
qround(this.stream, 0, 4, 8, 12);
|
||||
qround(this.stream, 1, 5, 9, 13);
|
||||
qround(this.stream, 2, 6, 10, 14);
|
||||
qround(this.stream, 3, 7, 11, 15);
|
||||
qround(this.stream, 0, 5, 10, 15);
|
||||
qround(this.stream, 1, 6, 11, 12);
|
||||
qround(this.stream, 2, 7, 8, 13);
|
||||
qround(this.stream, 3, 4, 9, 14);
|
||||
}
|
||||
|
||||
for (let j = 0; j < 16; j++) {
|
||||
this.stream[j] += this.state[j];
|
||||
if (BIG_ENDIAN)
|
||||
this.bytes.writeUInt32LE(this.stream[j], j * 4, true);
|
||||
}
|
||||
|
||||
this.state[12]++;
|
||||
|
||||
if (this.state[12] === 0) {
|
||||
assert(this.ivSize === 64, 'Counter overflow.');
|
||||
this.state[13]++;
|
||||
assert(this.state[13] !== 0, 'Counter overflow.');
|
||||
}
|
||||
|
||||
this.pos = 0;
|
||||
}
|
||||
|
||||
data[i] ^= this.bytes[this.pos++];
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Artificially set the counter.
|
||||
* @param {Number} counter
|
||||
*/
|
||||
|
||||
ChaCha20.prototype.setCounter = function setCounter(counter) {
|
||||
if (!counter)
|
||||
counter = 0;
|
||||
|
||||
const lo = counter % 0x100000000;
|
||||
const hi = (counter - lo) / 0x100000000;
|
||||
|
||||
this.state[12] = lo;
|
||||
|
||||
if (this.ivSize === 64)
|
||||
this.state[13] = hi;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the counter as a uint64.
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
ChaCha20.prototype.getCounter = function getCounter() {
|
||||
const lo = this.state[12];
|
||||
const hi = this.state[13];
|
||||
if (this.ivSize === 64)
|
||||
return hi * 0x100000000 + lo;
|
||||
return lo;
|
||||
};
|
||||
|
||||
if (native)
|
||||
ChaCha20 = native.ChaCha20;
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function qround(x, a, b, c, d) {
|
||||
x[a] += x[b];
|
||||
x[d] = rotl32(x[d] ^ x[a], 16);
|
||||
|
||||
x[c] += x[d];
|
||||
x[b] = rotl32(x[b] ^ x[c], 12);
|
||||
|
||||
x[a] += x[b];
|
||||
x[d] = rotl32(x[d] ^ x[a], 8);
|
||||
|
||||
x[c] += x[d];
|
||||
x[b] = rotl32(x[b] ^ x[c], 7);
|
||||
}
|
||||
|
||||
function rotl32(w, b) {
|
||||
return (w << b) | (w >>> (32 - b));
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = ChaCha20;
|
||||
@ -1,34 +0,0 @@
|
||||
/*!
|
||||
* cleanse.js - memzero for bcoin
|
||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto.cleanse
|
||||
*/
|
||||
|
||||
const native = require('../native').binding;
|
||||
|
||||
let counter = 0;
|
||||
|
||||
/**
|
||||
* A maybe-secure memzero.
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
module.exports = function cleanse(data) {
|
||||
let ctr = counter;
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
data[i] = ctr & 0xff;
|
||||
ctr += i;
|
||||
}
|
||||
|
||||
counter = ctr >>> 0;
|
||||
};
|
||||
|
||||
if (native)
|
||||
exports.cleanse = native.cleanse;
|
||||
@ -1,122 +0,0 @@
|
||||
/*!
|
||||
* digest-browser.js - hash functions for bcoin
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto.digest-browser
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
const assert = require('assert');
|
||||
const hashjs = require('hash.js');
|
||||
const SHA256 = require('./sha256');
|
||||
const POOL64 = Buffer.allocUnsafe(64);
|
||||
|
||||
/**
|
||||
* Hash with chosen algorithm.
|
||||
* @param {String} alg
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.hash = function hash(alg, data) {
|
||||
if (alg === 'sha256')
|
||||
return SHA256.digest(data);
|
||||
|
||||
const algo = hashjs[alg];
|
||||
|
||||
assert(algo != null, 'Unknown algorithm.');
|
||||
|
||||
return Buffer.from(algo().update(data).digest());
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash with ripemd160.
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.ripemd160 = function ripemd160(data) {
|
||||
return exports.hash('ripemd160', data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash with sha1.
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.sha1 = function sha1(data) {
|
||||
return exports.hash('sha1', data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash with sha256.
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.sha256 = function sha256(data) {
|
||||
return SHA256.digest(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash with sha256 and ripemd160 (OP_HASH160).
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.hash160 = function hash160(data) {
|
||||
return exports.hash('ripemd160', SHA256.digest(data));
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash with sha256 twice (OP_HASH256).
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.hash256 = function hash256(data) {
|
||||
return SHA256.hash256(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash left and right hashes with hash256.
|
||||
* @param {Buffer} left
|
||||
* @param {Buffer} right
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.root256 = function root256(left, right) {
|
||||
const data = POOL64;
|
||||
|
||||
assert(left.length === 32);
|
||||
assert(right.length === 32);
|
||||
|
||||
left.copy(data, 0);
|
||||
right.copy(data, 32);
|
||||
|
||||
return exports.hash256(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an HMAC.
|
||||
* @param {String} alg
|
||||
* @param {Buffer} data
|
||||
* @param {Buffer} key
|
||||
* @returns {Buffer} HMAC
|
||||
*/
|
||||
|
||||
exports.hmac = function hmac(alg, data, key) {
|
||||
const algo = hashjs[alg];
|
||||
|
||||
assert(algo != null, 'Unknown algorithm.');
|
||||
|
||||
const ctx = hashjs.hmac(algo, key);
|
||||
|
||||
return Buffer.from(ctx.update(data).digest());
|
||||
};
|
||||
@ -1,120 +0,0 @@
|
||||
/*!
|
||||
* digest.js - hash functions for bcoin
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto.digest
|
||||
*/
|
||||
|
||||
const assert = require('assert');
|
||||
const crypto = require('crypto');
|
||||
const native = require('../native').binding;
|
||||
const POOL64 = Buffer.allocUnsafe(64);
|
||||
|
||||
/**
|
||||
* Hash with chosen algorithm.
|
||||
* @param {String} alg
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.hash = function hash(alg, data) {
|
||||
return crypto.createHash(alg).update(data).digest();
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash with ripemd160.
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.ripemd160 = function ripemd160(data) {
|
||||
return exports.hash('ripemd160', data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash with sha1.
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.sha1 = function sha1(data) {
|
||||
return exports.hash('sha1', data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash with sha256.
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.sha256 = function sha256(data) {
|
||||
return exports.hash('sha256', data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash with sha256 and ripemd160 (OP_HASH160).
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.hash160 = function hash160(data) {
|
||||
return exports.ripemd160(exports.sha256(data));
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash with sha256 twice (OP_HASH256).
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.hash256 = function hash256(data) {
|
||||
return exports.sha256(exports.sha256(data));
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash left and right hashes with hash256.
|
||||
* @param {Buffer} left
|
||||
* @param {Buffer} right
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.root256 = function root256(left, right) {
|
||||
const data = POOL64;
|
||||
|
||||
assert(left.length === 32);
|
||||
assert(right.length === 32);
|
||||
|
||||
left.copy(data, 0);
|
||||
right.copy(data, 32);
|
||||
|
||||
return exports.hash256(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an HMAC.
|
||||
* @param {String} alg
|
||||
* @param {Buffer} data
|
||||
* @param {Buffer} key
|
||||
* @returns {Buffer} HMAC
|
||||
*/
|
||||
|
||||
exports.hmac = function hmac(alg, data, key) {
|
||||
const ctx = crypto.createHmac(alg, key);
|
||||
return ctx.update(data).digest();
|
||||
};
|
||||
|
||||
if (native) {
|
||||
exports.hash = native.hash;
|
||||
exports.hmac = native.hmac;
|
||||
exports.ripemd160 = native.ripemd160;
|
||||
exports.sha1 = native.sha1;
|
||||
exports.sha256 = native.sha256;
|
||||
exports.hash160 = native.hash160;
|
||||
exports.hash256 = native.hash256;
|
||||
exports.root256 = native.root256;
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
/*!
|
||||
* ecdsa.js - ecdsa for bcoin
|
||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto/ecdsa
|
||||
*/
|
||||
|
||||
const assert = require('assert');
|
||||
const elliptic = require('elliptic');
|
||||
const digest = require('./digest');
|
||||
|
||||
/**
|
||||
* Verify ECDSA signature.
|
||||
* @param {String} curve - Curve name.
|
||||
* @param {String} alg - Hash algorithm.
|
||||
* @param {Buffer} msg - Signed message.
|
||||
* @param {Buffer} sig - Signature.
|
||||
* @param {Buffer} key - ASN1 serialized ECDSA key.
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
exports.verify = function verify(curve, alg, msg, sig, key) {
|
||||
assert(typeof curve === 'string', 'No curve selected.');
|
||||
assert(typeof alg === 'string', 'No algorithm selected.');
|
||||
assert(Buffer.isBuffer(msg));
|
||||
assert(Buffer.isBuffer(sig));
|
||||
assert(Buffer.isBuffer(key));
|
||||
|
||||
const ec = elliptic.ec(curve);
|
||||
const hash = digest.hash(alg, msg);
|
||||
|
||||
try {
|
||||
return ec.verify(hash, sig, key);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sign message with ECDSA key.
|
||||
* @memberof module:crypto/pk.ecdsa
|
||||
* @param {String} curve - Curve name.
|
||||
* @param {String} alg - Hash algorithm.
|
||||
* @param {Buffer} msg - Signed message.
|
||||
* @param {Buffer} key - ASN1 serialized ECDSA key.
|
||||
* @returns {Buffer} Signature (DER)
|
||||
*/
|
||||
|
||||
exports.sign = function sign(curve, alg, msg, key) {
|
||||
assert(typeof curve === 'string', 'No curve selected.');
|
||||
assert(typeof alg === 'string', 'No algorithm selected.');
|
||||
assert(Buffer.isBuffer(msg));
|
||||
assert(Buffer.isBuffer(key));
|
||||
|
||||
const ec = elliptic.ec(curve);
|
||||
const hash = digest.hash(alg, msg);
|
||||
const sig = ec.sign(hash, key, { canonical: true });
|
||||
|
||||
return Buffer.from(sig.toDER());
|
||||
};
|
||||
@ -1,65 +0,0 @@
|
||||
/*!
|
||||
* hkdf.js - hkdf for bcoin
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto/hkdf
|
||||
*/
|
||||
|
||||
const digest = require('./digest');
|
||||
|
||||
/**
|
||||
* Perform hkdf extraction.
|
||||
* @param {Buffer} ikm
|
||||
* @param {Buffer} key
|
||||
* @param {String} alg
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.extract = function extract(ikm, key, alg) {
|
||||
return digest.hmac(alg, ikm, key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform hkdf expansion.
|
||||
* @param {Buffer} prk
|
||||
* @param {Buffer} info
|
||||
* @param {Number} len
|
||||
* @param {String} alg
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.expand = function expand(prk, info, len, alg) {
|
||||
const size = digest.hash(alg, Buffer.alloc(0)).length;
|
||||
const blocks = Math.ceil(len / size);
|
||||
|
||||
if (blocks > 255)
|
||||
throw new Error('Too many blocks.');
|
||||
|
||||
const okm = Buffer.allocUnsafe(len);
|
||||
|
||||
if (blocks === 0)
|
||||
return okm;
|
||||
|
||||
const buf = Buffer.allocUnsafe(size + info.length + 1);
|
||||
|
||||
// First round:
|
||||
info.copy(buf, size);
|
||||
buf[buf.length - 1] = 1;
|
||||
|
||||
let out = digest.hmac(alg, buf.slice(size), prk);
|
||||
out.copy(okm, 0);
|
||||
|
||||
for (let i = 1; i < blocks; i++) {
|
||||
out.copy(buf, 0);
|
||||
buf[buf.length - 1]++;
|
||||
out = digest.hmac(alg, buf, prk);
|
||||
out.copy(okm, i * size);
|
||||
}
|
||||
|
||||
return okm;
|
||||
};
|
||||
@ -1,120 +0,0 @@
|
||||
/*!
|
||||
* hmac-drbg.js - hmac-drbg implementation for bcoin
|
||||
* Copyright (c) 2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
* Parts of this software based on hmac-drbg.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const digest = require('./digest');
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
||||
const HASH_ALG = 'sha256';
|
||||
const HASH_SIZE = 32;
|
||||
const RESEED_INTERVAL = 0x1000000000000;
|
||||
const POOL33 = Buffer.allocUnsafe(HASH_SIZE + 1);
|
||||
const POOL112 = Buffer.allocUnsafe(HASH_SIZE * 2 + 48);
|
||||
const POOL145 = Buffer.allocUnsafe(POOL33.length + POOL112.length);
|
||||
|
||||
/**
|
||||
* HmacDRBG
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
function HmacDRBG(entropy, nonce, pers) {
|
||||
if (!(this instanceof HmacDRBG))
|
||||
return new HmacDRBG(entropy, nonce, pers);
|
||||
|
||||
this.K = Buffer.allocUnsafe(HASH_SIZE);
|
||||
this.V = Buffer.allocUnsafe(HASH_SIZE);
|
||||
this.rounds = 0;
|
||||
|
||||
this.init(entropy, nonce, pers);
|
||||
}
|
||||
|
||||
HmacDRBG.prototype.init = function init(entropy, nonce, pers) {
|
||||
for (let i = 0; i < this.V.length; i++) {
|
||||
this.K[i] = 0x00;
|
||||
this.V[i] = 0x01;
|
||||
}
|
||||
|
||||
this.reseed(entropy, nonce, pers);
|
||||
};
|
||||
|
||||
HmacDRBG.prototype.reseed = function reseed(entropy, nonce, pers) {
|
||||
const seed = POOL112;
|
||||
|
||||
assert(Buffer.isBuffer(entropy));
|
||||
assert(Buffer.isBuffer(nonce));
|
||||
assert(Buffer.isBuffer(pers));
|
||||
|
||||
assert(entropy.length === HASH_SIZE);
|
||||
assert(nonce.length === HASH_SIZE);
|
||||
assert(pers.length === 48);
|
||||
|
||||
entropy.copy(seed, 0);
|
||||
nonce.copy(seed, HASH_SIZE);
|
||||
pers.copy(seed, HASH_SIZE * 2);
|
||||
|
||||
this.update(seed);
|
||||
this.rounds = 1;
|
||||
};
|
||||
|
||||
HmacDRBG.prototype.iterate = function iterate() {
|
||||
const data = POOL33;
|
||||
|
||||
this.V.copy(data, 0);
|
||||
data[HASH_SIZE] = 0x00;
|
||||
|
||||
this.K = digest.hmac(HASH_ALG, data, this.K);
|
||||
this.V = digest.hmac(HASH_ALG, this.V, this.K);
|
||||
};
|
||||
|
||||
HmacDRBG.prototype.update = function update(seed) {
|
||||
const data = POOL145;
|
||||
|
||||
assert(Buffer.isBuffer(seed));
|
||||
assert(seed.length === HASH_SIZE * 2 + 48);
|
||||
|
||||
this.V.copy(data, 0);
|
||||
data[HASH_SIZE] = 0x00;
|
||||
seed.copy(data, HASH_SIZE + 1);
|
||||
|
||||
this.K = digest.hmac(HASH_ALG, data, this.K);
|
||||
this.V = digest.hmac(HASH_ALG, this.V, this.K);
|
||||
|
||||
data[HASH_SIZE] = 0x01;
|
||||
|
||||
this.K = digest.hmac(HASH_ALG, data, this.K);
|
||||
this.V = digest.hmac(HASH_ALG, this.V, this.K);
|
||||
};
|
||||
|
||||
HmacDRBG.prototype.generate = function generate(len) {
|
||||
if (this.rounds > RESEED_INTERVAL)
|
||||
throw new Error('Reseed is required.');
|
||||
|
||||
const data = Buffer.allocUnsafe(len);
|
||||
let pos = 0;
|
||||
|
||||
while (pos < len) {
|
||||
this.V = digest.hmac(HASH_ALG, this.V, this.K);
|
||||
this.V.copy(data, pos);
|
||||
pos += HASH_SIZE;
|
||||
}
|
||||
|
||||
this.iterate();
|
||||
this.rounds++;
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = HmacDRBG;
|
||||
@ -1,51 +0,0 @@
|
||||
/*!
|
||||
* crypto/index.js - crypto for bcoin
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto
|
||||
*/
|
||||
|
||||
const digest = require('./digest');
|
||||
const random = require('./random');
|
||||
const aes = require('./aes');
|
||||
|
||||
exports.aes = require('./aes');
|
||||
exports.AEAD = require('./aead');
|
||||
exports.BN = require('./bn');
|
||||
exports.ccmp = require('./ccmp');
|
||||
exports.ChaCha20 = require('./chacha20');
|
||||
exports.cleanse = require('./cleanse');
|
||||
exports.digest = require('./digest');
|
||||
exports.ecdsa = require('./ecdsa');
|
||||
exports.hkdf = require('./hkdf');
|
||||
exports.HmacDRBG = require('./hmac-drbg');
|
||||
exports.merkle = require('./merkle');
|
||||
exports.pbkdf2 = require('./pbkdf2');
|
||||
exports.Poly1305 = require('./poly1305');
|
||||
exports.random = require('./random');
|
||||
exports.rsa = require('./rsa');
|
||||
exports.schnorr = require('./schnorr');
|
||||
exports.scrypt = require('./scrypt');
|
||||
exports.secp256k1 = require('./secp256k1');
|
||||
exports.siphash = require('./siphash');
|
||||
|
||||
exports.hash = digest.hash;
|
||||
exports.ripemd160 = digest.ripemd160;
|
||||
exports.sha1 = digest.sha1;
|
||||
exports.sha256 = digest.sha256;
|
||||
exports.hash160 = digest.hash160;
|
||||
exports.hash256 = digest.hash256;
|
||||
exports.root256 = digest.root256;
|
||||
exports.hmac = digest.hmac;
|
||||
|
||||
exports.encipher = aes.encipher;
|
||||
exports.decipher = aes.decipher;
|
||||
|
||||
exports.randomBytes = random.randomBytes;
|
||||
exports.randomInt = random.randomInt;
|
||||
exports.randomRange = random.randomRange;
|
||||
@ -1,115 +0,0 @@
|
||||
/*!
|
||||
* merkle.js - merkle trees for bcoin
|
||||
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto/merkle
|
||||
*/
|
||||
|
||||
const digest = require('./digest');
|
||||
|
||||
/**
|
||||
* Build a merkle tree from leaves.
|
||||
* Note that this will mutate the `leaves` array!
|
||||
* @param {Buffer[]} leaves
|
||||
* @returns {Array} [nodes, malleated]
|
||||
*/
|
||||
|
||||
exports.createTree = function createTree(leaves) {
|
||||
const nodes = leaves;
|
||||
let size = leaves.length;
|
||||
let malleated = false;
|
||||
let i = 0;
|
||||
|
||||
if (size === 0) {
|
||||
nodes.push(Buffer.alloc(32));
|
||||
return [nodes, malleated];
|
||||
}
|
||||
|
||||
while (size > 1) {
|
||||
for (let j = 0; j < size; j += 2) {
|
||||
const k = Math.min(j + 1, size - 1);
|
||||
const left = nodes[i + j];
|
||||
const right = nodes[i + k];
|
||||
|
||||
if (k === j + 1 && k + 1 === size
|
||||
&& left.equals(right)) {
|
||||
malleated = true;
|
||||
}
|
||||
|
||||
const hash = digest.root256(left, right);
|
||||
|
||||
nodes.push(hash);
|
||||
}
|
||||
i += size;
|
||||
size += 1;
|
||||
size >>>= 1;
|
||||
}
|
||||
|
||||
return [nodes, malleated];
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate merkle root from leaves.
|
||||
* @param {Buffer[]} leaves
|
||||
* @returns {Array} [root, malleated]
|
||||
*/
|
||||
|
||||
exports.createRoot = function createRoot(leaves) {
|
||||
const [nodes, malleated] = exports.createTree(leaves);
|
||||
const root = nodes[nodes.length - 1];
|
||||
return [root, malleated];
|
||||
};
|
||||
|
||||
/**
|
||||
* Collect a merkle branch from vector index.
|
||||
* @param {Number} index
|
||||
* @param {Buffer[]} leaves
|
||||
* @returns {Buffer[]} branch
|
||||
*/
|
||||
|
||||
exports.createBranch = function createBranch(index, leaves) {
|
||||
let size = leaves.length;
|
||||
const [nodes] = exports.createTree(leaves);
|
||||
const branch = [];
|
||||
let i = 0;
|
||||
|
||||
while (size > 1) {
|
||||
const j = Math.min(index ^ 1, size - 1);
|
||||
branch.push(nodes[i + j]);
|
||||
index >>>= 1;
|
||||
i += size;
|
||||
size += 1;
|
||||
size >>>= 1;
|
||||
}
|
||||
|
||||
return branch;
|
||||
};
|
||||
|
||||
/**
|
||||
* Derive merkle root from branch.
|
||||
* @param {Buffer} hash
|
||||
* @param {Buffer[]} branch
|
||||
* @param {Number} index
|
||||
* @returns {Buffer} root
|
||||
*/
|
||||
|
||||
exports.deriveRoot = function deriveRoot(hash, branch, index) {
|
||||
let root = hash;
|
||||
|
||||
for (const hash of branch) {
|
||||
if (index & 1)
|
||||
root = digest.root256(hash, root);
|
||||
else
|
||||
root = digest.root256(root, hash);
|
||||
|
||||
index >>>= 1;
|
||||
}
|
||||
|
||||
return root;
|
||||
};
|
||||
@ -1,101 +0,0 @@
|
||||
/*!
|
||||
* pbkdf2.js - pbkdf2 for bcoin
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto.pbkdf2-browser
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
const digest = require('./digest');
|
||||
const crypto = global.crypto || global.msCrypto || {};
|
||||
const subtle = crypto.subtle || {};
|
||||
|
||||
/**
|
||||
* Perform key derivation using PBKDF2.
|
||||
* @param {Buffer} key
|
||||
* @param {Buffer} salt
|
||||
* @param {Number} iter
|
||||
* @param {Number} len
|
||||
* @param {String} alg
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.derive = function derive(key, salt, iter, len, alg) {
|
||||
const size = digest.hash(alg, Buffer.alloc(0)).length;
|
||||
const blocks = Math.ceil(len / size);
|
||||
const out = Buffer.allocUnsafe(len);
|
||||
const buf = Buffer.allocUnsafe(salt.length + 4);
|
||||
const block = Buffer.allocUnsafe(size);
|
||||
let pos = 0;
|
||||
|
||||
salt.copy(buf, 0);
|
||||
|
||||
for (let i = 0; i < blocks; i++) {
|
||||
buf.writeUInt32BE(i + 1, salt.length, true);
|
||||
let mac = digest.hmac(alg, buf, key);
|
||||
mac.copy(block, 0);
|
||||
for (let j = 1; j < iter; j++) {
|
||||
mac = digest.hmac(alg, mac, key);
|
||||
for (let k = 0; k < size; k++)
|
||||
block[k] ^= mac[k];
|
||||
}
|
||||
block.copy(out, pos);
|
||||
pos += size;
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute pbkdf2 asynchronously.
|
||||
* @param {Buffer} key
|
||||
* @param {Buffer} salt
|
||||
* @param {Number} iter
|
||||
* @param {Number} len
|
||||
* @param {String} alg
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
exports.deriveAsync = async function deriveAsync(key, salt, iter, len, alg) {
|
||||
const algo = { name: 'PBKDF2' };
|
||||
const use = ['deriveBits'];
|
||||
|
||||
if (!subtle.importKey || !subtle.deriveBits)
|
||||
return exports.derive(key, salt, iter, len, alg);
|
||||
|
||||
const options = {
|
||||
name: 'PBKDF2',
|
||||
salt: salt,
|
||||
iterations: iter,
|
||||
hash: getHash(alg)
|
||||
};
|
||||
|
||||
const imported = await subtle.importKey('raw', key, algo, false, use);
|
||||
const data = await subtle.deriveBits(options, imported, len * 8);
|
||||
|
||||
return Buffer.from(data);
|
||||
};
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function getHash(name) {
|
||||
switch (name) {
|
||||
case 'sha1':
|
||||
return 'SHA-1';
|
||||
case 'sha256':
|
||||
return 'SHA-256';
|
||||
case 'sha384':
|
||||
return 'SHA-384';
|
||||
case 'sha512':
|
||||
return 'SHA-512';
|
||||
default:
|
||||
throw new Error(`Algorithm not supported: ${name}.`);
|
||||
}
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
/*!
|
||||
* pbkdf2.js - pbkdf2 for bcoin
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto.pbkdf2
|
||||
*/
|
||||
|
||||
const crypto = require('crypto');
|
||||
|
||||
/**
|
||||
* Perform key derivation using PBKDF2.
|
||||
* @param {Buffer} key
|
||||
* @param {Buffer} salt
|
||||
* @param {Number} iter
|
||||
* @param {Number} len
|
||||
* @param {String} alg
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.derive = function derive(key, salt, iter, len, alg) {
|
||||
return crypto.pbkdf2Sync(key, salt, iter, len, alg);
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute pbkdf2 asynchronously.
|
||||
* @param {Buffer} key
|
||||
* @param {Buffer} salt
|
||||
* @param {Number} iter
|
||||
* @param {Number} len
|
||||
* @param {String} alg
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
exports.deriveAsync = function deriveAsync(key, salt, iter, len, alg) {
|
||||
return new Promise((resolve, reject) => {
|
||||
crypto.pbkdf2(key, salt, iter, len, alg, (err, result) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -1,321 +0,0 @@
|
||||
/*!
|
||||
* poly1305.js - poly1305 for bcoin
|
||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const native = require('../native').binding;
|
||||
|
||||
/**
|
||||
* Poly1305 (used for bip151)
|
||||
* @alias module:crypto/chachapoly.Poly1305
|
||||
* @constructor
|
||||
* @see https://github.com/floodyberry/poly1305-donna
|
||||
* @see https://tools.ietf.org/html/rfc7539#section-2.5
|
||||
*/
|
||||
|
||||
function Poly1305() {
|
||||
if (!(this instanceof Poly1305))
|
||||
return new Poly1305();
|
||||
|
||||
this.r = new Uint16Array(10);
|
||||
this.h = new Uint16Array(10);
|
||||
this.pad = new Uint16Array(8);
|
||||
this.fin = 0;
|
||||
this.leftover = 0;
|
||||
this.buffer = Buffer.allocUnsafe(16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize poly1305 with a key.
|
||||
* @param {Buffer} key
|
||||
*/
|
||||
|
||||
Poly1305.prototype.init = function init(key) {
|
||||
// r &= 0xffffffc0ffffffc0ffffffc0fffffff
|
||||
const t0 = key.readUInt16LE(0, true);
|
||||
const t1 = key.readUInt16LE(2, true);
|
||||
const t2 = key.readUInt16LE(4, true);
|
||||
const t3 = key.readUInt16LE(6, true);
|
||||
const t4 = key.readUInt16LE(8, true);
|
||||
const t5 = key.readUInt16LE(10, true);
|
||||
const t6 = key.readUInt16LE(12, true);
|
||||
const t7 = key.readUInt16LE(14, true);
|
||||
|
||||
this.r[0] = t0 & 0x1fff;
|
||||
this.r[1] = ((t0 >>> 13) | (t1 << 3)) & 0x1fff;
|
||||
this.r[2] = ((t1 >>> 10) | (t2 << 6)) & 0x1f03;
|
||||
this.r[3] = ((t2 >>> 7) | (t3 << 9)) & 0x1fff;
|
||||
this.r[4] = ((t3 >>> 4) | (t4 << 12)) & 0x00ff;
|
||||
this.r[5] = (t4 >>> 1) & 0x1ffe;
|
||||
this.r[6] = ((t4 >>> 14) | (t5 << 2)) & 0x1fff;
|
||||
this.r[7] = ((t5 >>> 11) | (t6 << 5)) & 0x1f81;
|
||||
this.r[8] = ((t6 >>> 8) | (t7 << 8)) & 0x1fff;
|
||||
this.r[9] = (t7 >>> 5) & 0x007f;
|
||||
|
||||
// h = 0
|
||||
for (let i = 0; i < 10; i++)
|
||||
this.h[i] = 0;
|
||||
|
||||
// save pad for later
|
||||
for (let i = 0; i < 8; i++)
|
||||
this.pad[i] = key.readUInt16LE(16 + (2 * i), true);
|
||||
|
||||
this.leftover = 0;
|
||||
this.fin = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Process 16 byte blocks.
|
||||
* @param {Buffer} data - Blocks.
|
||||
* @param {Number} bytes - Size.
|
||||
* @param {Number} m - Offset pointer.
|
||||
*/
|
||||
|
||||
Poly1305.prototype.blocks = function blocks(data, bytes, m) {
|
||||
const hibit = this.fin ? 0 : (1 << 11); // 1 << 128
|
||||
const d = new Uint32Array(10);
|
||||
|
||||
while (bytes >= 16) {
|
||||
// h += m[i]
|
||||
const t0 = data.readUInt16LE(m + 0, true);
|
||||
const t1 = data.readUInt16LE(m + 2, true);
|
||||
const t2 = data.readUInt16LE(m + 4, true);
|
||||
const t3 = data.readUInt16LE(m + 6, true);
|
||||
const t4 = data.readUInt16LE(m + 8, true);
|
||||
const t5 = data.readUInt16LE(m + 10, true);
|
||||
const t6 = data.readUInt16LE(m + 12, true);
|
||||
const t7 = data.readUInt16LE(m + 14, true);
|
||||
|
||||
this.h[0] += t0 & 0x1fff;
|
||||
this.h[1] += ((t0 >>> 13) | (t1 << 3)) & 0x1fff;
|
||||
this.h[2] += ((t1 >>> 10) | (t2 << 6)) & 0x1fff;
|
||||
this.h[3] += ((t2 >>> 7) | (t3 << 9)) & 0x1fff;
|
||||
this.h[4] += ((t3 >>> 4) | (t4 << 12)) & 0x1fff;
|
||||
this.h[5] += ((t4 >>> 1)) & 0x1fff;
|
||||
this.h[6] += ((t4 >>> 14) | (t5 << 2)) & 0x1fff;
|
||||
this.h[7] += ((t5 >>> 11) | (t6 << 5)) & 0x1fff;
|
||||
this.h[8] += ((t6 >>> 8) | (t7 << 8)) & 0x1fff;
|
||||
this.h[9] += ((t7 >>> 5)) | hibit;
|
||||
|
||||
// h *= r, (partial) h %= p
|
||||
let c = 0;
|
||||
for (let i = 0; i < 10; i++) {
|
||||
d[i] = c;
|
||||
|
||||
for (let j = 0; j < 10; j++) {
|
||||
let a = this.h[j];
|
||||
|
||||
if (j <= i)
|
||||
a *= this.r[i - j];
|
||||
else
|
||||
a *= 5 * this.r[i + 10 - j];
|
||||
|
||||
d[i] += a;
|
||||
|
||||
// Sum(h[i] * r[i] * 5) will overflow slightly
|
||||
// above 6 products with an unclamped r, so
|
||||
// carry at 5
|
||||
if (j === 4) {
|
||||
c = d[i] >>> 13;
|
||||
d[i] &= 0x1fff;
|
||||
}
|
||||
}
|
||||
|
||||
c += d[i] >>> 13;
|
||||
d[i] &= 0x1fff;
|
||||
}
|
||||
|
||||
c = (c << 2) + c; // c *= 5
|
||||
c += d[0];
|
||||
d[0] = (c & 0x1fff);
|
||||
c = c >>> 13;
|
||||
d[1] += c;
|
||||
|
||||
for (let i = 0; i < 10; i++)
|
||||
this.h[i] = d[i];
|
||||
|
||||
m += 16;
|
||||
bytes -= 16;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the MAC with data (will be
|
||||
* processed as 16 byte blocks).
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
Poly1305.prototype.update = function update(data) {
|
||||
let bytes = data.length;
|
||||
let m = 0;
|
||||
|
||||
// handle leftover
|
||||
if (this.leftover) {
|
||||
let want = 16 - this.leftover;
|
||||
|
||||
if (want > bytes)
|
||||
want = bytes;
|
||||
|
||||
for (let i = 0; i < want; i++)
|
||||
this.buffer[this.leftover + i] = data[m + i];
|
||||
|
||||
bytes -= want;
|
||||
m += want;
|
||||
|
||||
this.leftover += want;
|
||||
|
||||
if (this.leftover < 16)
|
||||
return;
|
||||
|
||||
this.blocks(this.buffer, 16, 0);
|
||||
this.leftover = 0;
|
||||
}
|
||||
|
||||
// process full blocks
|
||||
if (bytes >= 16) {
|
||||
const want = bytes & ~(16 - 1);
|
||||
this.blocks(data, want, m);
|
||||
m += want;
|
||||
bytes -= want;
|
||||
}
|
||||
|
||||
// store leftover
|
||||
if (bytes) {
|
||||
for (let i = 0; i < bytes; i++)
|
||||
this.buffer[this.leftover + i] = data[m + i];
|
||||
this.leftover += bytes;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Finalize and return a 16-byte MAC.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
Poly1305.prototype.finish = function finish() {
|
||||
const mac = Buffer.allocUnsafe(16);
|
||||
const g = new Uint16Array(10);
|
||||
|
||||
// process the remaining block
|
||||
if (this.leftover) {
|
||||
let i = this.leftover;
|
||||
this.buffer[i++] = 1;
|
||||
for (; i < 16; i++)
|
||||
this.buffer[i] = 0;
|
||||
this.fin = 1;
|
||||
this.blocks(this.buffer, 16, 0);
|
||||
}
|
||||
|
||||
// fully carry h
|
||||
let c = this.h[1] >>> 13;
|
||||
this.h[1] &= 0x1fff;
|
||||
for (let i = 2; i < 10; i++) {
|
||||
this.h[i] += c;
|
||||
c = this.h[i] >>> 13;
|
||||
this.h[i] &= 0x1fff;
|
||||
}
|
||||
this.h[0] += c * 5;
|
||||
c = this.h[0] >>> 13;
|
||||
this.h[0] &= 0x1fff;
|
||||
this.h[1] += c;
|
||||
c = this.h[1] >>> 13;
|
||||
this.h[1] &= 0x1fff;
|
||||
this.h[2] += c;
|
||||
|
||||
// compute h + -p
|
||||
g[0] = this.h[0] + 5;
|
||||
c = g[0] >>> 13;
|
||||
g[0] &= 0x1fff;
|
||||
for (let i = 1; i < 10; i++) {
|
||||
g[i] = this.h[i] + c;
|
||||
c = g[i] >>> 13;
|
||||
g[i] &= 0x1fff;
|
||||
}
|
||||
|
||||
// select h if h < p, or h + -p if h >= p
|
||||
let mask = (c ^ 1) - 1;
|
||||
for (let i = 0; i < 10; i++)
|
||||
g[i] &= mask;
|
||||
mask = ~mask;
|
||||
for (let i = 0; i < 10; i++)
|
||||
this.h[i] = (this.h[i] & mask) | g[i];
|
||||
|
||||
// h = h % (2^128)
|
||||
this.h[0] = ((this.h[0]) | (this.h[1] << 13)) & 0xffff;
|
||||
this.h[1] = ((this.h[1] >>> 3) | (this.h[2] << 10)) & 0xffff;
|
||||
this.h[2] = ((this.h[2] >>> 6) | (this.h[3] << 7)) & 0xffff;
|
||||
this.h[3] = ((this.h[3] >>> 9) | (this.h[4] << 4)) & 0xffff;
|
||||
this.h[4] = ((this.h[4] >>> 12)
|
||||
| (this.h[5] << 1) | (this.h[6] << 14)) & 0xffff;
|
||||
this.h[5] = ((this.h[6] >>> 2) | (this.h[7] << 11)) & 0xffff;
|
||||
this.h[6] = ((this.h[7] >>> 5) | (this.h[8] << 8)) & 0xffff;
|
||||
this.h[7] = ((this.h[8] >>> 8) | (this.h[9] << 5)) & 0xffff;
|
||||
|
||||
// mac = (h + pad) % (2^128)
|
||||
let f = this.h[0] + this.pad[0];
|
||||
this.h[0] = f;
|
||||
for (let i = 1; i < 8; i++) {
|
||||
f = this.h[i] + this.pad[i] + (f >>> 16);
|
||||
this.h[i] = f;
|
||||
}
|
||||
|
||||
for (let i = 0; i < 8; i++)
|
||||
mac.writeUInt16LE(this.h[i], i * 2, true);
|
||||
|
||||
// zero out the state
|
||||
for (let i = 0; i < 10; i++)
|
||||
this.h[i] = 0;
|
||||
|
||||
for (let i = 0; i < 10; i++)
|
||||
this.r[i] = 0;
|
||||
|
||||
for (let i = 0; i < 8; i++)
|
||||
this.pad[i] = 0;
|
||||
|
||||
return mac;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a MAC for a message and key.
|
||||
* @param {Buffer} msg
|
||||
* @param {Buffer} key
|
||||
* @returns {Buffer} MAC
|
||||
*/
|
||||
|
||||
Poly1305.auth = function auth(msg, key) {
|
||||
const poly = new Poly1305();
|
||||
poly.init(key);
|
||||
poly.update(msg);
|
||||
return poly.finish();
|
||||
};
|
||||
|
||||
/**
|
||||
* Compare two MACs in constant time.
|
||||
* @param {Buffer} mac1
|
||||
* @param {Buffer} mac2
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
Poly1305.verify = function verify(mac1, mac2) {
|
||||
let dif = 0;
|
||||
|
||||
// Compare in constant time.
|
||||
for (let i = 0; i < 16; i++)
|
||||
dif |= mac1[i] ^ mac2[i];
|
||||
|
||||
dif = (dif - 1) >>> 31;
|
||||
|
||||
return (dif & 1) !== 0;
|
||||
};
|
||||
|
||||
if (native)
|
||||
Poly1305 = native.Poly1305;
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Poly1305;
|
||||
@ -1,63 +0,0 @@
|
||||
/*!
|
||||
* random-browser.js - randomness for bcoin
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto.random-browser
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
const crypto = global.crypto || global.msCrypto || {};
|
||||
|
||||
/**
|
||||
* Generate pseudo-random bytes.
|
||||
* @param {Number} size
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.randomBytes = function randomBytes(size) {
|
||||
const data = new Uint8Array(size);
|
||||
crypto.getRandomValues(data);
|
||||
return Buffer.from(data.buffer);
|
||||
};
|
||||
|
||||
if (!crypto.getRandomValues) {
|
||||
// Out of luck here. Use bad randomness for now.
|
||||
exports.randomBytes = function randomBytes(size) {
|
||||
const data = Buffer.allocUnsafe(size);
|
||||
|
||||
for (let i = 0; i < data.length; i++)
|
||||
data[i] = Math.floor(Math.random() * 256);
|
||||
|
||||
return data;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random uint32.
|
||||
* Probably more cryptographically sound than
|
||||
* `Math.random()`.
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
exports.randomInt = function randomInt() {
|
||||
return exports.randomBytes(4).readUInt32LE(0, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a random number within a range.
|
||||
* Probably more cryptographically sound than
|
||||
* `Math.random()`.
|
||||
* @param {Number} min - Inclusive.
|
||||
* @param {Number} max - Exclusive.
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
exports.randomRange = function randomRange(min, max) {
|
||||
const num = exports.randomInt();
|
||||
return Math.floor((num / 0x100000000) * (max - min) + min);
|
||||
};
|
||||
@ -1,47 +0,0 @@
|
||||
/*!
|
||||
* random.js - randomness for bcoin
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto.random
|
||||
*/
|
||||
|
||||
const crypto = require('crypto');
|
||||
|
||||
/**
|
||||
* Generate pseudo-random bytes.
|
||||
* @function
|
||||
* @param {Number} size
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
exports.randomBytes = crypto.randomBytes;
|
||||
|
||||
/**
|
||||
* Generate a random uint32.
|
||||
* Probably more cryptographically sound than
|
||||
* `Math.random()`.
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
exports.randomInt = function randomInt() {
|
||||
return exports.randomBytes(4).readUInt32LE(0, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a random number within a range.
|
||||
* Probably more cryptographically sound than
|
||||
* `Math.random()`.
|
||||
* @param {Number} min - Inclusive.
|
||||
* @param {Number} max - Exclusive.
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
exports.randomRange = function randomRange(min, max) {
|
||||
const num = exports.randomInt();
|
||||
return Math.floor((num / 0x100000000) * (max - min) + min);
|
||||
};
|
||||
@ -1,186 +0,0 @@
|
||||
/*!
|
||||
* rsa-browser.js - rsa for bcoin
|
||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const BN = require('./bn');
|
||||
const ASN1 = require('../utils/asn1');
|
||||
const digest = require('./digest');
|
||||
const ccmp = require('./ccmp');
|
||||
|
||||
/**
|
||||
* @exports crypto/rsa
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
const rsa = exports;
|
||||
|
||||
/**
|
||||
* PKCS signature prefixes.
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
rsa.prefixes = {
|
||||
md5: Buffer.from('3020300c06082a864886f70d020505000410', 'hex'),
|
||||
sha1: Buffer.from('3021300906052b0e03021a05000414', 'hex'),
|
||||
sha224: Buffer.from('302d300d06096086480165030402040500041c', 'hex'),
|
||||
sha256: Buffer.from('3031300d060960864801650304020105000420', 'hex'),
|
||||
sha384: Buffer.from('3041300d060960864801650304020205000430', 'hex'),
|
||||
sha512: Buffer.from('3051300d060960864801650304020305000440', 'hex'),
|
||||
ripemd160: Buffer.from('30203008060628cf060300310414', 'hex')
|
||||
};
|
||||
|
||||
/**
|
||||
* Verify RSA signature.
|
||||
* @param {String} alg - Hash algorithm.
|
||||
* @param {Buffer} msg - Signed message.
|
||||
* @param {Buffer} sig - Signature.
|
||||
* @param {Buffer} key - ASN1 serialized RSA key.
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
rsa.verify = function verify(alg, msg, sig, key) {
|
||||
assert(typeof alg === 'string', 'No algorithm selected.');
|
||||
assert(Buffer.isBuffer(msg));
|
||||
assert(Buffer.isBuffer(sig));
|
||||
assert(Buffer.isBuffer(key));
|
||||
|
||||
const prefix = rsa.prefixes[alg];
|
||||
|
||||
if (!prefix)
|
||||
throw new Error('Unknown PKCS prefix.');
|
||||
|
||||
const hash = digest.hash(alg, msg);
|
||||
const len = prefix.length + hash.length;
|
||||
const pub = ASN1.parseRSAPublic(key);
|
||||
|
||||
const N = new BN(pub.modulus);
|
||||
const e = new BN(pub.publicExponent);
|
||||
const k = Math.ceil(N.bitLength() / 8);
|
||||
|
||||
if (k < len + 11)
|
||||
throw new Error('Message too long.');
|
||||
|
||||
const m = rsa.encrypt(N, e, sig);
|
||||
const em = leftpad(m, k);
|
||||
|
||||
let ok = ceq(em[0], 0x00);
|
||||
ok &= ceq(em[1], 0x01);
|
||||
ok &= ccmp(em.slice(k - hash.length, k), hash);
|
||||
ok &= ccmp(em.slice(k - len, k - hash.length), prefix);
|
||||
ok &= ceq(em[k - len - 1], 0x00);
|
||||
|
||||
for (let i = 2; i < k - len - 1; i++)
|
||||
ok &= ceq(em[i], 0xff);
|
||||
|
||||
return ok === 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sign message with RSA key.
|
||||
* @param {String} alg - Hash algorithm.
|
||||
* @param {Buffer} msg - Signed message.
|
||||
* @param {Buffer} key - ASN1 serialized RSA key.
|
||||
* @returns {Buffer} Signature (DER)
|
||||
*/
|
||||
|
||||
rsa.sign = function sign(alg, msg, key) {
|
||||
assert(typeof alg === 'string', 'No algorithm selected.');
|
||||
assert(Buffer.isBuffer(msg));
|
||||
assert(Buffer.isBuffer(key));
|
||||
|
||||
const prefix = rsa.prefixes[alg];
|
||||
|
||||
if (!prefix)
|
||||
throw new Error('Unknown PKCS prefix.');
|
||||
|
||||
const hash = digest.hash(alg, msg);
|
||||
const len = prefix.length + hash.length;
|
||||
const priv = ASN1.parseRSAPrivate(key);
|
||||
|
||||
const N = new BN(priv.modulus);
|
||||
const D = new BN(priv.privateExponent);
|
||||
const k = Math.ceil(N.bitLength() / 8);
|
||||
|
||||
if (k < len + 11)
|
||||
throw new Error('Message too long.');
|
||||
|
||||
const em = Buffer.allocUnsafe(k);
|
||||
em.fill(0);
|
||||
|
||||
em[1] = 0x01;
|
||||
for (let i = 2; i < k - len - 1; i++)
|
||||
em[i] = 0xff;
|
||||
|
||||
prefix.copy(em, k - len);
|
||||
hash.copy(em, k - hash.length);
|
||||
|
||||
return rsa.decrypt(N, D, em);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrypt with modulus and exponent.
|
||||
* @param {BN} N
|
||||
* @param {BN} D
|
||||
* @param {Buffer} m
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
rsa.decrypt = function decrypt(N, D, m) {
|
||||
const c = new BN(m);
|
||||
|
||||
if (c.cmp(N) > 0)
|
||||
throw new Error('Cannot decrypt.');
|
||||
|
||||
return c
|
||||
.toRed(BN.red(N))
|
||||
.redPow(D)
|
||||
.fromRed()
|
||||
.toArrayLike(Buffer, 'be');
|
||||
};
|
||||
|
||||
/**
|
||||
* Encrypt with modulus and exponent.
|
||||
* @param {BN} N
|
||||
* @param {BN} e
|
||||
* @param {Buffer} m
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
rsa.encrypt = function encrypt(N, e, m) {
|
||||
return new BN(m)
|
||||
.toRed(BN.red(N))
|
||||
.redPow(e)
|
||||
.fromRed()
|
||||
.toArrayLike(Buffer, 'be');
|
||||
};
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function leftpad(input, size) {
|
||||
let n = input.length;
|
||||
|
||||
if (n > size)
|
||||
n = size;
|
||||
|
||||
const out = Buffer.allocUnsafe(size);
|
||||
out.fill(0);
|
||||
|
||||
input.copy(out, out.length - n);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function ceq(a, b) {
|
||||
let r = ~(a ^ b) & 0xff;
|
||||
r &= r >>> 4;
|
||||
r &= r >>> 2;
|
||||
r &= r >>> 1;
|
||||
return r === 1;
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
/*!
|
||||
* rsa.js - RSA for bcoin
|
||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto/rsa
|
||||
*/
|
||||
|
||||
const assert = require('assert');
|
||||
const crypto = require('crypto');
|
||||
const PEM = require('../utils/pem');
|
||||
|
||||
/**
|
||||
* Verify RSA signature.
|
||||
* @param {String} alg - Hash algorithm.
|
||||
* @param {Buffer} msg - Signed message.
|
||||
* @param {Buffer} sig - Signature.
|
||||
* @param {Buffer} key - ASN1 serialized RSA key.
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
exports.verify = function verify(alg, msg, sig, key) {
|
||||
assert(typeof alg === 'string', 'No algorithm selected.');
|
||||
assert(Buffer.isBuffer(msg));
|
||||
assert(Buffer.isBuffer(sig));
|
||||
assert(Buffer.isBuffer(key));
|
||||
|
||||
const name = normalizeAlg('rsa', alg);
|
||||
const pem = PEM.encode(key, 'rsa', 'public key');
|
||||
const ctx = crypto.createVerify(name);
|
||||
|
||||
try {
|
||||
ctx.update(msg);
|
||||
return ctx.verify(pem, sig);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sign message with RSA key.
|
||||
* @param {String} alg - Hash algorithm.
|
||||
* @param {Buffer} msg - Signed message.
|
||||
* @param {Buffer} key - ASN1 serialized RSA key.
|
||||
* @returns {Buffer} Signature (DER)
|
||||
*/
|
||||
|
||||
exports.sign = function sign(alg, msg, key) {
|
||||
assert(typeof alg === 'string', 'No algorithm selected.');
|
||||
assert(Buffer.isBuffer(msg));
|
||||
assert(Buffer.isBuffer(key));
|
||||
|
||||
const name = normalizeAlg('rsa', alg);
|
||||
const pem = PEM.encode(key, 'rsa', 'private key');
|
||||
const ctx = crypto.createSign(name);
|
||||
|
||||
ctx.update(msg);
|
||||
|
||||
return ctx.sign(pem);
|
||||
};
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function normalizeAlg(alg, hash) {
|
||||
return `${alg.toUpperCase()}-${hash.toUpperCase()}`;
|
||||
}
|
||||
@ -1,342 +0,0 @@
|
||||
/*!
|
||||
* schnorr.js - schnorr signatures for bcoin
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const elliptic = require('elliptic');
|
||||
const Signature = require('elliptic/lib/elliptic/ec/signature');
|
||||
const BN = require('./bn');
|
||||
const HmacDRBG = require('./hmac-drbg');
|
||||
const sha256 = require('./digest').sha256;
|
||||
const curve = elliptic.ec('secp256k1').curve;
|
||||
const POOL64 = Buffer.allocUnsafe(64);
|
||||
|
||||
/**
|
||||
* @exports crypto/schnorr
|
||||
*/
|
||||
|
||||
const schnorr = exports;
|
||||
|
||||
/**
|
||||
* Hash (r | M).
|
||||
* @param {Buffer} msg
|
||||
* @param {BN} r
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
schnorr.hash = function hash(msg, r) {
|
||||
const R = r.toArrayLike(Buffer, 'be', 32);
|
||||
const B = POOL64;
|
||||
|
||||
R.copy(B, 0);
|
||||
msg.copy(B, 32);
|
||||
|
||||
return new BN(sha256(B));
|
||||
};
|
||||
|
||||
/**
|
||||
* Sign message.
|
||||
* @private
|
||||
* @param {Buffer} msg
|
||||
* @param {BN} priv
|
||||
* @param {BN} k
|
||||
* @param {Buffer} pn
|
||||
* @returns {Signature|null}
|
||||
*/
|
||||
|
||||
schnorr.trySign = function trySign(msg, prv, k, pn) {
|
||||
if (prv.isZero())
|
||||
throw new Error('Bad private key.');
|
||||
|
||||
if (prv.gte(curve.n))
|
||||
throw new Error('Bad private key.');
|
||||
|
||||
if (k.isZero())
|
||||
return null;
|
||||
|
||||
if (k.gte(curve.n))
|
||||
return null;
|
||||
|
||||
let r = curve.g.mul(k);
|
||||
|
||||
if (pn)
|
||||
r = r.add(pn);
|
||||
|
||||
if (r.y.isOdd()) {
|
||||
k = k.umod(curve.n);
|
||||
k = curve.n.sub(k);
|
||||
}
|
||||
|
||||
const h = schnorr.hash(msg, r.getX());
|
||||
|
||||
if (h.isZero())
|
||||
return null;
|
||||
|
||||
if (h.gte(curve.n))
|
||||
return null;
|
||||
|
||||
let s = h.imul(prv);
|
||||
s = k.isub(s);
|
||||
s = s.umod(curve.n);
|
||||
|
||||
if (s.isZero())
|
||||
return null;
|
||||
|
||||
return new Signature({ r: r.getX(), s: s });
|
||||
};
|
||||
|
||||
/**
|
||||
* Sign message.
|
||||
* @param {Buffer} msg
|
||||
* @param {Buffer} key
|
||||
* @param {Buffer} pubNonce
|
||||
* @returns {Signature}
|
||||
*/
|
||||
|
||||
schnorr.sign = function sign(msg, key, pubNonce) {
|
||||
const prv = new BN(key);
|
||||
const drbg = schnorr.drbg(msg, key, pubNonce);
|
||||
const len = curve.n.byteLength();
|
||||
|
||||
let pn;
|
||||
if (pubNonce)
|
||||
pn = curve.decodePoint(pubNonce);
|
||||
|
||||
let sig;
|
||||
while (!sig) {
|
||||
const k = new BN(drbg.generate(len));
|
||||
sig = schnorr.trySign(msg, prv, k, pn);
|
||||
}
|
||||
|
||||
return sig;
|
||||
};
|
||||
|
||||
/**
|
||||
* Verify signature.
|
||||
* @param {Buffer} msg
|
||||
* @param {Buffer} signature
|
||||
* @param {Buffer} key
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
schnorr.verify = function verify(msg, signature, key) {
|
||||
const sig = new Signature(signature);
|
||||
const h = schnorr.hash(msg, sig.r);
|
||||
|
||||
if (h.gte(curve.n))
|
||||
throw new Error('Invalid hash.');
|
||||
|
||||
if (h.isZero())
|
||||
throw new Error('Invalid hash.');
|
||||
|
||||
if (sig.s.gte(curve.n))
|
||||
throw new Error('Invalid S value.');
|
||||
|
||||
if (sig.r.gt(curve.p))
|
||||
throw new Error('Invalid R value.');
|
||||
|
||||
const k = curve.decodePoint(key);
|
||||
const l = k.mul(h);
|
||||
const r = curve.g.mul(sig.s);
|
||||
const rl = l.add(r);
|
||||
|
||||
if (rl.y.isOdd())
|
||||
throw new Error('Odd R value.');
|
||||
|
||||
return rl.getX().eq(sig.r);
|
||||
};
|
||||
|
||||
/**
|
||||
* Recover public key.
|
||||
* @param {Buffer} msg
|
||||
* @param {Buffer} signature
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
schnorr.recover = function recover(signature, msg) {
|
||||
const sig = new Signature(signature);
|
||||
const h = schnorr.hash(msg, sig.r);
|
||||
|
||||
if (h.gte(curve.n))
|
||||
throw new Error('Invalid hash.');
|
||||
|
||||
if (h.isZero())
|
||||
throw new Error('Invalid hash.');
|
||||
|
||||
if (sig.s.gte(curve.n))
|
||||
throw new Error('Invalid S value.');
|
||||
|
||||
if (sig.r.gt(curve.p))
|
||||
throw new Error('Invalid R value.');
|
||||
|
||||
let hinv = h.invm(curve.n);
|
||||
hinv = hinv.umod(curve.n);
|
||||
|
||||
let s = sig.s;
|
||||
s = curve.n.sub(s);
|
||||
s = s.umod(curve.n);
|
||||
|
||||
s = s.imul(hinv);
|
||||
s = s.umod(curve.n);
|
||||
|
||||
const R = curve.pointFromX(sig.r, false);
|
||||
let l = R.mul(hinv);
|
||||
let r = curve.g.mul(s);
|
||||
const k = l.add(r);
|
||||
|
||||
l = k.mul(h);
|
||||
r = curve.g.mul(sig.s);
|
||||
|
||||
const rl = l.add(r);
|
||||
|
||||
if (rl.y.isOdd())
|
||||
throw new Error('Odd R value.');
|
||||
|
||||
if (!rl.getX().eq(sig.r))
|
||||
throw new Error('Could not recover pubkey.');
|
||||
|
||||
return Buffer.from(k.encode('array', true));
|
||||
};
|
||||
|
||||
/**
|
||||
* Combine signatures.
|
||||
* @param {Buffer[]} sigs
|
||||
* @returns {Signature}
|
||||
*/
|
||||
|
||||
schnorr.combineSigs = function combineSigs(sigs) {
|
||||
let s = new BN(0);
|
||||
let r, last;
|
||||
|
||||
for (let i = 0; i < sigs.length; i++) {
|
||||
const sig = new Signature(sigs[i]);
|
||||
|
||||
if (sig.s.isZero())
|
||||
throw new Error('Bad S value.');
|
||||
|
||||
if (sig.s.gte(curve.n))
|
||||
throw new Error('Bad S value.');
|
||||
|
||||
if (!r)
|
||||
r = sig.r;
|
||||
|
||||
if (last && !last.r.eq(sig.r))
|
||||
throw new Error('Bad signature combination.');
|
||||
|
||||
s = s.iadd(sig.s);
|
||||
s = s.umod(curve.n);
|
||||
|
||||
last = sig;
|
||||
}
|
||||
|
||||
if (s.isZero())
|
||||
throw new Error('Bad combined signature.');
|
||||
|
||||
return new Signature({ r: r, s: s });
|
||||
};
|
||||
|
||||
/**
|
||||
* Combine public keys.
|
||||
* @param {Buffer[]} keys
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
schnorr.combineKeys = function combineKeys(keys) {
|
||||
if (keys.length === 0)
|
||||
throw new Error();
|
||||
|
||||
if (keys.length === 1)
|
||||
return keys[0];
|
||||
|
||||
let point = curve.decodePoint(keys[0]);
|
||||
|
||||
for (let i = 1; i < keys.length; i++) {
|
||||
const key = curve.decodePoint(keys[i]);
|
||||
point = point.add(key);
|
||||
}
|
||||
|
||||
return Buffer.from(point.encode('array', true));
|
||||
};
|
||||
|
||||
/**
|
||||
* Partially sign.
|
||||
* @param {Buffer} msg
|
||||
* @param {Buffer} priv
|
||||
* @param {Buffer} privNonce
|
||||
* @param {Buffer} pubNonce
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
schnorr.partialSign = function partialSign(msg, priv, privNonce, pubNonce) {
|
||||
const prv = new BN(priv);
|
||||
const k = new BN(privNonce);
|
||||
const pn = curve.decodePoint(pubNonce);
|
||||
const sig = schnorr.trySign(msg, prv, k, pn);
|
||||
|
||||
if (!sig)
|
||||
throw new Error('Bad K value.');
|
||||
|
||||
return sig;
|
||||
};
|
||||
|
||||
/**
|
||||
* Schnorr personalization string.
|
||||
* @const {Buffer}
|
||||
*/
|
||||
|
||||
schnorr.alg = Buffer.from('Schnorr+SHA256 ', 'ascii');
|
||||
|
||||
/**
|
||||
* Instantiate an HMAC-DRBG.
|
||||
* @param {Buffer} msg
|
||||
* @param {Buffer} priv
|
||||
* @param {Buffer} data
|
||||
* @returns {HmacDRBG}
|
||||
*/
|
||||
|
||||
schnorr.drbg = function drbg(msg, priv, data) {
|
||||
const pers = Buffer.allocUnsafe(48);
|
||||
|
||||
pers.fill(0);
|
||||
|
||||
if (data) {
|
||||
assert(data.length === 32);
|
||||
data.copy(pers, 0);
|
||||
}
|
||||
|
||||
schnorr.alg.copy(pers, 32);
|
||||
|
||||
return new HmacDRBG(priv, msg, pers);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate pub+priv nonce pair.
|
||||
* @param {Buffer} msg
|
||||
* @param {Buffer} priv
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
schnorr.generateNoncePair = function generateNoncePair(msg, priv, data) {
|
||||
const drbg = schnorr.drbg(msg, priv, data);
|
||||
const len = curve.n.byteLength();
|
||||
|
||||
let k;
|
||||
for (;;) {
|
||||
k = new BN(drbg.generate(len));
|
||||
|
||||
if (k.isZero())
|
||||
continue;
|
||||
|
||||
if (k.gte(curve.n))
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return Buffer.from(curve.g.mul(k).encode('array', true));
|
||||
};
|
||||
@ -1,269 +0,0 @@
|
||||
/*!
|
||||
* scrypt.js - scrypt for bcoin
|
||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*
|
||||
* Ported from:
|
||||
* https://github.com/Tarsnap/scrypt/blob/master/lib/crypto/crypto_scrypt-ref.c
|
||||
*
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* eslint camelcase: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto/scrypt
|
||||
*/
|
||||
|
||||
const pbkdf2 = require('./pbkdf2');
|
||||
const native = require('../native').binding;
|
||||
|
||||
/**
|
||||
* Javascript scrypt implementation. Scrypt is
|
||||
* used in bip38. Bcoin doesn't support bip38
|
||||
* yet, but here it is, just in case.
|
||||
* @alias module:crypto/scrypt.derive
|
||||
* @param {Buffer} passwd
|
||||
* @param {Buffer} salt
|
||||
* @param {Number} N
|
||||
* @param {Number} r
|
||||
* @param {Number} p
|
||||
* @param {Number} len
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
function derive(passwd, salt, N, r, p, len) {
|
||||
if (r * p >= (1 << 30))
|
||||
throw new Error('EFBIG');
|
||||
|
||||
if ((N & (N - 1)) !== 0 || N === 0)
|
||||
throw new Error('EINVAL');
|
||||
|
||||
if (N > 0xffffffff)
|
||||
throw new Error('EINVAL');
|
||||
|
||||
const XY = Buffer.allocUnsafe(256 * r);
|
||||
const V = Buffer.allocUnsafe(128 * r * N);
|
||||
|
||||
const B = pbkdf2.derive(passwd, salt, 1, p * 128 * r, 'sha256');
|
||||
|
||||
for (let i = 0; i < p; i++)
|
||||
smix(B, i * 128 * r, r, N, V, XY);
|
||||
|
||||
return pbkdf2.derive(passwd, B, 1, len, 'sha256');
|
||||
}
|
||||
|
||||
if (native)
|
||||
derive = native.scrypt;
|
||||
|
||||
/**
|
||||
* Asynchronous scrypt implementation.
|
||||
* @alias module:crypto/scrypt.deriveAsync
|
||||
* @function
|
||||
* @param {Buffer} passwd
|
||||
* @param {Buffer} salt
|
||||
* @param {Number} N
|
||||
* @param {Number} r
|
||||
* @param {Number} p
|
||||
* @param {Number} len
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
async function deriveAsync(passwd, salt, N, r, p, len) {
|
||||
if (r * p >= (1 << 30))
|
||||
throw new Error('EFBIG');
|
||||
|
||||
if ((N & (N - 1)) !== 0 || N === 0)
|
||||
throw new Error('EINVAL');
|
||||
|
||||
if (N > 0xffffffff)
|
||||
throw new Error('EINVAL');
|
||||
|
||||
const XY = Buffer.allocUnsafe(256 * r);
|
||||
const V = Buffer.allocUnsafe(128 * r * N);
|
||||
|
||||
const B = await pbkdf2.deriveAsync(passwd, salt, 1, p * 128 * r, 'sha256');
|
||||
|
||||
for (let i = 0; i < p; i++)
|
||||
await smixAsync(B, i * 128 * r, r, N, V, XY);
|
||||
|
||||
return await pbkdf2.deriveAsync(passwd, B, 1, len, 'sha256');
|
||||
}
|
||||
|
||||
if (native)
|
||||
deriveAsync = native.scryptAsync;
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function salsa20_8(B) {
|
||||
const B32 = new Uint32Array(16);
|
||||
const x = new Uint32Array(16);
|
||||
|
||||
for (let i = 0; i < 16; i++)
|
||||
B32[i] = B.readUInt32LE(i * 4, true);
|
||||
|
||||
for (let i = 0; i < 16; i++)
|
||||
x[i] = B32[i];
|
||||
|
||||
for (let i = 0; i < 8; i += 2) {
|
||||
x[4] ^= R(x[0] + x[12], 7);
|
||||
x[8] ^= R(x[4] + x[0], 9);
|
||||
x[12] ^= R(x[8] + x[4], 13);
|
||||
x[0] ^= R(x[12] + x[8], 18);
|
||||
|
||||
x[9] ^= R(x[5] + x[1], 7);
|
||||
x[13] ^= R(x[9] + x[5], 9);
|
||||
x[1] ^= R(x[13] + x[9], 13);
|
||||
x[5] ^= R(x[1] + x[13], 18);
|
||||
|
||||
x[14] ^= R(x[10] + x[6], 7);
|
||||
x[2] ^= R(x[14] + x[10], 9);
|
||||
x[6] ^= R(x[2] + x[14], 13);
|
||||
x[10] ^= R(x[6] + x[2], 18);
|
||||
|
||||
x[3] ^= R(x[15] + x[11], 7);
|
||||
x[7] ^= R(x[3] + x[15], 9);
|
||||
x[11] ^= R(x[7] + x[3], 13);
|
||||
x[15] ^= R(x[11] + x[7], 18);
|
||||
|
||||
x[1] ^= R(x[0] + x[3], 7);
|
||||
x[2] ^= R(x[1] + x[0], 9);
|
||||
x[3] ^= R(x[2] + x[1], 13);
|
||||
x[0] ^= R(x[3] + x[2], 18);
|
||||
|
||||
x[6] ^= R(x[5] + x[4], 7);
|
||||
x[7] ^= R(x[6] + x[5], 9);
|
||||
x[4] ^= R(x[7] + x[6], 13);
|
||||
x[5] ^= R(x[4] + x[7], 18);
|
||||
|
||||
x[11] ^= R(x[10] + x[9], 7);
|
||||
x[8] ^= R(x[11] + x[10], 9);
|
||||
x[9] ^= R(x[8] + x[11], 13);
|
||||
x[10] ^= R(x[9] + x[8], 18);
|
||||
|
||||
x[12] ^= R(x[15] + x[14], 7);
|
||||
x[13] ^= R(x[12] + x[15], 9);
|
||||
x[14] ^= R(x[13] + x[12], 13);
|
||||
x[15] ^= R(x[14] + x[13], 18);
|
||||
}
|
||||
|
||||
for (let i = 0; i < 16; i++)
|
||||
B32[i] += x[i];
|
||||
|
||||
for (let i = 0; i < 16; i++)
|
||||
B.writeUInt32LE(B32[i], 4 * i, true);
|
||||
}
|
||||
|
||||
function R(a, b) {
|
||||
return (a << b) | (a >>> (32 - b));
|
||||
}
|
||||
|
||||
function blockmix_salsa8(B, Y, Yo, r) {
|
||||
const X = Buffer.allocUnsafe(64);
|
||||
|
||||
blkcpy(X, B, 0, (2 * r - 1) * 64, 64);
|
||||
|
||||
for (let i = 0; i < 2 * r; i++) {
|
||||
blkxor(X, B, 0, i * 64, 64);
|
||||
salsa20_8(X);
|
||||
blkcpy(Y, X, Yo + i * 64, 0, 64);
|
||||
}
|
||||
|
||||
for (let i = 0; i < r; i++)
|
||||
blkcpy(B, Y, i * 64, Yo + (i * 2) * 64, 64);
|
||||
|
||||
for (let i = 0; i < r; i++)
|
||||
blkcpy(B, Y, (i + r) * 64, Yo + (i * 2 + 1) * 64, 64);
|
||||
}
|
||||
|
||||
function integerify(B, r) {
|
||||
return B.readUInt32LE((2 * r - 1) * 64, true);
|
||||
}
|
||||
|
||||
function smix(B, Bo, r, N, V, XY) {
|
||||
const X = XY;
|
||||
const Y = XY;
|
||||
|
||||
blkcpy(X, B, 0, Bo, 128 * r);
|
||||
|
||||
for (let i = 0; i < N; i++) {
|
||||
blkcpy(V, X, i * (128 * r), 0, 128 * r);
|
||||
blockmix_salsa8(X, Y, 128 * r, r);
|
||||
}
|
||||
|
||||
for (let i = 0; i < N; i++) {
|
||||
const j = integerify(X, r) & (N - 1);
|
||||
blkxor(X, V, 0, j * (128 * r), 128 * r);
|
||||
blockmix_salsa8(X, Y, 128 * r, r);
|
||||
}
|
||||
|
||||
blkcpy(B, X, Bo, 0, 128 * r);
|
||||
}
|
||||
|
||||
async function smixAsync(B, Bo, r, N, V, XY) {
|
||||
const X = XY;
|
||||
const Y = XY;
|
||||
|
||||
blkcpy(X, B, 0, Bo, 128 * r);
|
||||
|
||||
for (let i = 0; i < N; i++) {
|
||||
blkcpy(V, X, i * (128 * r), 0, 128 * r);
|
||||
blockmix_salsa8(X, Y, 128 * r, r);
|
||||
await wait();
|
||||
}
|
||||
|
||||
for (let i = 0; i < N; i++) {
|
||||
const j = integerify(X, r) & (N - 1);
|
||||
blkxor(X, V, 0, j * (128 * r), 128 * r);
|
||||
blockmix_salsa8(X, Y, 128 * r, r);
|
||||
await wait();
|
||||
}
|
||||
|
||||
blkcpy(B, X, Bo, 0, 128 * r);
|
||||
}
|
||||
|
||||
function blkcpy(dest, src, s1, s2, len) {
|
||||
src.copy(dest, s1, s2, s2 + len);
|
||||
}
|
||||
|
||||
function blkxor(dest, src, s1, s2, len) {
|
||||
for (let i = 0; i < len; i++)
|
||||
dest[s1 + i] ^= src[s2 + i];
|
||||
}
|
||||
|
||||
function wait() {
|
||||
return new Promise(r => setImmediate(r));
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
exports.derive = derive;
|
||||
exports.deriveAsync = deriveAsync;
|
||||
@ -1,345 +0,0 @@
|
||||
/*!
|
||||
* secp256k1-elliptic.js - wrapper for elliptic
|
||||
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const elliptic = require('elliptic');
|
||||
const secp256k1 = elliptic.ec('secp256k1');
|
||||
const Signature = require('elliptic/lib/elliptic/ec/signature');
|
||||
const BN = require('./bn');
|
||||
const curve = secp256k1.curve;
|
||||
|
||||
/**
|
||||
* @exports crypto/secp256k1-elliptic
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
const ec = exports;
|
||||
|
||||
/**
|
||||
* Whether we're using native bindings.
|
||||
* @const {Boolean}
|
||||
*/
|
||||
|
||||
ec.binding = false;
|
||||
|
||||
/**
|
||||
* Generate a private key.
|
||||
* @returns {Buffer} Private key.
|
||||
*/
|
||||
|
||||
ec.generatePrivateKey = function generatePrivateKey() {
|
||||
const key = secp256k1.genKeyPair();
|
||||
return key.getPrivate().toArrayLike(Buffer, 'be', 32);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a public key from a private key.
|
||||
* @param {Buffer} priv
|
||||
* @param {Boolean?} compress
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
ec.publicKeyCreate = function publicKeyCreate(priv, compress) {
|
||||
if (compress == null)
|
||||
compress = true;
|
||||
|
||||
assert(Buffer.isBuffer(priv));
|
||||
|
||||
const key = secp256k1.keyPair({ priv: priv });
|
||||
|
||||
return Buffer.from(key.getPublic(compress, 'array'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Compress or decompress public key.
|
||||
* @param {Buffer} pub
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
ec.publicKeyConvert = function publicKeyConvert(key, compress) {
|
||||
if (compress == null)
|
||||
compress = true;
|
||||
|
||||
const point = curve.decodePoint(key);
|
||||
|
||||
return Buffer.from(point.encode('array', compress));
|
||||
};
|
||||
|
||||
/**
|
||||
* ((tweak + key) % n)
|
||||
* @param {Buffer} privateKey
|
||||
* @param {Buffer} tweak
|
||||
* @returns {Buffer} privateKey
|
||||
*/
|
||||
|
||||
ec.privateKeyTweakAdd = function privateKeyTweakAdd(privateKey, tweak) {
|
||||
const key = new BN(tweak)
|
||||
.add(new BN(privateKey))
|
||||
.mod(curve.n)
|
||||
.toArrayLike(Buffer, 'be', 32);
|
||||
|
||||
// Only a 1 in 2^127 chance of happening.
|
||||
if (!ec.privateKeyVerify(key))
|
||||
throw new Error('Private key is invalid.');
|
||||
|
||||
return key;
|
||||
};
|
||||
|
||||
/**
|
||||
* ((g * tweak) + key)
|
||||
* @param {Buffer} publicKey
|
||||
* @param {Buffer} tweak
|
||||
* @returns {Buffer} publicKey
|
||||
*/
|
||||
|
||||
ec.publicKeyTweakAdd = function publicKeyTweakAdd(publicKey, tweak, compress) {
|
||||
if (compress == null)
|
||||
compress = true;
|
||||
|
||||
const key = curve.decodePoint(publicKey);
|
||||
const point = curve.g.mul(new BN(tweak)).add(key);
|
||||
const pub = Buffer.from(point.encode('array', compress));
|
||||
|
||||
if (!ec.publicKeyVerify(pub))
|
||||
throw new Error('Public key is invalid.');
|
||||
|
||||
return pub;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an ecdh.
|
||||
* @param {Buffer} pub
|
||||
* @param {Buffer} priv
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
ec.ecdh = function ecdh(pub, priv) {
|
||||
priv = secp256k1.keyPair({ priv: priv });
|
||||
pub = secp256k1.keyPair({ pub: pub });
|
||||
return priv.derive(pub.getPublic()).toArrayLike(Buffer, 'be', 32);
|
||||
};
|
||||
|
||||
/**
|
||||
* Recover a public key.
|
||||
* @param {Buffer} msg
|
||||
* @param {Buffer} sig
|
||||
* @param {Number?} j
|
||||
* @param {Boolean?} compress
|
||||
* @returns {Buffer[]|Buffer|null}
|
||||
*/
|
||||
|
||||
ec.recover = function recover(msg, sig, j, compress) {
|
||||
if (!j)
|
||||
j = 0;
|
||||
|
||||
if (compress == null)
|
||||
compress = true;
|
||||
|
||||
let point;
|
||||
try {
|
||||
point = secp256k1.recoverPubKey(msg, sig, j);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Buffer.from(point.encode('array', compress));
|
||||
};
|
||||
|
||||
/**
|
||||
* Verify a signature.
|
||||
* @param {Buffer} msg
|
||||
* @param {Buffer} sig - DER formatted.
|
||||
* @param {Buffer} key
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
ec.verify = function verify(msg, sig, key) {
|
||||
assert(Buffer.isBuffer(msg));
|
||||
assert(Buffer.isBuffer(sig));
|
||||
assert(Buffer.isBuffer(key));
|
||||
|
||||
if (sig.length === 0)
|
||||
return false;
|
||||
|
||||
if (key.length === 0)
|
||||
return false;
|
||||
|
||||
// Attempt to normalize the signature
|
||||
// length before passing to elliptic.
|
||||
// https://github.com/indutny/elliptic/issues/78
|
||||
sig = normalizeLength(sig);
|
||||
|
||||
try {
|
||||
return secp256k1.verify(msg, sig, key);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate a public key.
|
||||
* @param {Buffer} key
|
||||
* @returns {Boolean} True if buffer is a valid public key.
|
||||
*/
|
||||
|
||||
ec.publicKeyVerify = function publicKeyVerify(key) {
|
||||
try {
|
||||
const pub = secp256k1.keyPair({ pub: key });
|
||||
return pub.validate();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate a private key.
|
||||
* @param {Buffer} key
|
||||
* @returns {Boolean} True if buffer is a valid private key.
|
||||
*/
|
||||
|
||||
ec.privateKeyVerify = function privateKeyVerify(key) {
|
||||
if (key.length !== 32)
|
||||
return false;
|
||||
|
||||
key = new BN(key);
|
||||
|
||||
return !key.isZero() && key.lt(curve.n);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sign a message.
|
||||
* @param {Buffer} msg
|
||||
* @param {Buffer} key - Private key.
|
||||
* @returns {Buffer} DER-formatted signature.
|
||||
*/
|
||||
|
||||
ec.sign = function sign(msg, key) {
|
||||
assert(Buffer.isBuffer(msg));
|
||||
assert(Buffer.isBuffer(key));
|
||||
|
||||
// Sign message and ensure low S value
|
||||
const sig = secp256k1.sign(msg, key, { canonical: true });
|
||||
|
||||
// Convert to DER
|
||||
return Buffer.from(sig.toDER());
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert DER signature to R/S.
|
||||
* @param {Buffer} raw
|
||||
* @returns {Buffer} R/S-formatted signature.
|
||||
*/
|
||||
|
||||
ec.fromDER = function fromDER(raw) {
|
||||
assert(Buffer.isBuffer(raw));
|
||||
|
||||
const sig = new Signature(raw);
|
||||
const out = Buffer.allocUnsafe(64);
|
||||
|
||||
sig.r.toArrayLike(Buffer, 'be', 32).copy(out, 0);
|
||||
sig.s.toArrayLike(Buffer, 'be', 32).copy(out, 32);
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert R/S signature to DER.
|
||||
* @param {Buffer} sig
|
||||
* @returns {Buffer} DER-formatted signature.
|
||||
*/
|
||||
|
||||
ec.toDER = function toDER(raw) {
|
||||
assert(Buffer.isBuffer(raw));
|
||||
|
||||
const sig = new Signature({
|
||||
r: new BN(raw.slice(0, 32), 'be'),
|
||||
s: new BN(raw.slice(32, 64), 'be')
|
||||
});
|
||||
|
||||
return Buffer.from(sig.toDER());
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether a signature has a low S value.
|
||||
* @param {Buffer} sig
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
ec.isLowS = function isLowS(raw) {
|
||||
let sig;
|
||||
try {
|
||||
sig = new Signature(raw);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sig.s.isZero())
|
||||
return false;
|
||||
|
||||
// If S is greater than half the order,
|
||||
// it's too high.
|
||||
if (sig.s.gt(secp256k1.nh))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function normalizeLength(sig) {
|
||||
let data = sig;
|
||||
let pos = 0;
|
||||
let len;
|
||||
|
||||
if (data[pos++] !== 0x30)
|
||||
return sig;
|
||||
|
||||
[len, pos] = getLength(data, pos);
|
||||
|
||||
if (data.length > len + pos)
|
||||
data = data.slice(0, len + pos);
|
||||
|
||||
if (data[pos++] !== 0x02)
|
||||
return sig;
|
||||
|
||||
// R length.
|
||||
[len, pos] = getLength(data, pos);
|
||||
|
||||
pos += len;
|
||||
|
||||
if (data[pos++] !== 0x02)
|
||||
return sig;
|
||||
|
||||
// S length.
|
||||
[len, pos] = getLength(data, pos);
|
||||
|
||||
if (data.length > len + pos)
|
||||
data = data.slice(0, len + pos);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function getLength(buf, pos) {
|
||||
const initial = buf[pos++];
|
||||
|
||||
if (!(initial & 0x80))
|
||||
return [initial, pos];
|
||||
|
||||
const len = initial & 0xf;
|
||||
let val = 0;
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
val <<= 8;
|
||||
val |= buf[pos++];
|
||||
}
|
||||
|
||||
return [val, pos];
|
||||
}
|
||||
@ -1,257 +0,0 @@
|
||||
/*!
|
||||
* secp256k1-native.js - wrapper for secp256k1-node
|
||||
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const secp256k1 = require('secp256k1');
|
||||
const random = require('./random');
|
||||
|
||||
/**
|
||||
* @exports crypto/secp256k1
|
||||
*/
|
||||
|
||||
const ec = exports;
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
||||
const ZERO_S = Buffer.from(
|
||||
'0000000000000000000000000000000000000000000000000000000000000000',
|
||||
'hex'
|
||||
);
|
||||
|
||||
const HALF_ORDER = Buffer.from(
|
||||
'7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0',
|
||||
'hex');
|
||||
|
||||
/**
|
||||
* Whether we're using native bindings.
|
||||
* @const {Boolean}
|
||||
* @private
|
||||
*/
|
||||
|
||||
ec.binding = true;
|
||||
|
||||
/**
|
||||
* Generate a private key.
|
||||
* @returns {Buffer} Private key.
|
||||
*/
|
||||
|
||||
ec.generatePrivateKey = function generatePrivateKey() {
|
||||
let priv;
|
||||
|
||||
do {
|
||||
priv = random.randomBytes(32);
|
||||
} while (!secp256k1.privateKeyVerify(priv));
|
||||
|
||||
return priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a public key from a private key.
|
||||
* @param {Buffer} priv
|
||||
* @param {Boolean?} compress
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
ec.publicKeyCreate = function publicKeyCreate(priv, compress) {
|
||||
assert(Buffer.isBuffer(priv));
|
||||
return secp256k1.publicKeyCreate(priv, compress);
|
||||
};
|
||||
|
||||
/**
|
||||
* Compress or decompress public key.
|
||||
* @param {Buffer} pub
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
ec.publicKeyConvert = function publicKeyConvert(key, compress) {
|
||||
return secp256k1.publicKeyConvert(key, compress);
|
||||
};
|
||||
|
||||
/**
|
||||
* ((tweak + key) % n)
|
||||
* @param {Buffer} privateKey
|
||||
* @param {Buffer} tweak
|
||||
* @returns {Buffer} privateKey
|
||||
*/
|
||||
|
||||
ec.privateKeyTweakAdd = function privateKeyTweakAdd(privateKey, tweak) {
|
||||
return secp256k1.privateKeyTweakAdd(privateKey, tweak);
|
||||
};
|
||||
|
||||
/**
|
||||
* ((g * tweak) + key)
|
||||
* @param {Buffer} publicKey
|
||||
* @param {Buffer} tweak
|
||||
* @returns {Buffer} publicKey
|
||||
*/
|
||||
|
||||
ec.publicKeyTweakAdd = function publicKeyTweakAdd(publicKey, tweak, compress) {
|
||||
return secp256k1.publicKeyTweakAdd(publicKey, tweak, compress);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an ecdh.
|
||||
* @param {Buffer} pub
|
||||
* @param {Buffer} priv
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
ec.ecdh = function ecdh(pub, priv) {
|
||||
const point = secp256k1.ecdhUnsafe(pub, priv, true);
|
||||
return point.slice(1, 33);
|
||||
};
|
||||
|
||||
/**
|
||||
* Recover a public key.
|
||||
* @param {Buffer} msg
|
||||
* @param {Buffer} sig
|
||||
* @param {Number?} j
|
||||
* @param {Boolean?} compress
|
||||
* @returns {Buffer[]|Buffer|null}
|
||||
*/
|
||||
|
||||
ec.recover = function recover(msg, sig, j, compress) {
|
||||
if (!j)
|
||||
j = 0;
|
||||
|
||||
try {
|
||||
sig = secp256k1.signatureImport(sig);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let key;
|
||||
try {
|
||||
key = secp256k1.recover(msg, sig, j, compress);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return key;
|
||||
};
|
||||
|
||||
/**
|
||||
* Verify a signature.
|
||||
* @param {Buffer} msg
|
||||
* @param {Buffer} sig - DER formatted.
|
||||
* @param {Buffer} key
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
ec.verify = function verify(msg, sig, key) {
|
||||
assert(Buffer.isBuffer(msg));
|
||||
assert(Buffer.isBuffer(sig));
|
||||
assert(Buffer.isBuffer(key));
|
||||
|
||||
if (sig.length === 0)
|
||||
return false;
|
||||
|
||||
if (key.length === 0)
|
||||
return false;
|
||||
|
||||
try {
|
||||
sig = secp256k1.signatureImportLax(sig);
|
||||
sig = secp256k1.signatureNormalize(sig);
|
||||
return secp256k1.verify(msg, sig, key);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate a public key.
|
||||
* @param {Buffer} key
|
||||
* @returns {Boolean} True if buffer is a valid public key.
|
||||
*/
|
||||
|
||||
ec.publicKeyVerify = function publicKeyVerify(key) {
|
||||
return secp256k1.publicKeyVerify(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate a private key.
|
||||
* @param {Buffer} key
|
||||
* @returns {Boolean} True if buffer is a valid private key.
|
||||
*/
|
||||
|
||||
ec.privateKeyVerify = function privateKeyVerify(key) {
|
||||
return secp256k1.privateKeyVerify(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sign a message.
|
||||
* @param {Buffer} msg
|
||||
* @param {Buffer} key - Private key.
|
||||
* @returns {Buffer} DER-formatted signature.
|
||||
*/
|
||||
|
||||
ec.sign = function sign(msg, key) {
|
||||
assert(Buffer.isBuffer(msg));
|
||||
assert(Buffer.isBuffer(key));
|
||||
|
||||
// Sign message
|
||||
let sig = secp256k1.sign(msg, key);
|
||||
|
||||
// Ensure low S value
|
||||
sig = secp256k1.signatureNormalize(sig.signature);
|
||||
|
||||
// Convert to DER
|
||||
return secp256k1.signatureExport(sig);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert DER signature to R/S.
|
||||
* @param {Buffer} sig
|
||||
* @returns {Buffer} R/S-formatted signature.
|
||||
*/
|
||||
|
||||
ec.fromDER = function fromDER(sig) {
|
||||
assert(Buffer.isBuffer(sig));
|
||||
return secp256k1.signatureImport(sig);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert R/S signature to DER.
|
||||
* @param {Buffer} sig
|
||||
* @returns {Buffer} DER-formatted signature.
|
||||
*/
|
||||
|
||||
ec.toDER = function toDER(sig) {
|
||||
assert(Buffer.isBuffer(sig));
|
||||
return secp256k1.signatureExport(sig);
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether a signature has a low S value.
|
||||
* @param {Buffer} sig
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
ec.isLowS = function isLowS(sig) {
|
||||
let s;
|
||||
|
||||
try {
|
||||
const rs = secp256k1.signatureImport(sig);
|
||||
s = rs.slice(32, 64);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s.equals(ZERO_S))
|
||||
return false;
|
||||
|
||||
// If S is greater than half the order,
|
||||
// it's too high.
|
||||
if (s.compare(HALF_ORDER) > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
@ -1,21 +0,0 @@
|
||||
/*!
|
||||
* secp256k1.js - ecdsa wrapper for secp256k1 and elliptic
|
||||
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
let native;
|
||||
|
||||
if (Number(process.env.BCOIN_NO_SECP256K1) !== 1) {
|
||||
try {
|
||||
native = require('secp256k1/bindings');
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = native
|
||||
? require('./secp256k1-native')
|
||||
: require('./secp256k1-browser');
|
||||
@ -1,399 +0,0 @@
|
||||
/*!
|
||||
* sha256.js - SHA256 implementation for bcoin
|
||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
* Parts of this software based on hash.js.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto/sha256
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
||||
const DESC = Buffer.allocUnsafe(8);
|
||||
const BUFFER64 = Buffer.allocUnsafe(64);
|
||||
const PADDING = Buffer.allocUnsafe(64);
|
||||
|
||||
const K = [
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
];
|
||||
|
||||
PADDING.fill(0);
|
||||
PADDING[0] = 0x80;
|
||||
|
||||
/**
|
||||
* SHA256
|
||||
* @alias module:crypto/sha256.SHA256
|
||||
* @constructor
|
||||
* @property {Number[]} s
|
||||
* @property {Number[]} w
|
||||
* @property {Buffer} block
|
||||
* @property {Number} bytes
|
||||
*/
|
||||
|
||||
function SHA256() {
|
||||
if (!(this instanceof SHA256))
|
||||
return new SHA256();
|
||||
|
||||
this.s = new Array(8);
|
||||
this.w = new Array(64);
|
||||
this.block = Buffer.allocUnsafe(64);
|
||||
this.bytes = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize SHA256 context.
|
||||
*/
|
||||
|
||||
SHA256.prototype.init = function init() {
|
||||
this.s[0] = 0x6a09e667;
|
||||
this.s[1] = 0xbb67ae85;
|
||||
this.s[2] = 0x3c6ef372;
|
||||
this.s[3] = 0xa54ff53a;
|
||||
this.s[4] = 0x510e527f;
|
||||
this.s[5] = 0x9b05688c;
|
||||
this.s[6] = 0x1f83d9ab;
|
||||
this.s[7] = 0x5be0cd19;
|
||||
this.bytes = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Update SHA256 context.
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
SHA256.prototype.update = function update(data) {
|
||||
return this._update(data, data.length);
|
||||
};
|
||||
|
||||
/**
|
||||
* Finalize SHA256 context.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
SHA256.prototype.finish = function finish() {
|
||||
return this._finish(Buffer.allocUnsafe(32));
|
||||
};
|
||||
|
||||
/**
|
||||
* Update SHA256 context.
|
||||
* @private
|
||||
* @param {Buffer} data
|
||||
* @param {Number} len
|
||||
*/
|
||||
|
||||
SHA256.prototype._update = function _update(data, len) {
|
||||
let size = this.bytes & 0x3f;
|
||||
let pos = 0;
|
||||
|
||||
this.bytes += len;
|
||||
|
||||
if (size > 0) {
|
||||
let want = 64 - size;
|
||||
|
||||
if (want > len)
|
||||
want = len;
|
||||
|
||||
for (let i = 0; i < want; i++)
|
||||
this.block[size + i] = data[i];
|
||||
|
||||
size += want;
|
||||
len -= want;
|
||||
pos += want;
|
||||
|
||||
if (size < 64)
|
||||
return;
|
||||
|
||||
this.transform(this.block, 0);
|
||||
}
|
||||
|
||||
while (len >= 64) {
|
||||
this.transform(data, pos);
|
||||
pos += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
for (let i = 0; i < len; i++)
|
||||
this.block[i] = data[pos + i];
|
||||
};
|
||||
|
||||
/**
|
||||
* Finalize SHA256 context.
|
||||
* @private
|
||||
* @param {Buffer} out
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
SHA256.prototype._finish = function _finish(out) {
|
||||
writeU32(DESC, this.bytes >>> 29, 0);
|
||||
writeU32(DESC, this.bytes << 3, 4);
|
||||
|
||||
this._update(PADDING, 1 + ((119 - (this.bytes % 64)) % 64));
|
||||
this._update(DESC, 8);
|
||||
|
||||
for (let i = 0; i < 8; i++) {
|
||||
writeU32(out, this.s[i], i * 4);
|
||||
this.s[i] = 0;
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transform SHA256 block.
|
||||
* @param {Buffer} chunk
|
||||
* @param {Number} pos
|
||||
*/
|
||||
|
||||
SHA256.prototype.transform = function transform(chunk, pos) {
|
||||
const w = this.w;
|
||||
let a = this.s[0];
|
||||
let b = this.s[1];
|
||||
let c = this.s[2];
|
||||
let d = this.s[3];
|
||||
let e = this.s[4];
|
||||
let f = this.s[5];
|
||||
let g = this.s[6];
|
||||
let h = this.s[7];
|
||||
let i = 0;
|
||||
|
||||
for (; i < 16; i++)
|
||||
w[i] = readU32(chunk, pos + i * 4);
|
||||
|
||||
for (; i < 64; i++)
|
||||
w[i] = sigma1(w[i - 2]) + w[i - 7] + sigma0(w[i - 15]) + w[i - 16];
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
let t1 = h + Sigma1(e);
|
||||
t1 += Ch(e, f, g);
|
||||
t1 += K[i] + w[i];
|
||||
|
||||
let t2 = Sigma0(a);
|
||||
t2 += Maj(a, b, c);
|
||||
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
|
||||
e = d + t1;
|
||||
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
|
||||
a = t1 + t2;
|
||||
}
|
||||
|
||||
this.s[0] += a;
|
||||
this.s[1] += b;
|
||||
this.s[2] += c;
|
||||
this.s[3] += d;
|
||||
this.s[4] += e;
|
||||
this.s[5] += f;
|
||||
this.s[6] += g;
|
||||
this.s[7] += h;
|
||||
|
||||
this.s[0] >>>= 0;
|
||||
this.s[1] >>>= 0;
|
||||
this.s[2] >>>= 0;
|
||||
this.s[3] >>>= 0;
|
||||
this.s[4] >>>= 0;
|
||||
this.s[5] >>>= 0;
|
||||
this.s[6] >>>= 0;
|
||||
this.s[7] >>>= 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* SHA256Hmac
|
||||
* @alias module:crypto/sha256.SHA256Hmac
|
||||
* @constructor
|
||||
* @property {SHA256} inner
|
||||
* @property {SHA256} outer
|
||||
*/
|
||||
|
||||
function SHA256Hmac() {
|
||||
if (!(this instanceof SHA256Hmac))
|
||||
return new SHA256Hmac();
|
||||
|
||||
this.inner = new SHA256();
|
||||
this.outer = new SHA256();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize HMAC context.
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
SHA256Hmac.prototype.init = function init(data) {
|
||||
const key = BUFFER64;
|
||||
|
||||
if (data.length > 64) {
|
||||
this.inner.init();
|
||||
this.inner.update(data);
|
||||
this.inner._finish(key);
|
||||
key.fill(0, 32, 64);
|
||||
} else {
|
||||
data.copy(key, 0);
|
||||
key.fill(0, data.length, 64);
|
||||
}
|
||||
|
||||
for (let i = 0; i < key.length; i++)
|
||||
key[i] ^= 0x36;
|
||||
|
||||
this.inner.init();
|
||||
this.inner.update(key);
|
||||
|
||||
for (let i = 0; i < key.length; i++)
|
||||
key[i] ^= 0x6a;
|
||||
|
||||
this.outer.init();
|
||||
this.outer.update(key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update HMAC context.
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
SHA256Hmac.prototype.update = function update(data) {
|
||||
this.inner.update(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Finalize HMAC context.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
SHA256Hmac.prototype.finish = function finish() {
|
||||
this.outer.update(this.inner.finish());
|
||||
return this.outer.finish();
|
||||
};
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
* @see https://github.com/bitcoin-core/secp256k1/blob/master/src/hash_impl.h
|
||||
*/
|
||||
|
||||
function Sigma0(x) {
|
||||
return (x >>> 2 | x << 30) ^ (x >>> 13 | x << 19) ^ (x >>> 22 | x << 10);
|
||||
}
|
||||
|
||||
function Sigma1(x) {
|
||||
return (x >>> 6 | x << 26) ^ (x >>> 11 | x << 21) ^ (x >>> 25 | x << 7);
|
||||
}
|
||||
|
||||
function sigma0(x) {
|
||||
return (x >>> 7 | x << 25) ^ (x >>> 18 | x << 14) ^ (x >>> 3);
|
||||
}
|
||||
|
||||
function sigma1(x) {
|
||||
return (x >>> 17 | x << 15) ^ (x >>> 19 | x << 13) ^ (x >>> 10);
|
||||
}
|
||||
|
||||
function Ch(x, y, z) {
|
||||
return z ^ (x & (y ^ z));
|
||||
}
|
||||
|
||||
function Maj(x, y, z) {
|
||||
return (x & y) | (z & (x | y));
|
||||
}
|
||||
|
||||
function writeU32(buf, value, offset) {
|
||||
buf[offset] = value >>> 24;
|
||||
buf[offset + 1] = (value >> 16) & 0xff;
|
||||
buf[offset + 2] = (value >> 8) & 0xff;
|
||||
buf[offset + 3] = value & 0xff;
|
||||
}
|
||||
|
||||
function readU32(buf, offset) {
|
||||
return ((buf[offset] & 0xff) * 0x1000000)
|
||||
+ ((buf[offset + 1] & 0xff) << 16)
|
||||
| ((buf[offset + 2] & 0xff) << 8)
|
||||
| (buf[offset + 3] & 0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
* Context Helpers
|
||||
*/
|
||||
|
||||
const ctx = new SHA256();
|
||||
const mctx = new SHA256Hmac();
|
||||
|
||||
/**
|
||||
* Hash buffer with sha256.
|
||||
* @alias module:crypto/sha256.sha256
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
function sha256(data) {
|
||||
ctx.init();
|
||||
ctx.update(data);
|
||||
return ctx.finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash buffer with double sha256.
|
||||
* @alias module:crypto/sha256.hash256
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
function hash256(data) {
|
||||
const out = Buffer.allocUnsafe(32);
|
||||
ctx.init();
|
||||
ctx.update(data);
|
||||
ctx._finish(out);
|
||||
ctx.init();
|
||||
ctx.update(out);
|
||||
ctx._finish(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a sha256 HMAC from buffer and key.
|
||||
* @alias module:crypto/sha256.hmac
|
||||
* @param {Buffer} data
|
||||
* @param {Buffer} key
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
function hmac(data, key) {
|
||||
mctx.init(key);
|
||||
mctx.update(data);
|
||||
return mctx.finish();
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
exports = SHA256;
|
||||
exports.SHA256 = SHA256;
|
||||
exports.SHA256Hmac = SHA256Hmac;
|
||||
exports.digest = sha256;
|
||||
exports.hmac = hmac;
|
||||
exports.hash256 = hash256;
|
||||
|
||||
module.exports = exports;
|
||||
@ -1,304 +0,0 @@
|
||||
/*!
|
||||
* siphash.js - siphash for bcoin
|
||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*
|
||||
* Ported from:
|
||||
* https://github.com/bitcoin/bitcoin/blob/master/src/hash.cpp
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @module crypto/siphash
|
||||
*/
|
||||
|
||||
const native = require('../native').binding;
|
||||
|
||||
/**
|
||||
* Javascript siphash 2-4 implementation.
|
||||
* @private
|
||||
* @param {Buffer} data
|
||||
* @param {Buffer} key - 128 bit key.
|
||||
* @param {Number} shift
|
||||
* @returns {Array} [hi, lo]
|
||||
*/
|
||||
|
||||
function _siphash(data, key, shift) {
|
||||
const blocks = Math.floor(data.length / 8);
|
||||
const c0 = U64(0x736f6d65, 0x70736575);
|
||||
const c1 = U64(0x646f7261, 0x6e646f6d);
|
||||
const c2 = U64(0x6c796765, 0x6e657261);
|
||||
const c3 = U64(0x74656462, 0x79746573);
|
||||
const f0 = U64(blocks << (shift - 32), 0);
|
||||
const f1 = U64(0, 0xff);
|
||||
const k0 = U64.fromRaw(key, 0);
|
||||
const k1 = U64.fromRaw(key, 8);
|
||||
|
||||
// Init
|
||||
const v0 = c0.ixor(k0);
|
||||
const v1 = c1.ixor(k1);
|
||||
const v2 = c2.ixor(k0);
|
||||
const v3 = c3.ixor(k1);
|
||||
|
||||
// Blocks
|
||||
let p = 0;
|
||||
for (let i = 0; i < blocks; i++) {
|
||||
const d = U64.fromRaw(data, p);
|
||||
p += 8;
|
||||
v3.ixor(d);
|
||||
sipround(v0, v1, v2, v3);
|
||||
sipround(v0, v1, v2, v3);
|
||||
v0.ixor(d);
|
||||
}
|
||||
|
||||
switch (data.length & 7) {
|
||||
case 7:
|
||||
f0.hi |= data[p + 6] << 16;
|
||||
case 6:
|
||||
f0.hi |= data[p + 5] << 8;
|
||||
case 5:
|
||||
f0.hi |= data[p + 4];
|
||||
case 4:
|
||||
f0.lo |= data[p + 3] << 24;
|
||||
case 3:
|
||||
f0.lo |= data[p + 2] << 16;
|
||||
case 2:
|
||||
f0.lo |= data[p + 1] << 8;
|
||||
case 1:
|
||||
f0.lo |= data[p];
|
||||
}
|
||||
|
||||
// Finalization
|
||||
v3.ixor(f0);
|
||||
sipround(v0, v1, v2, v3);
|
||||
sipround(v0, v1, v2, v3);
|
||||
v0.ixor(f0);
|
||||
v2.ixor(f1);
|
||||
sipround(v0, v1, v2, v3);
|
||||
sipround(v0, v1, v2, v3);
|
||||
sipround(v0, v1, v2, v3);
|
||||
sipround(v0, v1, v2, v3);
|
||||
v0.ixor(v1);
|
||||
v0.ixor(v2);
|
||||
v0.ixor(v3);
|
||||
|
||||
return [v0.hi, v0.lo];
|
||||
}
|
||||
|
||||
/**
|
||||
* Javascript siphash 2-4 implementation (64 bit ints).
|
||||
* @private
|
||||
* @param {Number} hi
|
||||
* @param {Number} lo
|
||||
* @param {Buffer} key - 128 bit key.
|
||||
* @returns {Array} [hi, lo]
|
||||
*/
|
||||
|
||||
function _siphash64(hi, lo, key) {
|
||||
const c0 = U64(0x736f6d65, 0x70736575);
|
||||
const c1 = U64(0x646f7261, 0x6e646f6d);
|
||||
const c2 = U64(0x6c796765, 0x6e657261);
|
||||
const c3 = U64(0x74656462, 0x79746573);
|
||||
const f0 = U64(hi, lo);
|
||||
const f1 = U64(0, 0xff);
|
||||
const k0 = U64.fromRaw(key, 0);
|
||||
const k1 = U64.fromRaw(key, 8);
|
||||
|
||||
// Init
|
||||
const v0 = c0.ixor(k0);
|
||||
const v1 = c1.ixor(k1);
|
||||
const v2 = c2.ixor(k0);
|
||||
const v3 = c3.ixor(k1);
|
||||
|
||||
// Finalization
|
||||
v3.ixor(f0);
|
||||
sipround(v0, v1, v2, v3);
|
||||
sipround(v0, v1, v2, v3);
|
||||
v0.ixor(f0);
|
||||
v2.ixor(f1);
|
||||
sipround(v0, v1, v2, v3);
|
||||
sipround(v0, v1, v2, v3);
|
||||
sipround(v0, v1, v2, v3);
|
||||
sipround(v0, v1, v2, v3);
|
||||
v0.ixor(v1);
|
||||
v0.ixor(v2);
|
||||
v0.ixor(v3);
|
||||
|
||||
return [v0.hi, v0.lo];
|
||||
}
|
||||
|
||||
/**
|
||||
* Javascript siphash 2-4 implementation (shift=56).
|
||||
* @alias module:crypto/siphash.siphash
|
||||
* @param {Buffer} data
|
||||
* @param {Buffer} key - 128 bit key.
|
||||
* @returns {Array} [hi, lo]
|
||||
*/
|
||||
|
||||
function siphash(data, key) {
|
||||
return _siphash(data, key, 56);
|
||||
}
|
||||
|
||||
/**
|
||||
* Javascript siphash 2-4 implementation (shift=59).
|
||||
* @alias module:crypto/siphash.siphash256
|
||||
* @param {Buffer} data
|
||||
* @param {Buffer} key - 128 bit key.
|
||||
* @returns {Array} [hi, lo]
|
||||
*/
|
||||
|
||||
function siphash256(data, key) {
|
||||
return _siphash(data, key, 59);
|
||||
}
|
||||
|
||||
/**
|
||||
* Javascript siphash 2-4 implementation (32 bit ints).
|
||||
* @alias module:crypto/siphash.siphash32
|
||||
* @param {Number} num
|
||||
* @param {Buffer} key - 128 bit key.
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
function siphash32(num, key) {
|
||||
return _siphash64(0, num, key)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Javascript siphash 2-4 implementation (64 bit ints).
|
||||
* @alias module:crypto/siphash.siphash64
|
||||
* @param {Number} hi
|
||||
* @param {Number} lo
|
||||
* @param {Buffer} key - 128 bit key.
|
||||
* @returns {Array} [hi, lo]
|
||||
*/
|
||||
|
||||
function siphash64(hi, lo, key) {
|
||||
return _siphash64(hi, lo, key);
|
||||
}
|
||||
|
||||
if (native) {
|
||||
siphash = native.siphash;
|
||||
siphash256 = native.siphash256;
|
||||
siphash32 = native.siphash32;
|
||||
siphash64 = native.siphash64;
|
||||
}
|
||||
|
||||
/*
|
||||
* U64
|
||||
* @constructor
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
function U64(hi, lo) {
|
||||
if (!(this instanceof U64))
|
||||
return new U64(hi, lo);
|
||||
|
||||
this.hi = hi | 0;
|
||||
this.lo = lo | 0;
|
||||
}
|
||||
|
||||
U64.prototype.iadd = function iadd(b) {
|
||||
const a = this;
|
||||
|
||||
// Credit to @indutny for this method.
|
||||
const lo = (a.lo + b.lo) | 0;
|
||||
|
||||
const s = lo >> 31;
|
||||
const as = a.lo >> 31;
|
||||
const bs = b.lo >> 31;
|
||||
|
||||
const c = ((as & bs) | (~s & (as ^ bs))) & 1;
|
||||
|
||||
const hi = ((a.hi + b.hi) | 0) + c;
|
||||
|
||||
a.hi = hi | 0;
|
||||
a.lo = lo;
|
||||
|
||||
return a;
|
||||
};
|
||||
|
||||
U64.prototype.ixor = function ixor(b) {
|
||||
this.hi ^= b.hi;
|
||||
this.lo ^= b.lo;
|
||||
return this;
|
||||
};
|
||||
|
||||
U64.prototype.irotl = function irotl(bits) {
|
||||
let ahi = this.hi;
|
||||
let alo = this.lo;
|
||||
let bhi = this.hi;
|
||||
let blo = this.lo;
|
||||
|
||||
// a = x << b
|
||||
if (bits < 32) {
|
||||
ahi <<= bits;
|
||||
ahi |= alo >>> (32 - bits);
|
||||
alo <<= bits;
|
||||
} else {
|
||||
ahi = alo << (bits - 32);
|
||||
alo = 0;
|
||||
}
|
||||
|
||||
bits = 64 - bits;
|
||||
|
||||
// b = x >> (64 - b)
|
||||
if (bits < 32) {
|
||||
blo >>>= bits;
|
||||
blo |= bhi << (32 - bits);
|
||||
bhi >>>= bits;
|
||||
} else {
|
||||
blo = bhi >>> (bits - 32);
|
||||
bhi = 0;
|
||||
}
|
||||
|
||||
// a | b
|
||||
this.hi = ahi | bhi;
|
||||
this.lo = alo | blo;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
U64.fromRaw = function fromRaw(data, off) {
|
||||
const lo = data.readUInt32LE(off, true);
|
||||
const hi = data.readUInt32LE(off + 4, true);
|
||||
return new U64(hi, lo);
|
||||
};
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function sipround(v0, v1, v2, v3) {
|
||||
v0.iadd(v1);
|
||||
v1.irotl(13);
|
||||
v1.ixor(v0);
|
||||
|
||||
v0.irotl(32);
|
||||
|
||||
v2.iadd(v3);
|
||||
v3.irotl(16);
|
||||
v3.ixor(v2);
|
||||
|
||||
v0.iadd(v3);
|
||||
v3.irotl(21);
|
||||
v3.ixor(v0);
|
||||
|
||||
v2.iadd(v1);
|
||||
v1.irotl(17);
|
||||
v1.ixor(v2);
|
||||
|
||||
v2.irotl(32);
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
exports = siphash;
|
||||
exports.siphash = siphash;
|
||||
exports.siphash256 = siphash256;
|
||||
exports.siphash32 = siphash32;
|
||||
exports.siphash64 = siphash64;
|
||||
|
||||
module.exports = exports;
|
||||
@ -8,10 +8,11 @@
|
||||
|
||||
const assert = require('assert');
|
||||
const util = require('../utils/util');
|
||||
const digest = require('../crypto/digest');
|
||||
const cleanse = require('../crypto/cleanse');
|
||||
const random = require('../crypto/random');
|
||||
const pbkdf2 = require('../crypto/pbkdf2');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const cleanse = require('bcrypto/lib/cleanse');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const pbkdf2 = require('bcrypto/lib/pbkdf2');
|
||||
const sha512 = require('bcrypto/lib/sha512');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
const BufferReader = require('../utils/reader');
|
||||
const encoding = require('../utils/encoding');
|
||||
@ -154,10 +155,10 @@ Mnemonic.prototype.toSeed = function toSeed(passphrase) {
|
||||
const phrase = nfkd(this.getPhrase());
|
||||
const passwd = nfkd('mnemonic' + passphrase);
|
||||
|
||||
return pbkdf2.derive(
|
||||
return pbkdf2.derive(sha512,
|
||||
Buffer.from(phrase, 'utf8'),
|
||||
Buffer.from(passwd, 'utf8'),
|
||||
2048, 64, 'sha512');
|
||||
2048, 64);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -8,10 +8,10 @@
|
||||
|
||||
const assert = require('assert');
|
||||
const util = require('../utils/util');
|
||||
const digest = require('../crypto/digest');
|
||||
const cleanse = require('../crypto/cleanse');
|
||||
const random = require('../crypto/random');
|
||||
const secp256k1 = require('../crypto/secp256k1');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const cleanse = require('bcrypto/lib/cleanse');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
const Network = require('../protocol/network');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
const BufferReader = require('../utils/reader');
|
||||
|
||||
@ -8,9 +8,9 @@
|
||||
|
||||
const assert = require('assert');
|
||||
const util = require('../utils/util');
|
||||
const digest = require('../crypto/digest');
|
||||
const cleanse = require('../crypto/cleanse');
|
||||
const secp256k1 = require('../crypto/secp256k1');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const cleanse = require('bcrypto/lib/cleanse');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
const Network = require('../protocol/network');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
const BufferReader = require('../utils/reader');
|
||||
|
||||
@ -10,10 +10,10 @@ const assert = require('assert');
|
||||
const bweb = require('bweb');
|
||||
const util = require('../utils/util');
|
||||
const co = require('../utils/co');
|
||||
const digest = require('../crypto/digest');
|
||||
const ccmp = require('../crypto/ccmp');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const ccmp = require('bcrypto/lib/ccmp');
|
||||
const common = require('../blockchain/common');
|
||||
const secp256k1 = require('../crypto/secp256k1');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
const Amount = require('../btc/amount');
|
||||
const NetAddress = require('../primitives/netaddress');
|
||||
const Script = require('../script/script');
|
||||
|
||||
@ -15,9 +15,9 @@ const base58 = require('../utils/base58');
|
||||
const Bloom = require('../utils/bloom');
|
||||
const TX = require('../primitives/tx');
|
||||
const Outpoint = require('../primitives/outpoint');
|
||||
const digest = require('../crypto/digest');
|
||||
const random = require('../crypto/random');
|
||||
const ccmp = require('../crypto/ccmp');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const ccmp = require('bcrypto/lib/ccmp');
|
||||
const Network = require('../protocol/network');
|
||||
const Validator = require('../utils/validator');
|
||||
const pkg = require('../pkg');
|
||||
|
||||
@ -13,7 +13,7 @@ const common = require('../blockchain/common');
|
||||
const consensus = require('../protocol/consensus');
|
||||
const policy = require('../protocol/policy');
|
||||
const util = require('../utils/util');
|
||||
const random = require('../crypto/random');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const {VerifyError} = require('../protocol/errors');
|
||||
const RollingFilter = require('../utils/rollingfilter');
|
||||
const Address = require('../primitives/address');
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
const assert = require('assert');
|
||||
const consensus = require('../protocol/consensus');
|
||||
const BN = require('../crypto/bn');
|
||||
const BN = require('bcrypto/lib/bn');
|
||||
|
||||
/**
|
||||
* @exports mining/common
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const digest = require('../crypto/digest');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
|
||||
/**
|
||||
* Hash until the nonce overflows.
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
|
||||
const assert = require('assert');
|
||||
const util = require('../utils/util');
|
||||
const digest = require('../crypto/digest');
|
||||
const merkle = require('../crypto/merkle');
|
||||
const hash256 = require('bcrypto/lib/hash256');
|
||||
const merkle = require('bcrypto/lib/merkle');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
const Address = require('../primitives/address');
|
||||
const TX = require('../primitives/tx');
|
||||
@ -178,11 +178,11 @@ BlockTemplate.prototype.getWitnessHash = function getWitnessHash() {
|
||||
for (const item of this.items)
|
||||
leaves.push(item.tx.witnessHash());
|
||||
|
||||
const [root, malleated] = merkle.createRoot(leaves);
|
||||
const [root, malleated] = merkle.createRoot(hash256, leaves);
|
||||
|
||||
assert(!malleated);
|
||||
|
||||
return digest.root256(root, nonce);
|
||||
return hash256.root(root, nonce);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -381,7 +381,7 @@ BlockTemplate.prototype.getRawCoinbase = function getRawCoinbase(nonce1, nonce2)
|
||||
|
||||
BlockTemplate.prototype.getRoot = function getRoot(nonce1, nonce2) {
|
||||
const raw = this.getRawCoinbase(nonce1, nonce2);
|
||||
const hash = digest.hash256(raw);
|
||||
const hash = hash256.digest(raw);
|
||||
return this.tree.withFirst(hash);
|
||||
};
|
||||
|
||||
@ -418,7 +418,7 @@ BlockTemplate.prototype.getHeader = function getHeader(root, time, nonce) {
|
||||
BlockTemplate.prototype.getProof = function getProof(nonce1, nonce2, time, nonce) {
|
||||
const root = this.getRoot(nonce1, nonce2);
|
||||
const data = this.getHeader(root, time, nonce);
|
||||
const hash = digest.hash256(data);
|
||||
const hash = hash256.digest(data);
|
||||
return new BlockProof(hash, root, nonce1, nonce2, time, nonce);
|
||||
};
|
||||
|
||||
@ -685,7 +685,7 @@ function MerkleTree() {
|
||||
|
||||
MerkleTree.prototype.withFirst = function withFirst(hash) {
|
||||
for (const step of this.steps)
|
||||
hash = digest.root256(hash, step);
|
||||
hash = hash256.root(hash, step);
|
||||
return hash;
|
||||
};
|
||||
|
||||
@ -742,7 +742,7 @@ MerkleTree.prototype.fromLeaves = function fromLeaves(leaves) {
|
||||
leaves.push(leaves[len - 1]);
|
||||
|
||||
for (let i = 2; i < len; i += 2) {
|
||||
const hash = digest.root256(leaves[i], leaves[i + 1]);
|
||||
const hash = hash256.root(leaves[i], leaves[i + 1]);
|
||||
hashes.push(hash);
|
||||
}
|
||||
|
||||
|
||||
@ -12,11 +12,11 @@ const assert = require('assert');
|
||||
const path = require('path');
|
||||
const EventEmitter = require('events');
|
||||
const co = require('../utils/co');
|
||||
const digest = require('../crypto/digest');
|
||||
const random = require('../crypto/random');
|
||||
const ccmp = require('../crypto/ccmp');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const ccmp = require('bcrypto/lib/ccmp');
|
||||
const packets = require('./packets');
|
||||
const secp256k1 = require('../crypto/secp256k1');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
const base58 = require('../utils/base58');
|
||||
const encoding = require('../utils/encoding');
|
||||
|
||||
@ -16,12 +16,13 @@ const assert = require('assert');
|
||||
const EventEmitter = require('events');
|
||||
const util = require('../utils/util');
|
||||
const co = require('../utils/co');
|
||||
const digest = require('../crypto/digest');
|
||||
const ChaCha20 = require('../crypto/chacha20');
|
||||
const Poly1305 = require('../crypto/poly1305');
|
||||
const AEAD = require('../crypto/aead');
|
||||
const hkdf = require('../crypto/hkdf');
|
||||
const secp256k1 = require('../crypto/secp256k1');
|
||||
const hash256 = require('bcrypto/lib/hash256');
|
||||
const sha256 = require('bcrypto/lib/sha256');
|
||||
const ChaCha20 = require('bcrypto/lib/chacha20');
|
||||
const Poly1305 = require('bcrypto/lib/poly1305');
|
||||
const AEAD = require('bcrypto/lib/aead');
|
||||
const hkdf = require('bcrypto/lib/hkdf');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
const packets = require('./packets');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
const BufferReader = require('../utils/reader');
|
||||
@ -104,11 +105,11 @@ BIP151Stream.prototype.init = function init(publicKey) {
|
||||
bw.writeU8(this.cipher);
|
||||
|
||||
const data = bw.render();
|
||||
const prk = hkdf.extract(data, HKDF_SALT, 'sha256');
|
||||
const prk = hkdf.extract(sha256, data, HKDF_SALT);
|
||||
|
||||
this.k1 = hkdf.expand(prk, INFO_KEY1, 32, 'sha256');
|
||||
this.k2 = hkdf.expand(prk, INFO_KEY2, 32, 'sha256');
|
||||
this.sid = hkdf.expand(prk, INFO_SID, 32, 'sha256');
|
||||
this.k1 = hkdf.expand(sha256, prk, INFO_KEY1, 32);
|
||||
this.k2 = hkdf.expand(sha256, prk, INFO_KEY2, 32);
|
||||
this.sid = hkdf.expand(sha256, prk, INFO_SID, 32);
|
||||
|
||||
this.seq = 0;
|
||||
|
||||
@ -151,8 +152,8 @@ BIP151Stream.prototype.rekey = function rekey(k1, k2) {
|
||||
assert(this.sid, 'Cannot rekey before initialization.');
|
||||
|
||||
if (!k1) {
|
||||
this.k1 = digest.root256(this.sid, this.k1);
|
||||
this.k2 = digest.root256(this.sid, this.k2);
|
||||
this.k1 = hash256.root(this.sid, this.k1);
|
||||
this.k2 = hash256.root(this.sid, this.k2);
|
||||
} else {
|
||||
this.k1 = k1;
|
||||
this.k2 = k2;
|
||||
@ -263,8 +264,8 @@ BIP151Stream.prototype.auth = function auth(data) {
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
BIP151Stream.prototype.finish = function finish() {
|
||||
this.tag = this.aead.finish();
|
||||
BIP151Stream.prototype.final = function final() {
|
||||
this.tag = this.aead.final();
|
||||
return this.tag;
|
||||
};
|
||||
|
||||
@ -608,7 +609,7 @@ BIP151.prototype.packet = function packet(cmd, body) {
|
||||
|
||||
this.output.encryptSize(msg);
|
||||
this.output.encrypt(payload);
|
||||
this.output.finish().copy(msg, 4 + payloadSize);
|
||||
this.output.final().copy(msg, 4 + payloadSize);
|
||||
this.output.sequence();
|
||||
|
||||
return msg;
|
||||
@ -719,7 +720,7 @@ BIP151.prototype.parse = function parse(data) {
|
||||
// This ensures the cipher state isn't altered
|
||||
// if the payload integrity has been compromised.
|
||||
this.input.auth(payload);
|
||||
this.input.finish();
|
||||
this.input.final();
|
||||
|
||||
if (!this.input.verify(tag)) {
|
||||
this.input.sequence();
|
||||
|
||||
@ -16,8 +16,8 @@ const BufferReader = require('../utils/reader');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
const encoding = require('../utils/encoding');
|
||||
const consensus = require('../protocol/consensus');
|
||||
const digest = require('../crypto/digest');
|
||||
const siphash256 = require('../crypto/siphash').siphash256;
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const siphash256 = require('bcrypto/lib/siphash').siphash256;
|
||||
const AbstractBlock = require('../primitives/abstractblock');
|
||||
const TX = require('../primitives/tx');
|
||||
const Headers = require('../primitives/headers');
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
const assert = require('assert');
|
||||
const Network = require('../protocol/network');
|
||||
const digest = require('../crypto/digest');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
|
||||
/**
|
||||
* Protocol packet framer
|
||||
|
||||
@ -13,7 +13,7 @@ const assert = require('assert');
|
||||
const EventEmitter = require('events');
|
||||
const Network = require('../protocol/network');
|
||||
const util = require('../utils/util');
|
||||
const digest = require('../crypto/digest');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const common = require('./common');
|
||||
const packets = require('./packets');
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ const BIP151 = require('./bip151');
|
||||
const BIP152 = require('./bip152');
|
||||
const Bloom = require('../utils/bloom');
|
||||
const RollingFilter = require('../utils/rollingfilter');
|
||||
const secp256k1 = require('../crypto/secp256k1');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
const Lock = require('../utils/lock');
|
||||
const Network = require('../protocol/network');
|
||||
const Peer = require('./peer');
|
||||
|
||||
@ -10,7 +10,7 @@ const assert = require('assert');
|
||||
const EventEmitter = require('events');
|
||||
const bsock = require('bsock');
|
||||
const util = require('../utils/util');
|
||||
const digest = require('../crypto/digest');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const BufferWriter = require('../utils/writer');
|
||||
|
||||
function ProxySocket(uri) {
|
||||
|
||||
@ -13,7 +13,7 @@ const util = require('../utils/util');
|
||||
const Network = require('../protocol/network');
|
||||
const Logger = require('./logger');
|
||||
const WorkerPool = require('../workers/workerpool');
|
||||
const secp256k1 = require('../crypto/secp256k1');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
const native = require('../native');
|
||||
const Config = require('./config');
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
const assert = require('assert');
|
||||
const util = require('../utils/util');
|
||||
const digest = require('../crypto/digest');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const BufferReader = require('../utils/reader');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
const InvItem = require('./invitem');
|
||||
|
||||
@ -11,7 +11,7 @@ const assert = require('assert');
|
||||
const Network = require('../protocol/network');
|
||||
const encoding = require('../utils/encoding');
|
||||
const util = require('../utils/util');
|
||||
const digest = require('../crypto/digest');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const BufferReader = require('../utils/reader');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
const base58 = require('../utils/base58');
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
const assert = require('assert');
|
||||
const util = require('../utils/util');
|
||||
const encoding = require('../utils/encoding');
|
||||
const digest = require('../crypto/digest');
|
||||
const merkle = require('../crypto/merkle');
|
||||
const hash256 = require('bcrypto/lib/hash256');
|
||||
const merkle = require('bcrypto/lib/merkle');
|
||||
const consensus = require('../protocol/consensus');
|
||||
const AbstractBlock = require('./abstractblock');
|
||||
const BufferReader = require('../utils/reader');
|
||||
@ -280,7 +280,7 @@ Block.prototype.createMerkleRoot = function createMerkleRoot(enc) {
|
||||
for (const tx of this.txs)
|
||||
leaves.push(tx.hash());
|
||||
|
||||
const [root, malleated] = merkle.createRoot(leaves);
|
||||
const [root, malleated] = merkle.createRoot(hash256, leaves);
|
||||
|
||||
if (malleated)
|
||||
return null;
|
||||
@ -317,12 +317,12 @@ Block.prototype.createCommitmentHash = function createCommitmentHash(enc) {
|
||||
leaves.push(tx.witnessHash());
|
||||
}
|
||||
|
||||
const [root] = merkle.createRoot(leaves);
|
||||
const [root] = merkle.createRoot(hash256, leaves);
|
||||
|
||||
// Note: malleation check ignored here.
|
||||
// assert(!malleated);
|
||||
|
||||
const hash = digest.root256(root, nonce);
|
||||
const hash = hash256.root(root, nonce);
|
||||
|
||||
return enc === 'hex'
|
||||
? hash.toString('hex')
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
const assert = require('assert');
|
||||
const encoding = require('../utils/encoding');
|
||||
const digest = require('../crypto/digest');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const Network = require('../protocol/network');
|
||||
const BufferReader = require('../utils/reader');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
@ -17,7 +17,7 @@ const base58 = require('../utils/base58');
|
||||
const Script = require('../script/script');
|
||||
const Address = require('./address');
|
||||
const Output = require('./output');
|
||||
const secp256k1 = require('../crypto/secp256k1');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
|
||||
/**
|
||||
* Represents a key ring which amounts to an address.
|
||||
|
||||
@ -12,7 +12,7 @@ const util = require('../utils/util');
|
||||
const BufferReader = require('../utils/reader');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
const encoding = require('../utils/encoding');
|
||||
const digest = require('../crypto/digest');
|
||||
const hash256 = require('bcrypto/lib/hash256');
|
||||
const consensus = require('../protocol/consensus');
|
||||
const AbstractBlock = require('./abstractblock');
|
||||
const Headers = require('./headers');
|
||||
@ -238,7 +238,7 @@ MerkleBlock.prototype.extractTree = function extractTree() {
|
||||
right = left;
|
||||
}
|
||||
|
||||
return digest.root256(left, right);
|
||||
return hash256.root(left, right);
|
||||
};
|
||||
|
||||
if (totalTX === 0)
|
||||
@ -571,7 +571,7 @@ MerkleBlock.fromMatches = function fromMatches(block, matches) {
|
||||
else
|
||||
right = left;
|
||||
|
||||
return digest.root256(left, right);
|
||||
return hash256.root(left, right);
|
||||
};
|
||||
|
||||
const traverse = (height, pos, leaves, matches) => {
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
const assert = require('assert');
|
||||
const util = require('../utils/util');
|
||||
const encoding = require('../utils/encoding');
|
||||
const digest = require('../crypto/digest');
|
||||
const secp256k1 = require('../crypto/secp256k1');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
const Amount = require('../btc/amount');
|
||||
const Network = require('../protocol/network');
|
||||
const Script = require('../script/script');
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
const assert = require('assert');
|
||||
const BN = require('../crypto/bn');
|
||||
const BN = require('bcrypto/lib/bn');
|
||||
|
||||
/**
|
||||
* One bitcoin in satoshis.
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
* @module protocol/networks
|
||||
*/
|
||||
|
||||
const BN = require('../crypto/bn');
|
||||
const BN = require('bcrypto/lib/bn');
|
||||
|
||||
const network = exports;
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
const assert = require('assert');
|
||||
const util = require('../utils/util');
|
||||
const secp256k1 = require('../crypto/secp256k1');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
const ScriptNum = require('./scriptnum');
|
||||
|
||||
/**
|
||||
|
||||
@ -11,8 +11,8 @@ const assert = require('assert');
|
||||
const consensus = require('../protocol/consensus');
|
||||
const policy = require('../protocol/policy');
|
||||
const util = require('../utils/util');
|
||||
const digest = require('../crypto/digest');
|
||||
const merkle = require('../crypto/merkle');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const merkle = require('bcrypto/lib/merkle');
|
||||
const BufferWriter = require('../utils/writer');
|
||||
const BufferReader = require('../utils/reader');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
@ -23,7 +23,7 @@ const ScriptError = require('./scripterror');
|
||||
const ScriptNum = require('./scriptnum');
|
||||
const common = require('./common');
|
||||
const encoding = require('../utils/encoding');
|
||||
const secp256k1 = require('../crypto/secp256k1');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
const Address = require('../primitives/address');
|
||||
const opcodes = common.opcodes;
|
||||
const scriptTypes = common.types;
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
const assert = require('assert');
|
||||
const util = require('../utils/util');
|
||||
const secp256k1 = require('../crypto/secp256k1');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
|
||||
/**
|
||||
* Signature cache.
|
||||
|
||||
@ -1,548 +0,0 @@
|
||||
/*!
|
||||
* asn1.js - asn1 parsing for bcoin
|
||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*
|
||||
* Parts of this software are based on asn1.js.
|
||||
* https://github.com/indutny/asn1.js
|
||||
*
|
||||
* Copyright Fedor Indutny, 2013.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const BufferReader = require('./reader');
|
||||
|
||||
/**
|
||||
* @exports utils/asn1
|
||||
*/
|
||||
|
||||
const ASN1 = exports;
|
||||
|
||||
/**
|
||||
* Read next tag.
|
||||
* @param {BufferReader} br
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ASN1.readTag = function readTag(br) {
|
||||
let type = br.readU8();
|
||||
const primitive = (type & 0x20) === 0;
|
||||
|
||||
if ((type & 0x1f) === 0x1f) {
|
||||
let oct = type;
|
||||
type = 0;
|
||||
while ((oct & 0x80) === 0x80) {
|
||||
oct = br.readU8();
|
||||
type <<= 7;
|
||||
type |= oct & 0x7f;
|
||||
}
|
||||
} else {
|
||||
type &= 0x1f;
|
||||
}
|
||||
|
||||
return {
|
||||
type: type,
|
||||
primitive: primitive,
|
||||
size: ASN1.readSize(br, primitive)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Read tag size.
|
||||
* @param {BufferReader} br
|
||||
* @param {Boolean} primitive
|
||||
* @returns {Number}
|
||||
* @throws on indefinite size
|
||||
*/
|
||||
|
||||
ASN1.readSize = function readSize(br, primitive) {
|
||||
let size = br.readU8();
|
||||
|
||||
// Indefinite form
|
||||
if (!primitive && size === 0x80)
|
||||
throw new Error('Indefinite size.');
|
||||
|
||||
// Definite form
|
||||
if ((size & 0x80) === 0) {
|
||||
// Short form
|
||||
return size;
|
||||
}
|
||||
|
||||
// Long form
|
||||
const bytes = size & 0x7f;
|
||||
|
||||
if (bytes > 3)
|
||||
throw new Error('Length octet is too long.');
|
||||
|
||||
size = 0;
|
||||
for (let i = 0; i < bytes; i++) {
|
||||
size <<= 8;
|
||||
size |= br.readU8();
|
||||
}
|
||||
|
||||
return size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read implicit SEQ.
|
||||
* @param {BufferReader} br
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
ASN1.readSeq = function readSeq(br) {
|
||||
const tag = ASN1.implicit(br, 0x10);
|
||||
return br.readBytes(tag.size);
|
||||
};
|
||||
|
||||
/**
|
||||
* Read next tag and assert implicit.
|
||||
* @param {BufferReader} br
|
||||
* @param {Number} type
|
||||
* @returns {Object}
|
||||
* @throws on unexpected tag
|
||||
*/
|
||||
|
||||
ASN1.implicit = function implicit(br, type) {
|
||||
const tag = ASN1.readTag(br);
|
||||
|
||||
if (tag.type !== type)
|
||||
throw new Error(`Unexpected tag: ${tag.type}.`);
|
||||
|
||||
return tag;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read implicit tag.
|
||||
* @param {BufferReader} br
|
||||
* @param {Number} type
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
ASN1.explicit = function explicit(br, type) {
|
||||
const offset = br.offset;
|
||||
const tag = ASN1.readTag(br);
|
||||
|
||||
if (tag.type !== type) {
|
||||
br.offset = offset;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read next implicit SEQ and return a new reader.
|
||||
* @param {BufferReader} br
|
||||
* @returns {BufferReader}
|
||||
*/
|
||||
|
||||
ASN1.seq = function seq(br) {
|
||||
return new BufferReader(ASN1.readSeq(br), true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Read implicit int.
|
||||
* @param {BufferReader} br
|
||||
* @param {Boolean?} cast
|
||||
* @returns {Buffer|Number}
|
||||
*/
|
||||
|
||||
ASN1.readInt = function readInt(br, cast) {
|
||||
const tag = ASN1.implicit(br, 0x02);
|
||||
const num = br.readBytes(tag.size);
|
||||
|
||||
if (cast)
|
||||
return num.readUIntBE(0, num.length);
|
||||
|
||||
return num;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read explicit int.
|
||||
* @param {BufferReader} br
|
||||
* @param {Number} type
|
||||
* @param {Boolean?} readNum
|
||||
* @returns {Buffer|Number} `-1` on not present.
|
||||
*/
|
||||
|
||||
ASN1.readExplicitInt = function readExplicitInt(br, type, readNum) {
|
||||
if (!ASN1.explicit(br, type))
|
||||
return -1;
|
||||
|
||||
return ASN1.readInt(br, readNum);
|
||||
};
|
||||
|
||||
/**
|
||||
* Read and align an implicit bitstr.
|
||||
* @param {BufferReader} br
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
ASN1.readBitstr = function readBitstr(br) {
|
||||
const tag = ASN1.implicit(br, 0x03);
|
||||
const str = br.readBytes(tag.size);
|
||||
return ASN1.alignBitstr(str);
|
||||
};
|
||||
|
||||
/**
|
||||
* Read an implicit string (any type).
|
||||
* @param {BufferReader} br
|
||||
* @returns {String}
|
||||
*/
|
||||
|
||||
ASN1.readString = function readString(br) {
|
||||
const tag = ASN1.readTag(br);
|
||||
|
||||
switch (tag.type) {
|
||||
case 0x03: { // bitstr
|
||||
const str = br.readBytes(tag.size);
|
||||
return ASN1.alignBitstr(str).toString('utf8');
|
||||
}
|
||||
// Note:
|
||||
// Fuck all these.
|
||||
case 0x04: // octstr
|
||||
case 0x12: // numstr
|
||||
case 0x13: // prinstr
|
||||
case 0x14: // t61str
|
||||
case 0x15: // videostr
|
||||
case 0x16: // ia5str
|
||||
case 0x19: // graphstr
|
||||
case 0x0c: // utf8str
|
||||
case 0x1a: // iso646str
|
||||
case 0x1b: // genstr
|
||||
case 0x1c: // unistr
|
||||
case 0x1d: // charstr
|
||||
case 0x1e: { // bmpstr
|
||||
return br.readString('utf8', tag.size);
|
||||
}
|
||||
default: {
|
||||
throw new Error(`Unexpected tag: ${tag.type}.`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Align a bitstr.
|
||||
* @param {Buffer} data
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
ASN1.alignBitstr = function alignBitstr(data) {
|
||||
const padding = data[0];
|
||||
const bits = (data.length - 1) * 8 - padding;
|
||||
const buf = data.slice(1);
|
||||
const shift = 8 - (bits % 8);
|
||||
|
||||
if (shift === 8 || buf.length === 0)
|
||||
return buf;
|
||||
|
||||
const out = Buffer.allocUnsafe(buf.length);
|
||||
out[0] = buf[0] >>> shift;
|
||||
|
||||
for (let i = 1; i < buf.length; i++) {
|
||||
out[i] = buf[i - 1] << (8 - shift);
|
||||
out[i] |= buf[i] >>> shift;
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read an entire certificate.
|
||||
* @param {BufferReader} br
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ASN1.readCert = function readCert(br) {
|
||||
const buf = br;
|
||||
|
||||
buf.start();
|
||||
|
||||
br = ASN1.seq(buf);
|
||||
|
||||
return {
|
||||
tbs: ASN1.readTBS(br),
|
||||
sigAlg: ASN1.readAlgIdent(br),
|
||||
sig: ASN1.readBitstr(br),
|
||||
raw: buf.endData(true)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Read only the TBS certificate.
|
||||
* @param {BufferReader} br
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ASN1.readTBS = function readTBS(br) {
|
||||
const buf = br;
|
||||
|
||||
buf.start();
|
||||
|
||||
br = ASN1.seq(buf);
|
||||
|
||||
return {
|
||||
version: ASN1.readExplicitInt(br, 0x00, true),
|
||||
serial: ASN1.readInt(br),
|
||||
sig: ASN1.readAlgIdent(br),
|
||||
issuer: ASN1.readName(br),
|
||||
validity: ASN1.readValidity(br),
|
||||
subject: ASN1.readName(br),
|
||||
pubkey: ASN1.readPubkey(br),
|
||||
raw: buf.endData(true)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Read an implicit pubkey.
|
||||
* @param {BufferReader} br
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ASN1.readPubkey = function readPubkey(br) {
|
||||
br = ASN1.seq(br);
|
||||
return {
|
||||
alg: ASN1.readAlgIdent(br),
|
||||
pubkey: ASN1.readBitstr(br)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Read implicit name.
|
||||
* @param {BufferReader} br
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
|
||||
ASN1.readName = function readName(br) {
|
||||
const values = [];
|
||||
|
||||
br = ASN1.seq(br);
|
||||
|
||||
while (br.left()) {
|
||||
ASN1.implicit(br, 0x11); // set
|
||||
ASN1.implicit(br, 0x10); // seq
|
||||
values.push({
|
||||
type: ASN1.readOID(br),
|
||||
value: ASN1.readString(br)
|
||||
});
|
||||
}
|
||||
|
||||
return values;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read implicit validity timerange.
|
||||
* @param {BufferReader} br
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ASN1.readValidity = function readValidity(br) {
|
||||
br = ASN1.seq(br);
|
||||
return {
|
||||
notBefore: ASN1.readTime(br),
|
||||
notAfter: ASN1.readTime(br)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Read implicit timestamp.
|
||||
* @param {BufferReader} br
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
ASN1.readTime = function readTime(br) {
|
||||
const tag = ASN1.readTag(br);
|
||||
const str = br.readString('ascii', tag.size);
|
||||
let year, mon, day, hour, min, sec;
|
||||
|
||||
switch (tag.type) {
|
||||
case 0x17: // utctime
|
||||
year = str.slice(0, 2) | 0;
|
||||
mon = str.slice(2, 4) | 0;
|
||||
day = str.slice(4, 6) | 0;
|
||||
hour = str.slice(6, 8) | 0;
|
||||
min = str.slice(8, 10) | 0;
|
||||
sec = str.slice(10, 12) | 0;
|
||||
if (year < 70)
|
||||
year = 2000 + year;
|
||||
else
|
||||
year = 1900 + year;
|
||||
break;
|
||||
case 0x18: // gentime
|
||||
year = str.slice(0, 4) | 0;
|
||||
mon = str.slice(4, 6) | 0;
|
||||
day = str.slice(6, 8) | 0;
|
||||
hour = str.slice(8, 10) | 0;
|
||||
min = str.slice(10, 12) | 0;
|
||||
sec = str.slice(12, 14) | 0;
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unexpected tag: ${tag.type}.`);
|
||||
}
|
||||
|
||||
return Date.UTC(year, mon - 1, day, hour, min, sec, 0) / 1000;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read and format OID to string.
|
||||
* @param {BufferReader} br
|
||||
* @returns {String}
|
||||
*/
|
||||
|
||||
ASN1.readOID = function readOID(br) {
|
||||
const tag = ASN1.implicit(br, 0x06);
|
||||
const data = br.readBytes(tag.size);
|
||||
return ASN1.formatOID(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Format an OID buffer to a string.
|
||||
* @param {Buffer} data
|
||||
* @returns {String}
|
||||
*/
|
||||
|
||||
ASN1.formatOID = function formatOID(data) {
|
||||
const br = new BufferReader(data);
|
||||
const ids = [];
|
||||
let ident = 0;
|
||||
let subident = 0;
|
||||
|
||||
while (br.left()) {
|
||||
subident = br.readU8();
|
||||
ident <<= 7;
|
||||
ident |= subident & 0x7f;
|
||||
if ((subident & 0x80) === 0) {
|
||||
ids.push(ident);
|
||||
ident = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (subident & 0x80)
|
||||
ids.push(ident);
|
||||
|
||||
const first = (ids[0] / 40) | 0;
|
||||
const second = ids[0] % 40;
|
||||
const result = [first, second].concat(ids.slice(1));
|
||||
|
||||
return result.join('.');
|
||||
};
|
||||
|
||||
/**
|
||||
* Read algorithm identifier.
|
||||
* @param {BufferReader} br
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ASN1.readAlgIdent = function readAlgIdent(br) {
|
||||
let params = null;
|
||||
|
||||
br = ASN1.seq(br);
|
||||
|
||||
const alg = ASN1.readOID(br);
|
||||
|
||||
if (br.left() > 0) {
|
||||
const tag = ASN1.readTag(br);
|
||||
params = br.readBytes(tag.size);
|
||||
if (params.length === 0)
|
||||
params = null;
|
||||
}
|
||||
|
||||
return {
|
||||
alg: alg,
|
||||
params: params
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Read RSA public key.
|
||||
* @param {BufferReader} br
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ASN1.readRSAPublic = function readRSAPublic(br) {
|
||||
br = ASN1.seq(br);
|
||||
return {
|
||||
modulus: ASN1.readInt(br),
|
||||
publicExponent: ASN1.readInt(br)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Read RSA private key.
|
||||
* @param {BufferReader} br
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ASN1.readRSAPrivate = function readRSAPrivate(br) {
|
||||
br = ASN1.seq(br);
|
||||
return {
|
||||
version: ASN1.readInt(br, true),
|
||||
modulus: ASN1.readInt(br),
|
||||
publicExponent: ASN1.readInt(br),
|
||||
privateExponent: ASN1.readInt(br),
|
||||
prime1: ASN1.readInt(br),
|
||||
prime2: ASN1.readInt(br),
|
||||
exponent1: ASN1.readInt(br),
|
||||
exponent2: ASN1.readInt(br),
|
||||
coefficient: ASN1.readInt(br)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Read RSA public key from buffer.
|
||||
* @param {Buffer} data
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ASN1.parseRSAPublic = function parseRSAPublic(data) {
|
||||
return ASN1.readRSAPublic(new BufferReader(data, true));
|
||||
};
|
||||
|
||||
/**
|
||||
* Read RSA private key from buffer.
|
||||
* @param {Buffer} data
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ASN1.parseRSAPrivate = function parseRSAPrivate(data) {
|
||||
return ASN1.readRSAPrivate(new BufferReader(data, true));
|
||||
};
|
||||
|
||||
/**
|
||||
* Read certificate from buffer.
|
||||
* @param {Buffer} data
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ASN1.parseCert = function parseCert(data) {
|
||||
return ASN1.readCert(new BufferReader(data, true));
|
||||
};
|
||||
|
||||
/**
|
||||
* Read TBS certificate from buffer.
|
||||
* @param {Buffer} data
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ASN1.parseTBS = function parseTBS(data) {
|
||||
return ASN1.readTBS(new BufferReader(data, true));
|
||||
};
|
||||
@ -345,13 +345,13 @@ AsyncEmitter.prototype.fire = async function fire(type) {
|
||||
|
||||
AsyncEmitter.prototype.tryFire = async function tryFire(type) {
|
||||
try {
|
||||
await this.emit.apply(this, arguments);
|
||||
await this.fire.apply(this, arguments);
|
||||
} catch (e) {
|
||||
if (type === 'error')
|
||||
return;
|
||||
|
||||
try {
|
||||
await this.emit('error', e);
|
||||
await this.fire('error', e);
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
|
||||
@ -8,8 +8,8 @@
|
||||
|
||||
const assert = require('assert');
|
||||
const {U64} = require('./int64');
|
||||
const digest = require('../crypto/digest');
|
||||
const siphash = require('../crypto/siphash');
|
||||
const hash256 = require('bcrypto/lib/hash256');
|
||||
const siphash = require('bcrypto/lib/siphash');
|
||||
const DUMMY = Buffer.alloc(0);
|
||||
const EOF = new U64(-1);
|
||||
|
||||
@ -27,12 +27,12 @@ function GCSFilter() {
|
||||
}
|
||||
|
||||
GCSFilter.prototype.hash = function hash(enc) {
|
||||
const h = digest.hash256(this.data);
|
||||
const h = hash256.digest(this.data);
|
||||
return enc === 'hex' ? h.toString('hex') : h;
|
||||
};
|
||||
|
||||
GCSFilter.prototype.header = function header(prev) {
|
||||
return digest.root256(this.hash(), prev);
|
||||
return hash256.root(this.hash(), prev);
|
||||
};
|
||||
|
||||
GCSFilter.prototype.match = function match(key, data) {
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
* @module utils
|
||||
*/
|
||||
|
||||
exports.ASN1 = require('./asn1');
|
||||
// exports.AsyncEmitter = require('./asyncemitter');
|
||||
exports.AsyncObject = require('./asyncobject');
|
||||
exports.base32 = require('./base32');
|
||||
@ -31,7 +30,6 @@ exports.LRU = require('./lru');
|
||||
exports.MappedLock = require('./mappedlock');
|
||||
exports.murmur3 = require('./murmur3');
|
||||
exports.nfkd = require('./nfkd');
|
||||
exports.PEM = require('./pem');
|
||||
exports.ProtoWriter = require('./protowriter');
|
||||
exports.ProtoReader = require('./protoreader');
|
||||
exports.RBT = require('./rbt');
|
||||
|
||||
148
lib/utils/pem.js
148
lib/utils/pem.js
@ -1,148 +0,0 @@
|
||||
/*!
|
||||
* pem.js - pem parsing for bcoin
|
||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
/**
|
||||
* @exports utils/pem
|
||||
*/
|
||||
|
||||
const PEM = exports;
|
||||
|
||||
/**
|
||||
* Parse PEM into separated chunks.
|
||||
* @param {String} pem
|
||||
* @returns {Object[]}
|
||||
* @throws on parse error
|
||||
*/
|
||||
|
||||
PEM.parse = function parse(pem) {
|
||||
const chunks = [];
|
||||
let chunk = '';
|
||||
let tag;
|
||||
|
||||
while (pem.length) {
|
||||
let m;
|
||||
|
||||
m = /^-----BEGIN ([^\-]+)-----/.exec(pem);
|
||||
if (m) {
|
||||
pem = pem.substring(m[0].length);
|
||||
tag = m[1];
|
||||
continue;
|
||||
}
|
||||
|
||||
m = /^-----END ([^\-]+)-----/.exec(pem);
|
||||
if (m) {
|
||||
pem = pem.substring(m[0].length);
|
||||
|
||||
assert(tag === m[1], 'Tag mismatch.');
|
||||
|
||||
const type = tag.split(' ')[0].toLowerCase();
|
||||
const data = Buffer.from(chunk, 'base64');
|
||||
|
||||
chunks.push({
|
||||
tag: tag,
|
||||
type: type,
|
||||
data: data
|
||||
});
|
||||
|
||||
chunk = '';
|
||||
tag = null;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
m = /^[a-zA-Z0-9\+=\/]+/.exec(pem);
|
||||
if (m) {
|
||||
pem = pem.substring(m[0].length);
|
||||
chunk += m[0];
|
||||
continue;
|
||||
}
|
||||
|
||||
m = /^\s+/.exec(pem);
|
||||
if (m) {
|
||||
pem = pem.substring(m[0].length);
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new Error('PEM parse error.');
|
||||
}
|
||||
|
||||
assert(chunks.length !== 0, 'PEM parse error.');
|
||||
assert(!tag, 'Un-ended tag.');
|
||||
assert(chunk.length === 0, 'Trailing data.');
|
||||
|
||||
return chunks;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode PEM into a manageable format.
|
||||
* @param {String} pem
|
||||
* @returns {Object}
|
||||
* @throws on parse error
|
||||
*/
|
||||
|
||||
PEM.decode = function decode(pem) {
|
||||
const chunks = PEM.parse(pem);
|
||||
const body = chunks[0];
|
||||
const extra = chunks[1];
|
||||
|
||||
let params = null;
|
||||
|
||||
if (extra) {
|
||||
if (extra.tag.indexOf('PARAMETERS') !== -1)
|
||||
params = extra.data;
|
||||
}
|
||||
|
||||
let alg = null;
|
||||
|
||||
switch (body.type) {
|
||||
case 'dsa':
|
||||
alg = 'dsa';
|
||||
break;
|
||||
case 'rsa':
|
||||
alg = 'rsa';
|
||||
break;
|
||||
case 'ec':
|
||||
alg = 'ecdsa';
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
type: body.type,
|
||||
alg: alg,
|
||||
data: body.data,
|
||||
params: params
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Encode DER to PEM.
|
||||
* @param {Buffer} der
|
||||
* @param {String} type - e.g. "ec".
|
||||
* @param {String?} suffix - e.g. "public key".
|
||||
* @returns {String}
|
||||
*/
|
||||
|
||||
PEM.encode = function encode(der, type, suffix) {
|
||||
let pem = '';
|
||||
|
||||
if (suffix)
|
||||
type += ' ' + suffix;
|
||||
|
||||
type = type.toUpperCase();
|
||||
der = der.toString('base64');
|
||||
|
||||
for (let i = 0; i < der.length; i += 64)
|
||||
pem += der.slice(i, i + 64) + '\n';
|
||||
|
||||
return ''
|
||||
+ `-----BEGIN ${type}-----\n`
|
||||
+ pem
|
||||
+ `-----END ${type}-----\n`;
|
||||
};
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
const {NodeClient} = require('bclient');
|
||||
const TX = require('../primitives/tx');
|
||||
const digest = require('../crypto/digest');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const util = require('../utils/util');
|
||||
|
||||
class WalletClient extends NodeClient {
|
||||
|
||||
@ -15,9 +15,9 @@ const base58 = require('../utils/base58');
|
||||
const MTX = require('../primitives/mtx');
|
||||
const Outpoint = require('../primitives/outpoint');
|
||||
const Script = require('../script/script');
|
||||
const digest = require('../crypto/digest');
|
||||
const random = require('../crypto/random');
|
||||
const ccmp = require('../crypto/ccmp');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const ccmp = require('bcrypto/lib/ccmp');
|
||||
const Network = require('../protocol/network');
|
||||
const Validator = require('../utils/validator');
|
||||
const Address = require('../primitives/address');
|
||||
|
||||
@ -10,11 +10,12 @@ const assert = require('assert');
|
||||
const Network = require('../protocol/network');
|
||||
const util = require('../utils/util');
|
||||
const Lock = require('../utils/lock');
|
||||
const random = require('../crypto/random');
|
||||
const cleanse = require('../crypto/cleanse');
|
||||
const aes = require('../crypto/aes');
|
||||
const pbkdf2 = require('../crypto/pbkdf2');
|
||||
const scrypt = require('../crypto/scrypt');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const cleanse = require('bcrypto/lib/cleanse');
|
||||
const aes = require('bcrypto/lib/aes');
|
||||
const sha256 = require('bcrypto/lib/sha256');
|
||||
const pbkdf2 = require('bcrypto/lib/pbkdf2');
|
||||
const scrypt = require('bcrypto/lib/scrypt');
|
||||
const BufferReader = require('../utils/reader');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
const encoding = require('../utils/encoding');
|
||||
@ -265,7 +266,7 @@ MasterKey.prototype.derive = async function derive(passwd) {
|
||||
|
||||
switch (this.alg) {
|
||||
case MasterKey.alg.PBKDF2:
|
||||
return await pbkdf2.deriveAsync(passwd, salt, N, 32, 'sha256');
|
||||
return await pbkdf2.deriveAsync(sha256, passwd, salt, N, 32);
|
||||
case MasterKey.alg.SCRYPT:
|
||||
return await scrypt.deriveAsync(passwd, salt, N, r, p, 32);
|
||||
default:
|
||||
|
||||
@ -53,7 +53,8 @@ plugin.init = function init(node) {
|
||||
port: config.uint('wallet-port'),
|
||||
spv: node.spv,
|
||||
verify: node.spv,
|
||||
listen: false
|
||||
listen: true,
|
||||
plugin: true
|
||||
});
|
||||
|
||||
wdb.http.attach('/wallet', node.http);
|
||||
|
||||
@ -10,7 +10,7 @@ const assert = require('assert');
|
||||
const bweb = require('bweb');
|
||||
const fs = require('../utils/fs');
|
||||
const util = require('../utils/util');
|
||||
const digest = require('../crypto/digest');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const Amount = require('../btc/amount');
|
||||
const Script = require('../script/script');
|
||||
const Address = require('../primitives/address');
|
||||
|
||||
@ -13,8 +13,8 @@ const Network = require('../protocol/network');
|
||||
const util = require('../utils/util');
|
||||
const encoding = require('../utils/encoding');
|
||||
const Lock = require('../utils/lock');
|
||||
const digest = require('../crypto/digest');
|
||||
const cleanse = require('../crypto/cleanse');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const cleanse = require('bcrypto/lib/cleanse');
|
||||
const BufferReader = require('../utils/reader');
|
||||
const StaticWriter = require('../utils/staticwriter');
|
||||
const base58 = require('../utils/base58');
|
||||
|
||||
@ -14,8 +14,8 @@ const util = require('../utils/util');
|
||||
const Lock = require('../utils/lock');
|
||||
const MappedLock = require('../utils/mappedlock');
|
||||
const encoding = require('../utils/encoding');
|
||||
const ccmp = require('../crypto/ccmp');
|
||||
const aes = require('../crypto/aes');
|
||||
const ccmp = require('bcrypto/lib/ccmp');
|
||||
const aes = require('bcrypto/lib/aes');
|
||||
const Network = require('../protocol/network');
|
||||
const Path = require('./path');
|
||||
const common = require('./common');
|
||||
@ -130,7 +130,7 @@ WalletDB.prototype._init = function _init() {
|
||||
*/
|
||||
|
||||
WalletDB.prototype._open = async function _open() {
|
||||
if (this.options.listen)
|
||||
if (!this.options.plugin)
|
||||
await this.logger.open();
|
||||
|
||||
await this.db.open();
|
||||
@ -160,7 +160,8 @@ WalletDB.prototype._open = async function _open() {
|
||||
this.primary = wallet;
|
||||
this.rpc.wallet = wallet;
|
||||
|
||||
await this.http.open();
|
||||
if (this.options.listen)
|
||||
await this.http.open();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -171,7 +172,9 @@ WalletDB.prototype._open = async function _open() {
|
||||
|
||||
WalletDB.prototype._close = async function _close() {
|
||||
await this.disconnect();
|
||||
await this.http.close();
|
||||
|
||||
if (this.options.listen)
|
||||
await this.http.close();
|
||||
|
||||
for (const wallet of this.wallets.values()) {
|
||||
await wallet.destroy();
|
||||
@ -180,7 +183,7 @@ WalletDB.prototype._close = async function _close() {
|
||||
|
||||
await this.db.close();
|
||||
|
||||
if (this.options.listen)
|
||||
if (!this.options.plugin)
|
||||
await this.logger.close();
|
||||
};
|
||||
|
||||
@ -2043,6 +2046,7 @@ function WalletOptions(options) {
|
||||
this.ssl = false;
|
||||
this.host = '127.0.0.1';
|
||||
this.port = this.network.rpcPort + 2;
|
||||
this.plugin = false;
|
||||
this.listen = false;
|
||||
|
||||
if (options)
|
||||
@ -2169,6 +2173,11 @@ WalletOptions.prototype.fromOptions = function fromOptions(options) {
|
||||
this.port = options.port;
|
||||
}
|
||||
|
||||
if (options.plugin != null) {
|
||||
assert(typeof options.plugin === 'boolean');
|
||||
this.plugin = options.plugin;
|
||||
}
|
||||
|
||||
if (options.listen != null) {
|
||||
assert(typeof options.listen === 'boolean');
|
||||
this.listen = options.listen;
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const secp256k1 = require('../crypto/secp256k1');
|
||||
const {derive} = require('../crypto/scrypt');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
const {derive} = require('bcrypto/lib/scrypt');
|
||||
const hashcash = require('../mining/mine');
|
||||
const packets = require('./packets');
|
||||
|
||||
|
||||
@ -19,8 +19,8 @@ const assert = require('assert');
|
||||
const encoding = require('../lib/utils/encoding');
|
||||
const co = require('../lib/utils/co');
|
||||
const util = require('../lib/utils/util');
|
||||
const digest = require('../lib/crypto/digest');
|
||||
const BN = require('../lib/crypto/bn');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const BN = require('bcrypto/lib/bn');
|
||||
const StaticWriter = require('../lib/utils/staticwriter');
|
||||
const BufferReader = require('../lib/utils/reader');
|
||||
const OldCoins = require('./coins/coins');
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const secp256k1 = require('../lib/crypto/secp256k1');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
|
||||
/*
|
||||
* Compression
|
||||
|
||||
@ -3,10 +3,10 @@
|
||||
const assert = require('assert');
|
||||
const encoding = require('../lib/utils/encoding');
|
||||
const BufferReader = require('../lib/utils/reader');
|
||||
const digest = require('../lib/crypto/digest');
|
||||
const digest = require('bcrypto/lib/digest');
|
||||
const util = require('../lib/utils/util');
|
||||
const LDB = require('../lib/db/ldb');
|
||||
const BN = require('../lib/crypto/bn');
|
||||
const BN = require('bcrypto/lib/bn');
|
||||
const DUMMY = Buffer.from([0]);
|
||||
let file = process.argv[2];
|
||||
let batch;
|
||||
|
||||
@ -23,18 +23,16 @@
|
||||
"node": ">=7.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"bn.js": "4.11.8",
|
||||
"elliptic": "6.4.0",
|
||||
"n64": "0.0.18",
|
||||
"breq": "^0.0.1",
|
||||
"bclient": "^0.0.1",
|
||||
"bweb": "^0.0.1",
|
||||
"bsock": "^0.0.1"
|
||||
"bsock": "^0.0.1",
|
||||
"bcrypto": "^0.0.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"bcoin-native": "0.0.23",
|
||||
"leveldown": "1.7.2",
|
||||
"secp256k1": "3.3.0"
|
||||
"leveldown": "1.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.25.0",
|
||||
|
||||
@ -8,8 +8,8 @@ const Input = require('../lib/primitives/input');
|
||||
const Output = require('../lib/primitives/output');
|
||||
const Outpoint = require('../lib/primitives/outpoint');
|
||||
const TX = require('../lib/primitives/tx');
|
||||
const random = require('../lib/crypto/random');
|
||||
const secp256k1 = require('../lib/crypto/secp256k1');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
const flags = Script.flags;
|
||||
|
||||
let consensus = null;
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
/* eslint-env mocha */
|
||||
/* eslint prefer-arrow-callback: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('./util/assert');
|
||||
const aes = require('../lib/crypto/aes');
|
||||
|
||||
const key = Buffer.from(
|
||||
'3a0c0bf669694ac7685e6806eeadee8e56c9b9bd22c3caa81c718ed4bbf809a1',
|
||||
'hex');
|
||||
|
||||
const iv = Buffer.from('6dd26d9045b73c377a9ed2ffeca72ffd', 'hex');
|
||||
|
||||
describe('AES', function() {
|
||||
it('should encrypt and decrypt with 2 blocks', () => {
|
||||
const data = Buffer.from(
|
||||
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
|
||||
'hex');
|
||||
|
||||
const expected = Buffer.from(''
|
||||
+ '83de502a9c83112ca6383f2214a892a0cdad5ab2b3e192e'
|
||||
+ '9921ddb126b25262c41f1dcff4d67ccfb40e4116e5a4569c1',
|
||||
'hex');
|
||||
|
||||
const ciphertext = aes.encipher(data, key, iv);
|
||||
assert.bufferEqual(ciphertext, expected);
|
||||
|
||||
const plaintext = aes.decipher(ciphertext, key, iv);
|
||||
assert.bufferEqual(plaintext, data);
|
||||
});
|
||||
|
||||
it('should encrypt and decrypt with uneven blocks', () => {
|
||||
const data = Buffer.from(
|
||||
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855010203',
|
||||
'hex');
|
||||
|
||||
const expected = Buffer.from(''
|
||||
+ '83de502a9c83112ca6383f2214a892a0cdad5ab2b3e192e9'
|
||||
+ '921ddb126b25262c5211801019a30c0c6f795296923e0af8',
|
||||
'hex');
|
||||
|
||||
const ciphertext = aes.encipher(data, key, iv);
|
||||
assert.bufferEqual(ciphertext, expected);
|
||||
|
||||
const plaintext = aes.decipher(ciphertext, key, iv);
|
||||
assert.bufferEqual(plaintext, data);
|
||||
});
|
||||
});
|
||||
@ -4,7 +4,7 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('./util/assert');
|
||||
const secp256k1 = require('../lib/crypto/secp256k1');
|
||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||
const BIP150 = require('../lib/net/bip150');
|
||||
const BIP151 = require('../lib/net/bip151');
|
||||
|
||||
|
||||
@ -1,235 +0,0 @@
|
||||
/* eslint-env mocha */
|
||||
/* eslint prefer-arrow-callback: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('./util/assert');
|
||||
const ChaCha20 = require('../lib/crypto/chacha20');
|
||||
const Poly1305 = require('../lib/crypto/poly1305');
|
||||
const AEAD = require('../lib/crypto/aead');
|
||||
|
||||
function testChaCha(options) {
|
||||
const key = Buffer.from(options.key, 'hex');
|
||||
const nonce = Buffer.from(options.nonce, 'hex');
|
||||
const plain = Buffer.from(options.plain, 'hex');
|
||||
const ciphertext = Buffer.from(options.ciphertext, 'hex');
|
||||
const counter = options.counter;
|
||||
|
||||
const ctx1 = new ChaCha20();
|
||||
ctx1.init(key, nonce, counter);
|
||||
const plainenc = Buffer.from(plain);
|
||||
ctx1.encrypt(plainenc);
|
||||
assert.bufferEqual(plainenc, ciphertext);
|
||||
|
||||
const ctx2 = new ChaCha20();
|
||||
ctx2.init(key, nonce, counter);
|
||||
ctx2.encrypt(ciphertext);
|
||||
assert.bufferEqual(plain, ciphertext);
|
||||
}
|
||||
|
||||
function testAEAD(options) {
|
||||
const plain = Buffer.from(options.plain, 'hex');
|
||||
const aad = Buffer.from(options.aad, 'hex');
|
||||
const key = Buffer.from(options.key, 'hex');
|
||||
const nonce = Buffer.from(options.nonce, 'hex');
|
||||
const pk = Buffer.from(options.pk, 'hex');
|
||||
const ciphertext = Buffer.from(options.ciphertext, 'hex');
|
||||
const tag = Buffer.from(options.tag, 'hex');
|
||||
|
||||
const ctx1 = new AEAD();
|
||||
ctx1.init(key, nonce);
|
||||
assert.strictEqual(ctx1.chacha20.getCounter(), 1);
|
||||
assert.bufferEqual(ctx1.polyKey, pk);
|
||||
ctx1.aad(aad);
|
||||
const plainenc = Buffer.from(plain);
|
||||
ctx1.encrypt(plainenc);
|
||||
assert.bufferEqual(plainenc, ciphertext);
|
||||
assert.bufferEqual(ctx1.finish(), tag);
|
||||
|
||||
const ctx2 = new AEAD();
|
||||
ctx2.init(key, nonce);
|
||||
assert.strictEqual(ctx2.chacha20.getCounter(), 1);
|
||||
assert.bufferEqual(ctx2.polyKey, pk);
|
||||
ctx2.aad(aad);
|
||||
ctx2.decrypt(ciphertext);
|
||||
assert.bufferEqual(ciphertext, plain);
|
||||
assert.bufferEqual(ctx2.finish(), tag);
|
||||
}
|
||||
|
||||
describe('ChaCha20 / Poly1305 / AEAD', function() {
|
||||
it('should perform chacha20', () => {
|
||||
testChaCha({
|
||||
key: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
nonce: '000000000000004a00000000',
|
||||
plain: ''
|
||||
+ '4c616469657320616e642047656e746c656d656e206f6620746865206'
|
||||
+ '36c617373206f66202739393a204966204920636f756c64206f6666657220796'
|
||||
+ 'f75206f6e6c79206f6e652074697020666f7220746865206675747572652c207'
|
||||
+ '3756e73637265656e20776f756c642062652069742e',
|
||||
ciphertext: ''
|
||||
+ '6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afcc'
|
||||
+ 'fd9fae0bf91b65c5524733ab8f593dabcd62b3571639d624e65152ab'
|
||||
+ '8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d'
|
||||
+ '16ccf806818ce91ab77937365af90bbf74a35be6b40b8eedf2785e42874d',
|
||||
counter: 1
|
||||
});
|
||||
});
|
||||
|
||||
it('should perform chacha20', () => {
|
||||
testChaCha({
|
||||
key: '0000000000000000000000000000000000000000000000000000000000000000',
|
||||
nonce: '000000000000000000000000',
|
||||
plain: ''
|
||||
+ '0000000000000000000000000000000000000000000000000000000000000000'
|
||||
+ '0000000000000000000000000000000000000000000000000000000000000000',
|
||||
ciphertext: ''
|
||||
+ '76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b77'
|
||||
+ '0dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669'
|
||||
+ 'b2ee6586',
|
||||
counter: 0
|
||||
});
|
||||
});
|
||||
|
||||
it('should perform chacha20', () => {
|
||||
testChaCha({
|
||||
key: '0000000000000000000000000000000000000000000000000000000000000001',
|
||||
nonce: '000000000000000000000002',
|
||||
plain: ''
|
||||
+ '416e79207375626d697373696f6e20746f20746865204945544620696e'
|
||||
+ '74656e6465642062792074686520436f6e7472696275746f7220666f722'
|
||||
+ '07075626c69636174696f6e20617320616c6c206f722070617274206f'
|
||||
+ '6620616e204945544620496e7465726e65742d4472616674206f7220524'
|
||||
+ '64320616e6420616e792073746174656d656e74206d6164652077697468696'
|
||||
+ 'e2074686520636f6e74657874206f6620616e2049455446206163746976'
|
||||
+ '69747920697320636f6e7369646572656420616e20224945544620436f6'
|
||||
+ 'e747269627574696f6e222e20537563682073746174656d656e747320696e'
|
||||
+ '636c756465206f72616c2073746174656d656e747320696e204945544620'
|
||||
+ '73657373696f6e732c2061732077656c6c206173207772697474656e2061'
|
||||
+ '6e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d'
|
||||
+ '61646520617420616e792074696d65206f7220706c6163652c2077686963'
|
||||
+ '68206172652061646472657373656420746f',
|
||||
ciphertext: ''
|
||||
+ 'a3fbf07df3fa2fde4f376ca23e82737041605d9f4f4f57bd8cff2c1d'
|
||||
+ '4b7955ec2a97948bd3722915c8f3d337f7d370050e9e96d647b7c39f'
|
||||
+ '56e031ca5eb6250d4042e02785ececfa4b4bb5e8ead0440e20b6e8db'
|
||||
+ '09d881a7c6132f420e52795042bdfa7773d8a9051447b3291ce1411c'
|
||||
+ '680465552aa6c405b7764d5e87bea85ad00f8449ed8f72d0d662ab05'
|
||||
+ '2691ca66424bc86d2df80ea41f43abf937d3259dc4b2d0dfb48a6c91'
|
||||
+ '39ddd7f76966e928e635553ba76c5c879d7b35d49eb2e62b0871cdac'
|
||||
+ '638939e25e8a1e0ef9d5280fa8ca328b351c3c765989cbcf3daa8b6c'
|
||||
+ 'cc3aaf9f3979c92b3720fc88dc95ed84a1be059c6499b9fda236e7e8'
|
||||
+ '18b04b0bc39c1e876b193bfe5569753f88128cc08aaa9b63d1a16f80'
|
||||
+ 'ef2554d7189c411f5869ca52c5b83fa36ff216b9c1d30062bebcfd'
|
||||
+ '2dc5bce0911934fda79a86f6e698ced759c3ff9b6477338f3da4f9'
|
||||
+ 'cd8514ea9982ccafb341b2384dd902f3d1ab7ac61dd29c6f21ba5b'
|
||||
+ '862f3730e37cfdc4fd806c22f221',
|
||||
counter: 1
|
||||
});
|
||||
});
|
||||
|
||||
it('should perform chacha20', () => {
|
||||
testChaCha({
|
||||
key: '1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0',
|
||||
nonce: '000000000000000000000002',
|
||||
plain: ''
|
||||
+ '2754776173206272696c6c69672c20616e642074686520736c6974687920746f76'
|
||||
+ '65730a446964206779726520616e642067696d626c6520696e207468'
|
||||
+ '6520776162653a0a416c6c206d696d73792077657265207468652062'
|
||||
+ '6f726f676f7665732c0a416e6420746865206d6f6d65207261746873'
|
||||
+ '206f757467726162652e',
|
||||
ciphertext: ''
|
||||
+ '62e6347f95ed87a45ffae7426f27a1df5fb69110044c0d73118effa95b01e5cf16'
|
||||
+ '6d3df2d721caf9b21e5fb14c616871fd84c54f9d65b283196c7fe4f6'
|
||||
+ '0553ebf39c6402c42234e32a356b3e764312a61a5532055716ead696'
|
||||
+ '2568f87d3f3f7704c6a8d1bcd1bf4d50d6154b6da731b187b58dfd72'
|
||||
+ '8afa36757a797ac188d1',
|
||||
counter: 42
|
||||
});
|
||||
});
|
||||
|
||||
it('should perform poly1305', () => {
|
||||
const expected = Buffer.from('ddb9da7ddd5e52792730ed5cda5f90a4', 'hex');
|
||||
const key = Buffer.allocUnsafe(32);
|
||||
const msg = Buffer.allocUnsafe(73);
|
||||
|
||||
for (let i = 0; i < key.length; i++)
|
||||
key[i] = i + 221;
|
||||
|
||||
for (let i = 0; i < msg.length; i++)
|
||||
msg[i] = i + 121;
|
||||
|
||||
const mac = Poly1305.auth(msg, key);
|
||||
assert(Poly1305.verify(mac, expected));
|
||||
assert.bufferEqual(mac, expected);
|
||||
});
|
||||
|
||||
it('should perform poly1305', () => {
|
||||
const key = Buffer.from(''
|
||||
+ '85d6be7857556d337f4452fe42d506a'
|
||||
+ '80103808afb0db2fd4abff6af4149f51b',
|
||||
'hex');
|
||||
|
||||
const msg = Buffer.from('Cryptographic Forum Research Group', 'ascii');
|
||||
const tag = Buffer.from('a8061dc1305136c6c22b8baf0c0127a9', 'hex');
|
||||
|
||||
const mac = Poly1305.auth(msg, key);
|
||||
|
||||
assert(Poly1305.verify(mac, tag));
|
||||
|
||||
mac[0] = 0;
|
||||
|
||||
assert(!Poly1305.verify(mac, tag));
|
||||
});
|
||||
|
||||
it('should create an AEAD and encrypt', () => {
|
||||
testAEAD({
|
||||
plain: ''
|
||||
+ '4c616469657320616e642047656e746c656d656e206f662074686520636c6'
|
||||
+ '17373206f66202739393a204966204920636f756c64206f666665722'
|
||||
+ '0796f75206f6e6c79206f6e652074697020666f72207468652066757'
|
||||
+ '47572652c2073756e73637265656e20776f756c642062652069742e',
|
||||
aad: '50515253c0c1c2c3c4c5c6c7',
|
||||
key: '808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f',
|
||||
nonce: '07000000' + '4041424344454647',
|
||||
pk: '7bac2b252db447af09b67a55a4e955840ae1d6731075d9eb2a9375783ed553ff',
|
||||
ciphertext: ''
|
||||
+ 'd31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee6'
|
||||
+ '2d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a'
|
||||
+ '5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad67'
|
||||
+ '5945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116',
|
||||
tag: '1ae10b594f09e26a7e902ecbd0600691'
|
||||
});
|
||||
});
|
||||
|
||||
it('should create an AEAD and encrypt', () => {
|
||||
testAEAD({
|
||||
key: '1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0',
|
||||
ciphertext: ''
|
||||
+ '64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8'
|
||||
+ 'cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03'
|
||||
+ 'b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d3'
|
||||
+ '3bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b35063836069'
|
||||
+ '07b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a'
|
||||
+ '4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b004'
|
||||
+ '7718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa7'
|
||||
+ '6991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e61'
|
||||
+ '7d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6'
|
||||
+ 'f2c29a6ad5cb4022b02709b',
|
||||
nonce: '000000000102030405060708',
|
||||
aad: 'f33388860000000000004e91',
|
||||
tag: 'eead9d67890cbb22392336fea1851f38',
|
||||
pk: 'bdf04aa95ce4de8995b14bb6a18fecaf26478f50c054f563dbc0a21e261572aa',
|
||||
plain: ''
|
||||
+ '496e7465726e65742d4472616674732061726520647261667420646f63756'
|
||||
+ 'd656e74732076616c696420666f722061206d6178696d756d206f662'
|
||||
+ '0736978206d6f6e74687320616e64206d61792062652075706461746'
|
||||
+ '5642c207265706c616365642c206f72206f62736f6c6574656420627'
|
||||
+ '9206f7468657220646f63756d656e747320617420616e792074696d6'
|
||||
+ '52e20497420697320696e617070726f70726961746520746f2075736'
|
||||
+ '520496e7465726e65742d447261667473206173207265666572656e6'
|
||||
+ '365206d6174657269616c206f7220746f2063697465207468656d206'
|
||||
+ 'f74686572207468616e206173202fe2809c776f726b20696e2070726'
|
||||
+ 'f67726573732e2fe2809d'
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
const assert = require('./util/assert');
|
||||
const consensus = require('../lib/protocol/consensus');
|
||||
const BN = require('../lib/crypto/bn');
|
||||
const BN = require('bcrypto/lib/bn');
|
||||
|
||||
describe('Consensus', function() {
|
||||
it('should calculate reward properly', () => {
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
const assert = require('./util/assert');
|
||||
const GCSFilter = require('../lib/utils/gcs');
|
||||
const random = require('../lib/crypto/random');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const Outpoint = require('../lib/primitives/outpoint');
|
||||
const Address = require('../lib/primitives/address');
|
||||
const common = require('./util/common');
|
||||
|
||||
@ -6,7 +6,8 @@
|
||||
const assert = require('./util/assert');
|
||||
const HD = require('../lib/hd');
|
||||
const base58 = require('../lib/utils/base58');
|
||||
const pbkdf2 = require('../lib/crypto/pbkdf2');
|
||||
const pbkdf2 = require('bcrypto/lib/pbkdf2');
|
||||
const sha512 = require('bcrypto/lib/sha512');
|
||||
const vectors = require('./data/hd.json');
|
||||
const vector1 = vectors.vector1;
|
||||
const vector2 = vectors.vector2;
|
||||
@ -21,8 +22,11 @@ function base58Equal(a, b) {
|
||||
|
||||
describe('HD', function() {
|
||||
it('should create a pbkdf2 seed', () => {
|
||||
const seed = pbkdf2.derive(
|
||||
vectors.phrase, 'mnemonicfoo', 2048, 64, 'sha512');
|
||||
const seed = pbkdf2.derive(sha512,
|
||||
Buffer.from(vectors.phrase),
|
||||
Buffer.from('mnemonicfoo'),
|
||||
2048,
|
||||
64);
|
||||
assert.strictEqual(seed.toString('hex'), vectors.seed);
|
||||
});
|
||||
|
||||
|
||||
@ -1,84 +0,0 @@
|
||||
/* eslint-env mocha */
|
||||
/* eslint prefer-arrow-callback: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('./util/assert');
|
||||
const hkdf = require('../lib/crypto/hkdf');
|
||||
|
||||
describe('HKDF', function() {
|
||||
it('should do proper hkdf (1)', () => {
|
||||
// https://tools.ietf.org/html/rfc5869
|
||||
const alg = 'sha256';
|
||||
const ikm = Buffer.from(
|
||||
'0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', 'hex');
|
||||
const salt = Buffer.from('000102030405060708090a0b0c', 'hex');
|
||||
const info = Buffer.from('f0f1f2f3f4f5f6f7f8f9', 'hex');
|
||||
const len = 42;
|
||||
|
||||
const prkE = Buffer.from(
|
||||
'077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5',
|
||||
'hex');
|
||||
|
||||
const okmE = Buffer.from(''
|
||||
+ '3cb25f25faacd57a90434f64d0362f2a2d2d0a90'
|
||||
+ 'cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865',
|
||||
'hex');
|
||||
|
||||
const prk = hkdf.extract(ikm, salt, alg);
|
||||
const okm = hkdf.expand(prk, info, len, alg);
|
||||
|
||||
assert.bufferEqual(prk, prkE);
|
||||
assert.bufferEqual(okm, okmE);
|
||||
});
|
||||
|
||||
it('should do proper hkdf (2)', () => {
|
||||
const alg = 'sha256';
|
||||
|
||||
const ikm = Buffer.from(''
|
||||
+ '000102030405060708090a0b0c0d0e0f'
|
||||
+ '101112131415161718191a1b1c1d1e1f'
|
||||
+ '202122232425262728292a2b2c2d2e2f'
|
||||
+ '303132333435363738393a3b3c3d3e3f'
|
||||
+ '404142434445464748494a4b4c4d4e4f',
|
||||
'hex');
|
||||
|
||||
const salt = Buffer.from(''
|
||||
+ '606162636465666768696a6b6c6d6e6f'
|
||||
+ '707172737475767778797a7b7c7d7e7f'
|
||||
+ '808182838485868788898a8b8c8d8e8f'
|
||||
+ '909192939495969798999a9b9c9d9e9f'
|
||||
+ 'a0a1a2a3a4a5a6a7a8a9aaabacadaeaf',
|
||||
'hex');
|
||||
|
||||
const info = Buffer.from(''
|
||||
+ 'b0b1b2b3b4b5b6b7b8b9babbbcbdbebf'
|
||||
+ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf'
|
||||
+ 'd0d1d2d3d4d5d6d7d8d9dadbdcdddedf'
|
||||
+ 'e0e1e2e3e4e5e6e7e8e9eaebecedeeef'
|
||||
+ 'f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff',
|
||||
'hex');
|
||||
|
||||
const len = 82;
|
||||
|
||||
const prkE = Buffer.from(''
|
||||
+ '06a6b88c5853361a06104c9ceb35b45c'
|
||||
+ 'ef760014904671014a193f40c15fc244',
|
||||
'hex');
|
||||
|
||||
const okmE = Buffer.from(''
|
||||
+ 'b11e398dc80327a1c8e7f78c596a4934'
|
||||
+ '4f012eda2d4efad8a050cc4c19afa97c'
|
||||
+ '59045a99cac7827271cb41c65e590e09'
|
||||
+ 'da3275600c2f09b8367793a9aca3db71'
|
||||
+ 'cc30c58179ec3e87c14c01d5c1f3434f'
|
||||
+ '1d87',
|
||||
'hex');
|
||||
|
||||
const prk = hkdf.extract(ikm, salt, alg);
|
||||
const okm = hkdf.expand(prk, info, len, alg);
|
||||
|
||||
assert.bufferEqual(prk, prkE);
|
||||
assert.bufferEqual(okm, okmE);
|
||||
});
|
||||
});
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
const assert = require('./util/assert');
|
||||
const encoding = require('../lib/utils/encoding');
|
||||
const random = require('../lib/crypto/random');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const MempoolEntry = require('../lib/mempool/mempoolentry');
|
||||
const Mempool = require('../lib/mempool/mempool');
|
||||
const WorkerPool = require('../lib/workers/workerpool');
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
/* eslint-env mocha */
|
||||
/* eslint prefer-arrow-callback: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('./util/assert');
|
||||
const secp256k1 = require('../lib/crypto/secp256k1');
|
||||
const digest = require('../lib/crypto/digest');
|
||||
const schnorr = require('../lib/crypto/schnorr');
|
||||
|
||||
describe('Schnorr', function() {
|
||||
it('should do proper schnorr', () => {
|
||||
const key = secp256k1.generatePrivateKey();
|
||||
const pub = secp256k1.publicKeyCreate(key, true);
|
||||
const msg = digest.hash256(Buffer.from('foo', 'ascii'));
|
||||
const sig = schnorr.sign(msg, key);
|
||||
assert.strictEqual(schnorr.verify(msg, sig, pub), true);
|
||||
assert.bufferEqual(schnorr.recover(sig, msg), pub);
|
||||
});
|
||||
});
|
||||
@ -1,93 +0,0 @@
|
||||
/* eslint-env mocha */
|
||||
/* eslint prefer-arrow-callback: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('./util/assert');
|
||||
const scrypt = require('../lib/crypto/scrypt');
|
||||
|
||||
describe('Scrypt', function() {
|
||||
this.timeout(20000);
|
||||
|
||||
it('should perform scrypt with N=16', () => {
|
||||
const pass = Buffer.from('');
|
||||
const salt = Buffer.from('');
|
||||
const result = scrypt.derive(pass, salt, 16, 1, 1, 64);
|
||||
assert.strictEqual(result.toString('hex'), ''
|
||||
+ '77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3f'
|
||||
+ 'ede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628'
|
||||
+ 'cf35e20c38d18906');
|
||||
});
|
||||
|
||||
it('should perform scrypt with N=1024', () => {
|
||||
const pass = Buffer.from('password');
|
||||
const salt = Buffer.from('NaCl');
|
||||
const result = scrypt.derive(pass, salt, 1024, 8, 16, 64);
|
||||
assert.strictEqual(result.toString('hex'), ''
|
||||
+ 'fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e773'
|
||||
+ '76634b3731622eaf30d92e22a3886ff109279d9830dac727afb9'
|
||||
+ '4a83ee6d8360cbdfa2cc0640');
|
||||
});
|
||||
|
||||
it('should perform scrypt with N=16384', () => {
|
||||
const pass = Buffer.from('pleaseletmein');
|
||||
const salt = Buffer.from('SodiumChloride');
|
||||
const result = scrypt.derive(pass, salt, 16384, 8, 1, 64);
|
||||
assert.strictEqual(result.toString('hex'), ''
|
||||
+ '7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b54'
|
||||
+ '3f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d'
|
||||
+ '651e40dfcf017b45575887');
|
||||
});
|
||||
|
||||
// Only enable if you want to wait a while.
|
||||
// it('should perform scrypt with N=1048576', () => {
|
||||
// let pass = Buffer.from('pleaseletmein');
|
||||
// let salt = Buffer.from('SodiumChloride');
|
||||
// let result = scrypt.derive(pass, salt, 1048576, 8, 1, 64);
|
||||
// assert.strictEqual(result.toString('hex'), ''
|
||||
// + '2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5'
|
||||
// + 'ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049'
|
||||
// + 'e8a952fbcbf45c6fa77a41a4');
|
||||
// });
|
||||
|
||||
it('should perform scrypt with N=16 (async)', async () => {
|
||||
const pass = Buffer.from('');
|
||||
const salt = Buffer.from('');
|
||||
const result = await scrypt.deriveAsync(pass, salt, 16, 1, 1, 64);
|
||||
assert.strictEqual(result.toString('hex'), ''
|
||||
+ '77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3f'
|
||||
+ 'ede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628'
|
||||
+ 'cf35e20c38d18906');
|
||||
});
|
||||
|
||||
it('should perform scrypt with N=1024 (async)', async () => {
|
||||
const pass = Buffer.from('password');
|
||||
const salt = Buffer.from('NaCl');
|
||||
const result = await scrypt.deriveAsync(pass, salt, 1024, 8, 16, 64);
|
||||
assert.strictEqual(result.toString('hex'), ''
|
||||
+ 'fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e773'
|
||||
+ '76634b3731622eaf30d92e22a3886ff109279d9830dac727afb9'
|
||||
+ '4a83ee6d8360cbdfa2cc0640');
|
||||
});
|
||||
|
||||
it('should perform scrypt with N=16384 (async)', async () => {
|
||||
const pass = Buffer.from('pleaseletmein');
|
||||
const salt = Buffer.from('SodiumChloride');
|
||||
const result = await scrypt.deriveAsync(pass, salt, 16384, 8, 1, 64);
|
||||
assert.strictEqual(result.toString('hex'), ''
|
||||
+ '7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b54'
|
||||
+ '3f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d'
|
||||
+ '651e40dfcf017b45575887');
|
||||
});
|
||||
|
||||
// Only enable if you want to wait a while.
|
||||
// it('should perform scrypt with N=1048576 (async)', async () => {
|
||||
// let pass = Buffer.from('pleaseletmein');
|
||||
// let salt = Buffer.from('SodiumChloride');
|
||||
// let result = await scrypt.deriveAsync(pass, salt, 1048576, 8, 1, 64);
|
||||
// assert.strictEqual(result.toString('hex'), ''
|
||||
// + '2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5'
|
||||
// + 'ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049'
|
||||
// + 'e8a952fbcbf45c6fa77a41a4');
|
||||
// });
|
||||
});
|
||||
@ -1,30 +0,0 @@
|
||||
/* eslint-env mocha */
|
||||
/* eslint prefer-arrow-callback: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('./util/assert');
|
||||
const siphash = require('../lib/crypto/siphash');
|
||||
const siphash256 = siphash.siphash256;
|
||||
|
||||
describe('SipHash', function() {
|
||||
it('should perform siphash with no data', () => {
|
||||
const data = Buffer.alloc(0);
|
||||
const key = Buffer.from('000102030405060708090a0b0c0d0e0f', 'hex');
|
||||
assert.deepStrictEqual(siphash256(data, key), [1919933255, -586281423]);
|
||||
});
|
||||
|
||||
it('should perform siphash with data', () => {
|
||||
const data = Buffer.from('0001020304050607', 'hex');
|
||||
const key = Buffer.from('000102030405060708090a0b0c0d0e0f', 'hex');
|
||||
assert.deepStrictEqual(siphash256(data, key), [-1812597383, -1701632926]);
|
||||
});
|
||||
|
||||
it('should perform siphash with uint256', () => {
|
||||
const data = Buffer.from(
|
||||
'000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
'hex');
|
||||
const key = Buffer.from('000102030405060708090a0b0c0d0e0f', 'hex');
|
||||
assert.deepStrictEqual(siphash256(data, key), [1898402095, 1928494286]);
|
||||
});
|
||||
});
|
||||
@ -6,7 +6,7 @@
|
||||
const assert = require('./util/assert');
|
||||
const util = require('../lib/utils/util');
|
||||
const encoding = require('../lib/utils/encoding');
|
||||
const random = require('../lib/crypto/random');
|
||||
const random = require('bcrypto/lib/random');
|
||||
const consensus = require('../lib/protocol/consensus');
|
||||
const TX = require('../lib/primitives/tx');
|
||||
const Output = require('../lib/primitives/output');
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user