/*! * hip2-server@1.0.0 * Copyright (c) 2022, Matthew Zipkin (MIT) * https://github.com/pinheadmz/hip2-server#readme */ var __node_modules__ = [ [/* 0 */ 'hip2-server', '/src/derive.js', function(exports, module, __filename, __dirname, __meta) { 'use strict'; const HDPublicKey = __node_require__(1 /* 'hsd/lib/hd/public' */); const Address = __node_require__(55 /* 'hsd/lib/primitives/address' */); const fs = require('fs'); const path = require('path'); const http = require('http'); const MAX_INDEX = 0x7fffffff; if (process.argv.length < 3) throw new Error('Usage: node build/hip2-server.js '); const port = process.argv[2]; const xpubFile = path.join(__dirname, '..', 'conf', 'xpub'); let xpub; try { xpub = fs.readFileSync(xpubFile, 'ascii'); } catch (e) { throw new Error('xpub file missing'); } xpub = xpub.split('\n')[0]; if (xpub === 'xpub6DBMpym6PM3qe7Ug7BwG6zo7dinMMjpk8nmb73czsjkzPTzfQ1d5ZvqDea4uNmMVv1Y9DT6v17GuDL1x2km9FQuKqWMdnrDfRiDNrG1nTMr') throw new Error('Example xpub must not be used! Repalce with your own account xpub.'); const acct = HDPublicKey.fromBase58(xpub); const recv = acct.derive(0); function addr() { const indexFile = path.join(__dirname, '..', 'log', 'hip2-index'); let index = 0; try { index = parseInt(fs.readFileSync(indexFile)); } catch (e) { ; } fs.writeFileSync(indexFile, index + 1); // Wow, used all our non-hardened addresses! // Don't roll over the saved index (that way the user knows this has happened) // but start over the address space and reuse addresses starting again at 0. if (index >= MAX_INDEX) index -= MAX_INDEX; const pk = recv.derive(index); const addr = Address.fromPubkey(pk.publicKey).toString(); return addr; } const requestListener = function (req, res) { res.writeHead(200); res.end(addr()); }; const server = http.createServer(requestListener); server.listen({port}); }], [/* 1 */ 'hsd', '/lib/hd/public.js', function(exports, module, __filename, __dirname, __meta) { /*! * public.js - hd public keys for hsd * Copyright (c) 2017-2018, Christopher Jeffrey (MIT License). * https://github.com/handshake-org/hsd */ 'use strict'; const assert = __node_require__(2 /* 'bsert' */); const bio = __node_require__(3 /* 'bufio' */); const base58 = __node_require__(12 /* 'bcrypto/lib/encoding/base58' */); const sha512 = __node_require__(15 /* 'bcrypto/lib/sha512' */); const hash160 = __node_require__(18 /* 'bcrypto/lib/hash160' */); const hash256 = __node_require__(22 /* 'bcrypto/lib/hash256' */); const cleanse = __node_require__(24 /* 'bcrypto/lib/cleanse' */); const secp256k1 = __node_require__(28 /* 'bcrypto/lib/secp256k1' */); const Network = __node_require__(44 /* '../protocol/network' */); const consensus = __node_require__(51 /* '../protocol/consensus' */); const common = __node_require__(52 /* './common' */); /** * HDPublicKey * @alias module:hd.PublicKey * @property {Number} depth * @property {Number} parentFingerPrint * @property {Number} childIndex * @property {Buffer} chainCode * @property {Buffer} publicKey */ class HDPublicKey extends bio.Struct { /** * Create an HD public key. * @constructor * @param {Object|Base58String} options * @param {Base58String?} options.xkey - Serialized base58 key. * @param {Number?} options.depth * @param {Number?} options.parentFingerPrint * @param {Number?} options.childIndex * @param {Buffer?} options.chainCode * @param {Buffer?} options.publicKey */ constructor(options) { super(); this.depth = 0; this.parentFingerPrint = 0; this.childIndex = 0; this.chainCode = consensus.ZERO_HASH; this.publicKey = common.ZERO_KEY; this.fingerPrint = -1; if (options) this.fromOptions(options); } /** * Inject properties from options object. * @private * @param {Object} options */ fromOptions(options) { assert(options, 'No options for HDPublicKey'); assert((options.depth & 0xff) === options.depth); assert((options.parentFingerPrint >>> 0) === options.parentFingerPrint); assert((options.childIndex >>> 0) === options.childIndex); assert(Buffer.isBuffer(options.chainCode)); assert(Buffer.isBuffer(options.publicKey)); this.depth = options.depth; this.parentFingerPrint = options.parentFingerPrint; this.childIndex = options.childIndex; this.chainCode = options.chainCode; this.publicKey = options.publicKey; return this; } /** * Get HD public key (self). * @returns {HDPublicKey} */ toPublic() { return this; } /** * Get cached base58 xprivkey (always null here). * @returns {null} */ xprivkey(network) { return null; } /** * Get cached base58 xpubkey. * @returns {Base58String} */ xpubkey(network) { return this.toBase58(network); } /** * Destroy the key (zeroes chain code and pubkey). */ destroy() { this.depth = 0; this.childIndex = 0; this.parentFingerPrint = 0; cleanse(this.chainCode); cleanse(this.publicKey); this.fingerPrint = -1; } /** * Derive a child key. * @param {Number} index - Derivation index. * @param {Boolean?} hardened - Whether the derivation * should be hardened (throws if true). * @returns {HDPrivateKey} * @throws on `hardened` */ derive(index, hardened) { assert(typeof index === 'number'); if ((index >>> 0) !== index) throw new Error('Index out of range.'); if ((index & common.HARDENED) || hardened) throw new Error('Cannot derive hardened.'); if (this.depth >= 0xff) throw new Error('Depth too high.'); const id = this.getID(index); const cache = common.cache.get(id); if (cache) return cache; const bw = bio.pool(37); bw.writeBytes(this.publicKey); bw.writeU32BE(index); const data = bw.render(); const hash = sha512.mac(data, this.chainCode); const left = hash.slice(0, 32); const right = hash.slice(32, 64); let key; try { key = secp256k1.publicKeyTweakAdd(this.publicKey, left, true); } catch (e) { return this.derive(index + 1); } if (this.fingerPrint === -1) { const fp = hash160.digest(this.publicKey); this.fingerPrint = fp.readUInt32BE(0, true); } const child = new this.constructor(); child.depth = this.depth + 1; child.parentFingerPrint = this.fingerPrint; child.childIndex = index; child.chainCode = right; child.publicKey = key; common.cache.set(id, child); return child; } /** * Unique HD key ID. * @private * @param {Number} index * @returns {String} */ getID(index) { return 'b' + this.publicKey.toString('hex') + index; } /** * Derive a BIP44 account key (does not derive, only ensures account key). * @method * @param {Number} purpose * @param {Number} type * @param {Number} account * @returns {HDPublicKey} * @throws Error if key is not already an account key. */ deriveAccount(purpose, type, account) { assert((purpose >>> 0) === purpose); assert((type >>> 0) === type); assert((account >>> 0) === account); assert(this.isAccount(account), 'Cannot derive account index.'); return this; } /** * Test whether the key is a master key. * @method * @returns {Boolean} */ isMaster() { return common.isMaster(this); } /** * Test whether the key is (most likely) a BIP44 account key. * @method * @param {Number?} account * @returns {Boolean} */ isAccount(account) { return common.isAccount(this, account); } /** * Test whether a string is a valid path. * @param {String} path * @param {Boolean?} hardened * @returns {Boolean} */ static isValidPath(path) { try { common.parsePath(path, false); return true; } catch (e) { return false; } } /** * Derive a key from a derivation path. * @param {String} path * @returns {HDPublicKey} * @throws Error if `path` is not a valid path. * @throws Error if hardened. */ derivePath(path) { const indexes = common.parsePath(path, false); let key = this; for (const index of indexes) key = key.derive(index); return key; } /** * Compare a key against an object. * @param {Object} obj * @returns {Boolean} */ equals(obj) { assert(HDPublicKey.isHDPublicKey(obj)); return this.depth === obj.depth && this.parentFingerPrint === obj.parentFingerPrint && this.childIndex === obj.childIndex && this.chainCode.equals(obj.chainCode) && this.publicKey.equals(obj.publicKey); } /** * Compare a key against an object. * @param {Object} obj * @returns {Boolean} */ compare(key) { assert(HDPublicKey.isHDPublicKey(key)); let cmp = this.depth - key.depth; if (cmp !== 0) return cmp; cmp = this.parentFingerPrint - key.parentFingerPrint; if (cmp !== 0) return cmp; cmp = this.childIndex - key.childIndex; if (cmp !== 0) return cmp; cmp = this.chainCode.compare(key.chainCode); if (cmp !== 0) return cmp; cmp = this.publicKey.compare(key.publicKey); if (cmp !== 0) return cmp; return 0; } /** * Convert key to a more json-friendly object. * @returns {Object} */ getJSON(network) { return { xpubkey: this.xpubkey(network) }; } /** * Inject properties from json object. * @private * @param {Object} json * @param {Network?} network */ fromJSON(json, network) { assert(json.xpubkey, 'Could not handle HD key JSON.'); this.fromBase58(json.xpubkey, network); return this; } /** * Test whether an object is in the form of a base58 xpubkey. * @param {String} data * @param {(Network|NetworkType)?} network * @returns {Boolean} */ static isBase58(data, network) { if (typeof data !== 'string') return false; if (data.length < 4) return false; const prefix = data.substring(0, 4); try { Network.fromPublic58(prefix, network); return true; } catch (e) { return false; } } /** * Test whether a buffer has a valid network prefix. * @param {Buffer} data * @param {(Network|NetworkType)?} network * @returns {NetworkType} */ static isRaw(data, network) { if (!Buffer.isBuffer(data)) return false; if (data.length < 4) return false; const version = data.readUInt32BE(0, true); try { Network.fromPublic(version, network); return true; } catch (e) { return false; } } /** * Inject properties from a base58 key. * @private * @param {Base58String} xkey * @param {Network?} network */ fromBase58(xkey, network) { assert(typeof xkey === 'string'); return this.decode(base58.decode(xkey), network); } /** * Inject properties from serialized data. * @private * @param {BufferReader} br * @param {(Network|NetworkType)?} network */ read(br, network) { const version = br.readU32BE(); Network.fromPublic(version, network); this.depth = br.readU8(); this.parentFingerPrint = br.readU32BE(); this.childIndex = br.readU32BE(); this.chainCode = br.readBytes(32); this.publicKey = br.readBytes(33); br.verifyChecksum(hash256.digest); return this; } /** * Serialize key data to base58 extended key. * @param {(Network|NetworkType)?} network * @returns {Base58String} */ toBase58(network) { return base58.encode(this.encode(network)); } /** * Write the key to a buffer writer. * @param {BufferWriter} bw * @param {(Network|NetworkType)?} network */ write(bw, network) { network = Network.get(network); bw.writeU32BE(network.keyPrefix.xpubkey); bw.writeU8(this.depth); bw.writeU32BE(this.parentFingerPrint); bw.writeU32BE(this.childIndex); bw.writeBytes(this.chainCode); bw.writeBytes(this.publicKey); bw.writeChecksum(hash256.digest); return bw; } /** * Calculate serialization size. * @returns {Number} */ getSize() { return 82; } /** * Instantiate an HD public key from a base58 string. * @param {Base58String} xkey * @param {Network?} network * @returns {HDPublicKey} */ static fromBase58(xkey, network) { return new this().fromBase58(xkey, network); } /** * Test whether an object is a HDPublicKey. * @param {Object} obj * @returns {Boolean} */ static isHDPublicKey(obj) { return obj instanceof HDPublicKey; } } /* * Expose */ module.exports = HDPublicKey; }], [/* 2 */ 'bsert', '/lib/assert.js', function(exports, module, __filename, __dirname, __meta) { /*! * assert.js - assertions for javascript * Copyright (c) 2018, Christopher Jeffrey (MIT License). * https://github.com/chjj/bsert */ 'use strict'; /** * AssertionError */ class AssertionError extends Error { constructor(options) { if (typeof options === 'string') options = { message: options }; if (options === null || typeof options !== 'object') options = {}; let message = null; let operator = 'fail'; let generatedMessage = Boolean(options.generatedMessage); if (options.message != null) message = toString(options.message); if (typeof options.operator === 'string') operator = options.operator; if (message == null) { if (operator === 'fail') { message = 'Assertion failed.'; } else { const a = stringify(options.actual); const b = stringify(options.expected); message = `${a} ${operator} ${b}`; } generatedMessage = true; } super(message); let start = this.constructor; if (typeof options.stackStartFunction === 'function') start = options.stackStartFunction; else if (typeof options.stackStartFn === 'function') start = options.stackStartFn; this.type = 'AssertionError'; this.name = 'AssertionError [ERR_ASSERTION]'; this.code = 'ERR_ASSERTION'; this.generatedMessage = generatedMessage; this.actual = options.actual; this.expected = options.expected; this.operator = operator; if (Error.captureStackTrace) Error.captureStackTrace(this, start); } } /* * Assert */ function assert(value, message) { if (!value) { let generatedMessage = false; if (arguments.length === 0) { message = 'No value argument passed to `assert()`.'; generatedMessage = true; } else if (message == null) { message = 'Assertion failed.'; generatedMessage = true; } else if (isError(message)) { throw message; } throw new AssertionError({ message, actual: value, expected: true, operator: '==', generatedMessage, stackStartFn: assert }); } } function equal(actual, expected, message) { if (!Object.is(actual, expected)) { if (isError(message)) throw message; throw new AssertionError({ message, actual, expected, operator: 'strictEqual', stackStartFn: equal }); } } function notEqual(actual, expected, message) { if (Object.is(actual, expected)) { if (isError(message)) throw message; throw new AssertionError({ message, actual, expected, operator: 'notStrictEqual', stackStartFn: notEqual }); } } function fail(message) { let generatedMessage = false; if (isError(message)) throw message; if (message == null) { message = 'Assertion failed.'; generatedMessage = true; } throw new AssertionError({ message, actual: false, expected: true, operator: 'fail', generatedMessage, stackStartFn: fail }); } function throws(func, expected, message) { if (typeof expected === 'string') { message = expected; expected = undefined; } let thrown = false; let err = null; enforce(typeof func === 'function', 'func', 'function'); try { func(); } catch (e) { thrown = true; err = e; } if (!thrown) { let generatedMessage = false; if (message == null) { message = 'Missing expected exception.'; generatedMessage = true; } throw new AssertionError({ message, actual: undefined, expected, operator: 'throws', generatedMessage, stackStartFn: throws }); } if (!testError(err, expected, message, throws)) throw err; } function doesNotThrow(func, expected, message) { if (typeof expected === 'string') { message = expected; expected = undefined; } let thrown = false; let err = null; enforce(typeof func === 'function', 'func', 'function'); try { func(); } catch (e) { thrown = true; err = e; } if (!thrown) return; if (testError(err, expected, message, doesNotThrow)) { let generatedMessage = false; if (message == null) { message = 'Got unwanted exception.'; generatedMessage = true; } throw new AssertionError({ message, actual: err, expected, operator: 'doesNotThrow', generatedMessage, stackStartFn: doesNotThrow }); } throw err; } async function rejects(func, expected, message) { if (typeof expected === 'string') { message = expected; expected = undefined; } let thrown = false; let err = null; if (typeof func !== 'function') enforce(isPromise(func), 'func', 'promise'); try { if (isPromise(func)) await func; else await func(); } catch (e) { thrown = true; err = e; } if (!thrown) { let generatedMessage = false; if (message == null) { message = 'Missing expected rejection.'; generatedMessage = true; } throw new AssertionError({ message, actual: undefined, expected, operator: 'rejects', generatedMessage, stackStartFn: rejects }); } if (!testError(err, expected, message, rejects)) throw err; } async function doesNotReject(func, expected, message) { if (typeof expected === 'string') { message = expected; expected = undefined; } let thrown = false; let err = null; if (typeof func !== 'function') enforce(isPromise(func), 'func', 'promise'); try { if (isPromise(func)) await func; else await func(); } catch (e) { thrown = true; err = e; } if (!thrown) return; if (testError(err, expected, message, doesNotReject)) { let generatedMessage = false; if (message == null) { message = 'Got unwanted rejection.'; generatedMessage = true; } throw new AssertionError({ message, actual: undefined, expected, operator: 'doesNotReject', generatedMessage, stackStartFn: doesNotReject }); } throw err; } function ifError(err) { if (err != null) { let message = 'ifError got unwanted exception: '; if (typeof err === 'object' && typeof err.message === 'string') { if (err.message.length === 0 && err.constructor) message += err.constructor.name; else message += err.message; } else { message += stringify(err); } throw new AssertionError({ message, actual: err, expected: null, operator: 'ifError', generatedMessage: true, stackStartFn: ifError }); } } function deepEqual(actual, expected, message) { if (!isDeepEqual(actual, expected, false)) { if (isError(message)) throw message; throw new AssertionError({ message, actual, expected, operator: 'deepStrictEqual', stackStartFn: deepEqual }); } } function notDeepEqual(actual, expected, message) { if (isDeepEqual(actual, expected, true)) { if (isError(message)) throw message; throw new AssertionError({ message, actual, expected, operator: 'notDeepStrictEqual', stackStartFn: notDeepEqual }); } } function bufferEqual(actual, expected, enc, message) { if (!isEncoding(enc)) { message = enc; enc = null; } if (enc == null) enc = 'hex'; expected = bufferize(actual, expected, enc); enforce(isBuffer(actual), 'actual', 'buffer'); enforce(isBuffer(expected), 'expected', 'buffer'); if (actual !== expected && !actual.equals(expected)) { if (isError(message)) throw message; throw new AssertionError({ message, actual: actual.toString(enc), expected: expected.toString(enc), operator: 'bufferEqual', stackStartFn: bufferEqual }); } } function notBufferEqual(actual, expected, enc, message) { if (!isEncoding(enc)) { message = enc; enc = null; } if (enc == null) enc = 'hex'; expected = bufferize(actual, expected, enc); enforce(isBuffer(actual), 'actual', 'buffer'); enforce(isBuffer(expected), 'expected', 'buffer'); if (actual === expected || actual.equals(expected)) { if (isError(message)) throw message; throw new AssertionError({ message, actual: actual.toString(enc), expected: expected.toString(enc), operator: 'notBufferEqual', stackStartFn: notBufferEqual }); } } function enforce(value, name, type) { if (!value) { let msg; if (name == null) { msg = 'Invalid type for parameter.'; } else { if (type == null) msg = `Invalid type for "${name}".`; else msg = `"${name}" must be a(n) ${type}.`; } const err = new TypeError(msg); if (Error.captureStackTrace) Error.captureStackTrace(err, enforce); throw err; } } function range(value, name) { if (!value) { const msg = name != null ? `"${name}" is out of range.` : 'Parameter is out of range.'; const err = new RangeError(msg); if (Error.captureStackTrace) Error.captureStackTrace(err, range); throw err; } } /* * Stringification */ function stringify(value) { switch (typeof value) { case 'undefined': return 'undefined'; case 'object': if (value === null) return 'null'; return `[${objectName(value)}]`; case 'boolean': return `${value}`; case 'number': return `${value}`; case 'string': if (value.length > 80) value = `${value.substring(0, 77)}...`; return JSON.stringify(value); case 'symbol': return tryString(value); case 'function': return `[${funcName(value)}]`; case 'bigint': return `${value}n`; default: return `[${typeof value}]`; } } function toString(value) { if (typeof value === 'string') return value; if (isError(value)) return tryString(value); return stringify(value); } function tryString(value) { try { return String(value); } catch (e) { return 'Object'; } } /* * Error Testing */ function testError(err, expected, message, func) { if (expected == null) return true; if (isRegExp(expected)) return expected.test(err); if (typeof expected !== 'function') { if (func === doesNotThrow || func === doesNotReject) throw new TypeError('"expected" must not be an object.'); if (typeof expected !== 'object') throw new TypeError('"expected" must be an object.'); let generatedMessage = false; if (message == null) { const name = func === rejects ? 'rejection' : 'exception'; message = `Missing expected ${name}.`; generatedMessage = true; } if (err == null || typeof err !== 'object') { throw new AssertionError({ actual: err, expected, message, operator: func.name, generatedMessage, stackStartFn: func }); } const keys = Object.keys(expected); if (isError(expected)) keys.push('name', 'message'); if (keys.length === 0) throw new TypeError('"expected" may not be an empty object.'); for (const key of keys) { const expect = expected[key]; const value = err[key]; if (typeof value === 'string' && isRegExp(expect) && expect.test(value)) { continue; } if ((key in err) && isDeepEqual(value, expect, false)) continue; throw new AssertionError({ actual: err, expected: expected, message, operator: func.name, generatedMessage, stackStartFn: func }); } return true; } if (expected.prototype !== undefined && (err instanceof expected)) return true; if (Error.isPrototypeOf(expected)) return false; return expected.call({}, err) === true; } /* * Comparisons */ function isDeepEqual(x, y, fail) { try { return compare(x, y, null); } catch (e) { return fail; } } function compare(a, b, cache) { // Primitives. if (Object.is(a, b)) return true; if (!isObject(a) || !isObject(b)) return false; // Semi-primitives. if (objectString(a) !== objectString(b)) return false; if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) return false; if (isBuffer(a) && isBuffer(b)) return a.equals(b); if (isDate(a)) return Object.is(a.getTime(), b.getTime()); if (isRegExp(a)) { return a.source === b.source && a.global === b.global && a.multiline === b.multiline && a.lastIndex === b.lastIndex && a.ignoreCase === b.ignoreCase; } if (isError(a)) { if (a.message !== b.message) return false; } if (isArrayBuffer(a)) { a = new Uint8Array(a); b = new Uint8Array(b); } if (isView(a) && !isBuffer(a)) { if (isBuffer(b)) return false; const x = new Uint8Array(a.buffer); const y = new Uint8Array(b.buffer); if (x.length !== y.length) return false; for (let i = 0; i < x.length; i++) { if (x[i] !== y[i]) return false; } return true; } if (isSet(a)) { if (a.size !== b.size) return false; const keys = new Set([...a, ...b]); return keys.size === a.size; } // Recursive. if (!cache) { cache = { a: new Map(), b: new Map(), p: 0 }; } else { const aa = cache.a.get(a); if (aa != null) { const bb = cache.b.get(b); if (bb != null) return aa === bb; } cache.p += 1; } cache.a.set(a, cache.p); cache.b.set(b, cache.p); const ret = recurse(a, b, cache); cache.a.delete(a); cache.b.delete(b); return ret; } function recurse(a, b, cache) { if (isMap(a)) { if (a.size !== b.size) return false; const keys = new Set([...a.keys(), ...b.keys()]); if (keys.size !== a.size) return false; for (const key of keys) { if (!compare(a.get(key), b.get(key), cache)) return false; } return true; } if (isArray(a)) { if (a.length !== b.length) return false; for (let i = 0; i < a.length; i++) { if (!compare(a[i], b[i], cache)) return false; } return true; } const ak = ownKeys(a); const bk = ownKeys(b); if (ak.length !== bk.length) return false; const keys = new Set([...ak, ...bk]); if (keys.size !== ak.length) return false; for (const key of keys) { if (!compare(a[key], b[key], cache)) return false; } return true; } function ownKeys(obj) { const keys = Object.keys(obj); if (!Object.getOwnPropertySymbols) return keys; if (!Object.getOwnPropertyDescriptor) return keys; const symbols = Object.getOwnPropertySymbols(obj); for (const symbol of symbols) { const desc = Object.getOwnPropertyDescriptor(obj, symbol); if (desc && desc.enumerable) keys.push(symbol); } return keys; } /* * Helpers */ function objectString(obj) { if (obj === undefined) return '[object Undefined]'; if (obj === null) return '[object Null]'; try { return Object.prototype.toString.call(obj); } catch (e) { return '[object Object]'; } } function objectType(obj) { return objectString(obj).slice(8, -1); } function objectName(obj) { const type = objectType(obj); if (obj == null) return type; if (type !== 'Object' && type !== 'Error') return type; let ctor, name; try { ctor = obj.constructor; } catch (e) { ; } if (ctor == null) return type; try { name = ctor.name; } catch (e) { return type; } if (typeof name !== 'string' || name.length === 0) return type; return name; } function funcName(func) { let name; try { name = func.name; } catch (e) { ; } if (typeof name !== 'string' || name.length === 0) return 'Function'; return `Function: ${name}`; } function isArray(obj) { return Array.isArray(obj); } function isArrayBuffer(obj) { return obj instanceof ArrayBuffer; } function isBuffer(obj) { return isObject(obj) && typeof obj.writeUInt32LE === 'function' && typeof obj.equals === 'function'; } function isDate(obj) { return obj instanceof Date; } function isError(obj) { return obj instanceof Error; } function isMap(obj) { return obj instanceof Map; } function isObject(obj) { return obj && typeof obj === 'object'; } function isPromise(obj) { return obj instanceof Promise; } function isRegExp(obj) { return obj instanceof RegExp; } function isSet(obj) { return obj instanceof Set; } function isView(obj) { return ArrayBuffer.isView(obj); } function isEncoding(enc) { if (typeof enc !== 'string') return false; switch (enc) { case 'ascii': case 'binary': case 'base64': case 'hex': case 'latin1': case 'ucs2': case 'utf8': case 'utf16le': return true; } return false; } function bufferize(actual, expected, enc) { if (typeof expected === 'string') { if (!isBuffer(actual)) return null; const {constructor} = actual; if (!constructor || typeof constructor.from !== 'function') return null; if (!isEncoding(enc)) return null; if (enc === 'hex' && (expected.length & 1)) return null; const raw = constructor.from(expected, enc); if (enc === 'hex' && raw.length !== (expected.length >>> 1)) return null; return raw; } return expected; } /* * API */ assert.AssertionError = AssertionError; assert.assert = assert; assert.strict = assert; assert.ok = assert; assert.equal = equal; assert.notEqual = notEqual; assert.strictEqual = equal; assert.notStrictEqual = notEqual; assert.fail = fail; assert.throws = throws; assert.doesNotThrow = doesNotThrow; assert.rejects = rejects; assert.doesNotReject = doesNotReject; assert.ifError = ifError; assert.deepEqual = deepEqual; assert.notDeepEqual = notDeepEqual; assert.deepStrictEqual = deepEqual; assert.notDeepStrictEqual = notDeepEqual; assert.bufferEqual = bufferEqual; assert.notBufferEqual = notBufferEqual; assert.enforce = enforce; assert.range = range; /* * Expose */ module.exports = assert; }], [/* 3 */ 'bufio', '/lib/bufio.js', function(exports, module, __filename, __dirname, __meta) { /*! * bufio.js - buffer utilities for javascript * Copyright (c) 2014-2017, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcoin */ 'use strict'; const custom = __node_require__(4 /* './custom' */); const encoding = __node_require__(5 /* './encoding' */); const enforce = __node_require__(6 /* './enforce' */); const EncodingError = __node_require__(7 /* './error' */); const BufferReader = __node_require__(8 /* './reader' */); const BufferWriter = __node_require__(9 /* './writer' */); const StaticWriter = __node_require__(10 /* './staticwriter' */); const Struct = __node_require__(11 /* './struct' */); exports.custom = custom; exports.encoding = encoding; exports.EncodingError = EncodingError; exports.BufferReader = BufferReader; exports.BufferWriter = BufferWriter; exports.StaticWriter = StaticWriter; exports.Struct = Struct; exports.read = function read(data, zeroCopy) { return new BufferReader(data, zeroCopy); }; exports.write = function write(size) { return size != null ? new StaticWriter(size) : new BufferWriter(); }; exports.pool = function pool(size) { return StaticWriter.pool(size); }; function _read(func, size) { return function(data, off) { enforce(Buffer.isBuffer(data), 'data', 'buffer'); enforce((off >>> 0) === off, 'off', 'integer'); if (off + size > data.length) throw new EncodingError(off, 'Out of bounds read'); return func(data, off); }; } function _readn(func) { return function(data, off, len) { enforce(Buffer.isBuffer(data), 'data', 'buffer'); enforce((off >>> 0) === off, 'off', 'integer'); enforce((len >>> 0) === len, 'len', 'integer'); if (off + len > data.length) throw new EncodingError(off, 'Out of bounds read'); return func(data, off, len); }; } function _readvar(func) { return function(data, off) { enforce(Buffer.isBuffer(data), 'data', 'buffer'); enforce((off >>> 0) === off, 'off', 'integer'); return func(data, off); }; } function _write(func, size) { return function(data, num, off) { enforce(Buffer.isBuffer(data), 'data', 'buffer'); enforce((off >>> 0) === off, 'off', 'integer'); if (off + size > data.length) throw new EncodingError(off, 'Out of bounds write'); return func(data, num, off); }; } function _writen(func) { return function(data, num, off, len) { enforce(Buffer.isBuffer(data), 'data', 'buffer'); enforce((off >>> 0) === off, 'off', 'integer'); enforce((len >>> 0) === len, 'len', 'integer'); if (off + len > data.length) throw new EncodingError(off, 'Out of bounds write'); return func(data, num, off, len); }; } function _writecb(func, size) { return function(data, num, off) { enforce(Buffer.isBuffer(data), 'data', 'buffer'); enforce((off >>> 0) === off, 'off', 'integer'); if (off + size(num) > data.length) throw new EncodingError(off, 'Out of bounds write'); return func(data, num, off); }; } exports.readU = _readn(encoding.readU); exports.readU64 = _read(encoding.readU64, 8); exports.readU56 = _read(encoding.readU56, 7); exports.readU48 = _read(encoding.readU48, 6); exports.readU40 = _read(encoding.readU40, 5); exports.readU32 = _read(encoding.readU32, 4); exports.readU24 = _read(encoding.readU24, 3); exports.readU16 = _read(encoding.readU16, 2); exports.readU8 = _read(encoding.readU8, 1); exports.readUBE = _readn(encoding.readUBE); exports.readU64BE = _read(encoding.readU64BE, 8); exports.readU56BE = _read(encoding.readU56BE, 7); exports.readU48BE = _read(encoding.readU48BE, 6); exports.readU40BE = _read(encoding.readU40BE, 5); exports.readU32BE = _read(encoding.readU32BE, 4); exports.readU24BE = _read(encoding.readU24BE, 3); exports.readU16BE = _read(encoding.readU16BE, 2); exports.readI = _readn(encoding.readI); exports.readI64 = _read(encoding.readI64, 8); exports.readI56 = _read(encoding.readI56, 7); exports.readI48 = _read(encoding.readI48, 6); exports.readI40 = _read(encoding.readI40, 5); exports.readI32 = _read(encoding.readI32, 4); exports.readI24 = _read(encoding.readI24, 3); exports.readI16 = _read(encoding.readI16, 2); exports.readI8 = _read(encoding.readI8, 1); exports.readIBE = _readn(encoding.readIBE); exports.readI64BE = _read(encoding.readI64BE, 8); exports.readI56BE = _read(encoding.readI56BE, 7); exports.readI48BE = _read(encoding.readI48BE, 6); exports.readI40BE = _read(encoding.readI40BE, 5); exports.readI32BE = _read(encoding.readI32BE, 4); exports.readI24BE = _read(encoding.readI24BE, 3); exports.readI16BE = _read(encoding.readI16BE, 2); exports.readFloat = _read(encoding.readFloat, 4); exports.readFloatBE = _read(encoding.readFloatBE, 4); exports.readDouble = _read(encoding.readDouble, 8); exports.readDoubleBE = _read(encoding.readDoubleBE, 8); exports.writeU = _writen(encoding.writeU); exports.writeU64 = _write(encoding.writeU64, 8); exports.writeU56 = _write(encoding.writeU56, 7); exports.writeU48 = _write(encoding.writeU48, 6); exports.writeU40 = _write(encoding.writeU40, 5); exports.writeU32 = _write(encoding.writeU32, 4); exports.writeU24 = _write(encoding.writeU24, 3); exports.writeU16 = _write(encoding.writeU16, 2); exports.writeU8 = _write(encoding.writeU8, 1); exports.writeUBE = _writen(encoding.writeUBE); exports.writeU64BE = _write(encoding.writeU64BE, 8); exports.writeU56BE = _write(encoding.writeU56BE, 7); exports.writeU48BE = _write(encoding.writeU48BE, 6); exports.writeU40BE = _write(encoding.writeU40BE, 5); exports.writeU32BE = _write(encoding.writeU32BE, 4); exports.writeU24BE = _write(encoding.writeU24BE, 3); exports.writeU16BE = _write(encoding.writeU16BE, 2); exports.writeI = _writen(encoding.writeI); exports.writeI64 = _write(encoding.writeI64, 8); exports.writeI56 = _write(encoding.writeI56, 7); exports.writeI48 = _write(encoding.writeI48, 6); exports.writeI40 = _write(encoding.writeI40, 5); exports.writeI32 = _write(encoding.writeI32, 4); exports.writeI24 = _write(encoding.writeI24, 3); exports.writeI16 = _write(encoding.writeI16, 2); exports.writeI8 = _write(encoding.writeI8, 1); exports.writeIBE = _writen(encoding.writeIBE); exports.writeI64BE = _write(encoding.writeI64BE, 8); exports.writeI56BE = _write(encoding.writeI56BE, 7); exports.writeI48BE = _write(encoding.writeI48BE, 6); exports.writeI40BE = _write(encoding.writeI40BE, 5); exports.writeI32BE = _write(encoding.writeI32BE, 4); exports.writeI24BE = _write(encoding.writeI24BE, 3); exports.writeI16BE = _write(encoding.writeI16BE, 2); exports.writeFloat = _write(encoding.writeFloat, 4); exports.writeFloatBE = _write(encoding.writeFloatBE, 4); exports.writeDouble = _write(encoding.writeDouble, 8); exports.writeDoubleBE = _write(encoding.writeDoubleBE, 8); exports.readVarint = _readvar(encoding.readVarint); exports.writeVarint = _writecb(encoding.writeVarint, encoding.sizeVarint); exports.sizeVarint = encoding.sizeVarint; exports.readVarint2 = _readvar(encoding.readVarint2); exports.writeVarint2 = _writecb(encoding.writeVarint2, encoding.sizeVarint2); exports.sizeVarint2 = encoding.sizeVarint2; exports.sliceBytes = encoding.sliceBytes; exports.readBytes = encoding.readBytes; exports.writeBytes = encoding.writeBytes; exports.readString = encoding.readString; exports.writeString = encoding.writeString; exports.realloc = encoding.realloc; exports.copy = encoding.copy; exports.concat = encoding.concat; exports.sizeVarBytes = encoding.sizeVarBytes; exports.sizeVarlen = encoding.sizeVarlen; exports.sizeVarString = encoding.sizeVarString; }], [/* 4 */ 'bufio', '/lib/custom-browser.js', function(exports, module, __filename, __dirname, __meta) { 'use strict'; exports.custom = 'inspect'; }], [/* 5 */ 'bufio', '/lib/encoding.js', function(exports, module, __filename, __dirname, __meta) { /*! * encoding.js - encoding utils for bcoin * Copyright (c) 2014-2015, Fedor Indutny (MIT License) * Copyright (c) 2014-2017, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcoin */ /* eslint no-implicit-coercion: "off" */ 'use strict'; const enforce = __node_require__(6 /* './enforce' */); const EncodingError = __node_require__(7 /* './error' */); /* * Constants */ const HI = 1 / 0x100000000; const {MAX_SAFE_INTEGER} = Number; const F32_ARRAY = new Float32Array(1); const F328_ARRAY = new Uint8Array(F32_ARRAY.buffer); const F64_ARRAY = new Float64Array(1); const F648_ARRAY = new Uint8Array(F64_ARRAY.buffer); F32_ARRAY[0] = -1; const BIG_ENDIAN = F328_ARRAY[3] === 0; /* * Read Unsigned LE */ function readU(data, off, len) { switch (len) { case 8: return readU64(data, off); case 7: return readU56(data, off); case 6: return readU48(data, off); case 5: return readU40(data, off); case 4: return readU32(data, off); case 3: return readU24(data, off); case 2: return readU16(data, off); case 1: return readU8(data, off); default: throw new EncodingError(off, 'Invalid read length'); } } function readU64(data, off) { const hi = readU32(data, off + 4); const lo = readU32(data, off); check((hi & 0xffe00000) === 0, off, 'Number exceeds 2^53-1'); return hi * 0x100000000 + lo; } function readU56(data, off) { const hi = readU24(data, off + 4); const lo = readU32(data, off); check((hi & 0xffe00000) === 0, off, 'Number exceeds 2^53-1'); return hi * 0x100000000 + lo; } function readU48(data, off) { return (data[off++] + data[off++] * 0x100 + data[off++] * 0x10000 + data[off++] * 0x1000000 + data[off++] * 0x100000000 + data[off] * 0x10000000000); } function readU40(data, off) { return (data[off++] + data[off++] * 0x100 + data[off++] * 0x10000 + data[off++] * 0x1000000 + data[off] * 0x100000000); } function readU32(data, off) { return (data[off++] + data[off++] * 0x100 + data[off++] * 0x10000 + data[off] * 0x1000000); } function readU24(data, off) { return (data[off++] + data[off++] * 0x100 + data[off] * 0x10000); } function readU16(data, off) { return data[off++] + data[off] * 0x100; } function readU8(data, off) { return data[off]; } /* * Read Unsigned BE */ function readUBE(data, off, len) { switch (len) { case 8: return readU64BE(data, off); case 7: return readU56BE(data, off); case 6: return readU48BE(data, off); case 5: return readU40BE(data, off); case 4: return readU32BE(data, off); case 3: return readU24BE(data, off); case 2: return readU16BE(data, off); case 1: return readU8(data, off); default: throw new EncodingError(off, 'Invalid read length'); } } function readU64BE(data, off) { const hi = readU32BE(data, off); const lo = readU32BE(data, off + 4); check((hi & 0xffe00000) === 0, off, 'Number exceeds 2^53-1'); return hi * 0x100000000 + lo; } function readU56BE(data, off) { const hi = readU24BE(data, off); const lo = readU32BE(data, off + 3); check((hi & 0xffe00000) === 0, off, 'Number exceeds 2^53-1'); return hi * 0x100000000 + lo; } function readU48BE(data, off) { return (data[off++] * 0x10000000000 + data[off++] * 0x100000000 + data[off++] * 0x1000000 + data[off++] * 0x10000 + data[off++] * 0x100 + data[off]); } function readU40BE(data, off) { return (data[off++] * 0x100000000 + data[off++] * 0x1000000 + data[off++] * 0x10000 + data[off++] * 0x100 + data[off]); } function readU32BE(data, off) { return (data[off++] * 0x1000000 + data[off++] * 0x10000 + data[off++] * 0x100 + data[off]); } function readU24BE(data, off) { return (data[off++] * 0x10000 + data[off++] * 0x100 + data[off]); } function readU16BE(data, off) { return data[off++] * 0x100 + data[off]; } /* * Read Signed LE */ function readI(data, off, len) { switch (len) { case 8: return readI64(data, off); case 7: return readI56(data, off); case 6: return readI48(data, off); case 5: return readI40(data, off); case 4: return readI32(data, off); case 3: return readI24(data, off); case 2: return readI16(data, off); case 1: return readI8(data, off); default: throw new EncodingError(off, 'Invalid read length'); } } function readI64(data, off) { const hi = readI32(data, off + 4); const lo = readU32(data, off); check(isSafe(hi, lo), 'Number exceeds 2^53-1'); return hi * 0x100000000 + lo; } function readI56(data, off) { const hi = readI24(data, off + 4); const lo = readU32(data, off); check(isSafe(hi, lo), 'Number exceeds 2^53-1'); return hi * 0x100000000 + lo; } function readI48(data, off) { const val = data[off + 4] + data[off + 5] * 0x100; return (data[off++] + data[off++] * 0x100 + data[off++] * 0x10000 + data[off] * 0x1000000 + (val | (val & 0x8000) * 0x1fffe) * 0x100000000); } function readI40(data, off) { return (data[off++] + data[off++] * 0x100 + data[off++] * 0x10000 + data[off++] * 0x1000000 + (data[off] | (data[off] & 0x80) * 0x1fffffe) * 0x100000000); } function readI32(data, off) { return (data[off++] + data[off++] * 0x100 + data[off++] * 0x10000 + (data[off] << 24)); } function readI24(data, off) { const val = (data[off++] + data[off++] * 0x100 + data[off] * 0x10000); return val | (val & 0x800000) * 0x1fe; } function readI16(data, off) { const val = data[off++] + data[off] * 0x100; return val | (val & 0x8000) * 0x1fffe; } function readI8(data, off) { const val = data[off]; return val | (val & 0x80) * 0x1fffffe; } /* * Read Signed BE */ function readIBE(data, off, len) { switch (len) { case 8: return readI64BE(data, off); case 7: return readI56BE(data, off); case 6: return readI48BE(data, off); case 5: return readI40BE(data, off); case 4: return readI32BE(data, off); case 3: return readI24BE(data, off); case 2: return readI16BE(data, off); case 1: return readI8(data, off); default: throw new EncodingError(off, 'Invalid read length'); } } function readI64BE(data, off) { const hi = readI32BE(data, off); const lo = readU32BE(data, off + 4); check(isSafe(hi, lo), 'Number exceeds 2^53-1'); return hi * 0x100000000 + lo; } function readI56BE(data, off) { const hi = readI24BE(data, off); const lo = readU32BE(data, off + 3); check(isSafe(hi, lo), 'Number exceeds 2^53-1'); return hi * 0x100000000 + lo; } function readI48BE(data, off) { const val = data[off++] * 0x100 + data[off++]; return ((val | (val & 0x8000) * 0x1fffe) * 0x100000000 + data[off++] * 0x1000000 + data[off++] * 0x10000 + data[off++] * 0x100 + data[off]); } function readI40BE(data, off) { const val = data[off++]; return ((val | (val & 0x80) * 0x1fffffe) * 0x100000000 + data[off++] * 0x1000000 + data[off++] * 0x10000 + data[off++] * 0x100 + data[off]); } function readI32BE(data, off) { return ((data[off++] << 24) + data[off++] * 0x10000 + data[off++] * 0x100 + data[off]); } function readI24BE(data, off) { const val = (data[off++] * 0x10000 + data[off++] * 0x100 + data[off]); return val | (val & 0x800000) * 0x1fe; } function readI16BE(data, off) { const val = data[off++] * 0x100 + data[off]; return val | (val & 0x8000) * 0x1fffe; } /* * Read Float */ function _readFloatBackwards(data, off) { F328_ARRAY[3] = data[off++]; F328_ARRAY[2] = data[off++]; F328_ARRAY[1] = data[off++]; F328_ARRAY[0] = data[off]; return F32_ARRAY[0]; } function _readFloatForwards(data, off) { F328_ARRAY[0] = data[off++]; F328_ARRAY[1] = data[off++]; F328_ARRAY[2] = data[off++]; F328_ARRAY[3] = data[off]; return F32_ARRAY[0]; } function _readDoubleBackwards(data, off) { F648_ARRAY[7] = data[off++]; F648_ARRAY[6] = data[off++]; F648_ARRAY[5] = data[off++]; F648_ARRAY[4] = data[off++]; F648_ARRAY[3] = data[off++]; F648_ARRAY[2] = data[off++]; F648_ARRAY[1] = data[off++]; F648_ARRAY[0] = data[off]; return F64_ARRAY[0]; } function _readDoubleForwards(data, off) { F648_ARRAY[0] = data[off++]; F648_ARRAY[1] = data[off++]; F648_ARRAY[2] = data[off++]; F648_ARRAY[3] = data[off++]; F648_ARRAY[4] = data[off++]; F648_ARRAY[5] = data[off++]; F648_ARRAY[6] = data[off++]; F648_ARRAY[7] = data[off]; return F64_ARRAY[0]; } const readFloat = BIG_ENDIAN ? _readFloatBackwards : _readFloatForwards; const readFloatBE = BIG_ENDIAN ? _readFloatForwards : _readFloatBackwards; const readDouble = BIG_ENDIAN ? _readDoubleBackwards : _readDoubleForwards; const readDoubleBE = BIG_ENDIAN ? _readDoubleForwards : _readDoubleBackwards; /* * Write Unsigned LE */ function writeU(dst, num, off, len) { switch (len) { case 8: return writeU64(dst, num, off); case 7: return writeU56(dst, num, off); case 6: return writeU48(dst, num, off); case 5: return writeU40(dst, num, off); case 4: return writeU32(dst, num, off); case 3: return writeU24(dst, num, off); case 2: return writeU16(dst, num, off); case 1: return writeU8(dst, num, off); default: throw new EncodingError(off, 'Invalid write length'); } } function writeU64(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); return write64(dst, num, off, false); } function writeU56(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); return write56(dst, num, off, false); } function writeU48(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); const hi = (num * HI) | 0; dst[off++] = num; num >>>= 8; dst[off++] = num; num >>>= 8; dst[off++] = num; num >>>= 8; dst[off++] = num; dst[off++] = hi; dst[off++] = hi >>> 8; return off; } function writeU40(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); const hi = (num * HI) | 0; dst[off++] = num; num >>>= 8; dst[off++] = num; num >>>= 8; dst[off++] = num; num >>>= 8; dst[off++] = num; dst[off++] = hi; return off; } function writeU32(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); dst[off++] = num; num >>>= 8; dst[off++] = num; num >>>= 8; dst[off++] = num; num >>>= 8; dst[off++] = num; return off; } function writeU24(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); dst[off++] = num; num >>>= 8; dst[off++] = num; num >>>= 8; dst[off++] = num; return off; } function writeU16(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); dst[off++] = num; dst[off++] = num >>> 8; return off; } function writeU8(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); dst[off] = num; return off + 1; } /* * Write Unsigned BE */ function writeUBE(dst, num, off, len) { switch (len) { case 8: return writeU64BE(dst, num, off); case 7: return writeU56BE(dst, num, off); case 6: return writeU48BE(dst, num, off); case 5: return writeU40BE(dst, num, off); case 4: return writeU32BE(dst, num, off); case 3: return writeU24BE(dst, num, off); case 2: return writeU16BE(dst, num, off); case 1: return writeU8(dst, num, off); default: throw new EncodingError(off, 'Invalid write length'); } } function writeU64BE(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); return write64(dst, num, off, true); } function writeU56BE(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); return write56(dst, num, off, true); } function writeU48BE(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); const hi = (num * HI) | 0; dst[off++] = hi >>> 8; dst[off++] = hi; dst[off + 3] = num; num >>>= 8; dst[off + 2] = num; num >>>= 8; dst[off + 1] = num; num >>>= 8; dst[off] = num; return off + 4; } function writeU40BE(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); const hi = (num * HI) | 0; dst[off++] = hi; dst[off + 3] = num; num >>>= 8; dst[off + 2] = num; num >>>= 8; dst[off + 1] = num; num >>>= 8; dst[off] = num; return off + 4; } function writeU32BE(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); dst[off + 3] = num; num >>>= 8; dst[off + 2] = num; num >>>= 8; dst[off + 1] = num; num >>>= 8; dst[off] = num; return off + 4; } function writeU24BE(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); dst[off + 2] = num; num >>>= 8; dst[off + 1] = num; num >>>= 8; dst[off] = num; return off + 3; } function writeU16BE(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); dst[off++] = num >>> 8; dst[off++] = num; return off; } /* * Write Signed LE */ function writeI(dst, num, off, len) { switch (len) { case 8: return writeU64(dst, num, off); case 7: return writeU56(dst, num, off); case 6: return writeU48(dst, num, off); case 5: return writeU40(dst, num, off); case 4: return writeU24(dst, num, off); case 3: return writeU32(dst, num, off); case 2: return writeU16(dst, num, off); case 1: return writeU8(dst, num, off); default: throw new EncodingError(off, 'Invalid write length'); } } function writeI64(dst, num, off) { return writeU64(dst, num, off); } function writeI56(dst, num, off) { return writeU56(dst, num, off); } function writeI48(dst, num, off) { return writeU48(dst, num, off); } function writeI40(dst, num, off) { return writeU40(dst, num, off); } function writeI32(dst, num, off) { return writeU32(dst, num, off); } function writeI24(dst, num, off) { return writeU24(dst, num, off); } function writeI16(dst, num, off) { return writeU16(dst, num, off); } function writeI8(dst, num, off) { return writeU8(dst, num, off); } /* * Write Signed BE */ function writeIBE(dst, num, off, len) { switch (len) { case 8: return writeU64BE(dst, num, off); case 7: return writeU56BE(dst, num, off); case 6: return writeU48BE(dst, num, off); case 5: return writeU40BE(dst, num, off); case 4: return writeU32BE(dst, num, off); case 3: return writeU24BE(dst, num, off); case 2: return writeU16BE(dst, num, off); case 1: return writeU8(dst, num, off); default: throw new EncodingError(off, 'Invalid write length'); } } function writeI64BE(dst, num, off) { return writeU64BE(dst, num, off); } function writeI56BE(dst, num, off) { return writeU56BE(dst, num, off); } function writeI48BE(dst, num, off) { return writeU48BE(dst, num, off); } function writeI40BE(dst, num, off) { return writeU40BE(dst, num, off); } function writeI32BE(dst, num, off) { return writeU32BE(dst, num, off); } function writeI24BE(dst, num, off) { return writeU24BE(dst, num, off); } function writeI16BE(dst, num, off) { return writeU16BE(dst, num, off); } function _writeDoubleForwards(dst, num, off) { enforce(isNumber(num), 'num', 'number'); F64_ARRAY[0] = num; dst[off++] = F648_ARRAY[0]; dst[off++] = F648_ARRAY[1]; dst[off++] = F648_ARRAY[2]; dst[off++] = F648_ARRAY[3]; dst[off++] = F648_ARRAY[4]; dst[off++] = F648_ARRAY[5]; dst[off++] = F648_ARRAY[6]; dst[off++] = F648_ARRAY[7]; return off; } function _writeDoubleBackwards(dst, num, off) { enforce(isNumber(num), 'num', 'number'); F64_ARRAY[0] = num; dst[off++] = F648_ARRAY[7]; dst[off++] = F648_ARRAY[6]; dst[off++] = F648_ARRAY[5]; dst[off++] = F648_ARRAY[4]; dst[off++] = F648_ARRAY[3]; dst[off++] = F648_ARRAY[2]; dst[off++] = F648_ARRAY[1]; dst[off++] = F648_ARRAY[0]; return off; } function _writeFloatForwards(dst, num, off) { enforce(isNumber(num), 'num', 'number'); F32_ARRAY[0] = num; dst[off++] = F328_ARRAY[0]; dst[off++] = F328_ARRAY[1]; dst[off++] = F328_ARRAY[2]; dst[off++] = F328_ARRAY[3]; return off; } function _writeFloatBackwards(dst, num, off) { enforce(isNumber(num), 'num', 'number'); F32_ARRAY[0] = num; dst[off++] = F328_ARRAY[3]; dst[off++] = F328_ARRAY[2]; dst[off++] = F328_ARRAY[1]; dst[off++] = F328_ARRAY[0]; return off; } const writeFloat = BIG_ENDIAN ? _writeFloatBackwards : _writeFloatForwards; const writeFloatBE = BIG_ENDIAN ? _writeFloatForwards : _writeFloatBackwards; const writeDouble = BIG_ENDIAN ? _writeDoubleBackwards : _writeDoubleForwards; const writeDoubleBE = BIG_ENDIAN ? _writeDoubleForwards : _writeDoubleBackwards; /* * Varints */ function readVarint(data, off) { let value, size; checkRead(off < data.length, off); switch (data[off]) { case 0xff: size = 9; checkRead(off + size <= data.length, off); value = readU64(data, off + 1); check(value > 0xffffffff, off, 'Non-canonical varint'); break; case 0xfe: size = 5; checkRead(off + size <= data.length, off); value = readU32(data, off + 1); check(value > 0xffff, off, 'Non-canonical varint'); break; case 0xfd: size = 3; checkRead(off + size <= data.length, off); value = readU16(data, off + 1); check(value >= 0xfd, off, 'Non-canonical varint'); break; default: size = 1; value = data[off]; break; } return new Varint(size, value); } function writeVarint(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); if (num < 0xfd) { dst[off++] = num; return off; } if (num <= 0xffff) { dst[off++] = 0xfd; return writeU16(dst, num, off); } if (num <= 0xffffffff) { dst[off++] = 0xfe; return writeU32(dst, num, off); } dst[off++] = 0xff; return writeU64(dst, num, off); } function sizeVarint(num) { enforce(Number.isSafeInteger(num), 'num', 'integer'); if (num < 0xfd) return 1; if (num <= 0xffff) return 3; if (num <= 0xffffffff) return 5; return 9; } function readVarint2(data, off) { let num = 0; let size = 0; for (;;) { checkRead(off < data.length, off); const ch = data[off++]; size += 1; // Number.MAX_SAFE_INTEGER >>> 7 check(num <= 0x3fffffffffff - (ch & 0x7f), off, 'Number exceeds 2^53-1'); // num = (num << 7) | (ch & 0x7f); num = (num * 0x80) + (ch & 0x7f); if ((ch & 0x80) === 0) break; check(num !== MAX_SAFE_INTEGER, off, 'Number exceeds 2^53-1'); num += 1; } return new Varint(size, num); } function writeVarint2(dst, num, off) { enforce(Number.isSafeInteger(num), 'num', 'integer'); const tmp = []; let len = 0; for (;;) { tmp[len] = (num & 0x7f) | (len ? 0x80 : 0x00); if (num <= 0x7f) break; // num = (num >>> 7) - 1; num = ((num - (num % 0x80)) / 0x80) - 1; len += 1; } checkRead(off + len + 1 <= dst.length, off); do { dst[off++] = tmp[len]; } while (len--); return off; } function sizeVarint2(num) { enforce(Number.isSafeInteger(num), 'num', 'integer'); let size = 0; for (;;) { size += 1; if (num <= 0x7f) break; // num = (num >>> 7) - 1; num = ((num - (num % 0x80)) / 0x80) - 1; } return size; } /* * Bytes */ function sliceBytes(data, off, size) { enforce(Buffer.isBuffer(data), 'data', 'buffer'); enforce((off >>> 0) === off, 'off', 'integer'); enforce((size >>> 0) === size, 'size', 'integer'); if (off + size > data.length) throw new EncodingError(off, 'Out of bounds read'); return data.slice(off, off + size); } function readBytes(data, off, size) { enforce(Buffer.isBuffer(data), 'data', 'buffer'); enforce((off >>> 0) === off, 'off', 'integer'); enforce((size >>> 0) === size, 'size', 'integer'); if (off + size > data.length) throw new EncodingError(off, 'Out of bounds read'); const buf = Buffer.allocUnsafeSlow(size); data.copy(buf, 0, off, off + size); return buf; } function writeBytes(data, value, off) { enforce(Buffer.isBuffer(data), 'data', 'buffer'); enforce(Buffer.isBuffer(value), 'value', 'buffer'); enforce((off >>> 0) === off, 'off', 'integer'); if (off + value.length > data.length) throw new EncodingError(off, 'Out of bounds write'); return value.copy(data, off, 0, value.length); } function readString(data, off, size, enc) { if (enc == null) enc = 'binary'; enforce(Buffer.isBuffer(data), 'data', 'buffer'); enforce((off >>> 0) === off, 'off', 'integer'); enforce((size >>> 0) === size, 'size', 'integer'); enforce(typeof enc === 'string', 'enc', 'string'); if (off + size > data.length) throw new EncodingError(off, 'Out of bounds read'); return data.toString(enc, off, off + size); } function writeString(data, str, off, enc) { if (enc == null) enc = 'binary'; enforce(Buffer.isBuffer(data), 'data', 'buffer'); enforce(typeof str === 'string', 'str', 'string'); enforce((off >>> 0) === off, 'off', 'integer'); enforce(typeof enc === 'string', 'enc', 'string'); if (str.length === 0) return 0; const size = Buffer.byteLength(str, enc); if (off + size > data.length) throw new EncodingError(off, 'Out of bounds write'); return data.write(str, off, enc); } function realloc(data, size) { enforce(Buffer.isBuffer(data), 'data', 'buffer'); const buf = Buffer.allocUnsafeSlow(size); data.copy(buf, 0); return buf; } function copy(data) { enforce(Buffer.isBuffer(data), 'data', 'buffer'); return realloc(data, data.length); } function concat(a, b) { enforce(Buffer.isBuffer(a), 'a', 'buffer'); enforce(Buffer.isBuffer(b), 'b', 'buffer'); const size = a.length + b.length; const buf = Buffer.allocUnsafeSlow(size); a.copy(buf, 0); b.copy(buf, a.length); return buf; } /* * Size Helpers */ function sizeVarBytes(data) { enforce(Buffer.isBuffer(data), 'data', 'buffer'); return sizeVarint(data.length) + data.length; } function sizeVarlen(len) { return sizeVarint(len) + len; } function sizeVarString(str, enc) { if (enc == null) enc = 'binary'; enforce(typeof str === 'string', 'str', 'string'); enforce(typeof enc === 'string', 'enc', 'string'); if (str.length === 0) return 1; const len = Buffer.byteLength(str, enc); return sizeVarint(len) + len; } /* * Helpers */ function isSafe(hi, lo) { if (hi < 0) { hi = ~hi; if (lo === 0) hi += 1; } return (hi & 0xffe00000) === 0; } function write64(dst, num, off, be) { let neg = false; if (num < 0) { num = -num; neg = true; } let hi = (num * HI) | 0; let lo = num | 0; if (neg) { if (lo === 0) { hi = (~hi + 1) | 0; } else { hi = ~hi; lo = ~lo + 1; } } if (be) { off = writeI32BE(dst, hi, off); off = writeI32BE(dst, lo, off); } else { off = writeI32(dst, lo, off); off = writeI32(dst, hi, off); } return off; } function write56(dst, num, off, be) { let neg = false; if (num < 0) { num = -num; neg = true; } let hi = (num * HI) | 0; let lo = num | 0; if (neg) { if (lo === 0) { hi = (~hi + 1) | 0; } else { hi = ~hi; lo = ~lo + 1; } } if (be) { off = writeI24BE(dst, hi, off); off = writeI32BE(dst, lo, off); } else { off = writeI32(dst, lo, off); off = writeI24(dst, hi, off); } return off; } class Varint { constructor(size, value) { this.size = size; this.value = value; } } function isNumber(num) { return typeof num === 'number' && isFinite(num); } function checkRead(value, offset) { if (!value) throw new EncodingError(offset, 'Out of bounds read', checkRead); } function check(value, offset, reason) { if (!value) throw new EncodingError(offset, reason, check); } /* * Expose */ exports.readU = readU; exports.readU64 = readU64; exports.readU56 = readU56; exports.readU48 = readU48; exports.readU40 = readU40; exports.readU32 = readU32; exports.readU24 = readU24; exports.readU16 = readU16; exports.readU8 = readU8; exports.readUBE = readUBE; exports.readU64BE = readU64BE; exports.readU56BE = readU56BE; exports.readU48BE = readU48BE; exports.readU40BE = readU40BE; exports.readU32BE = readU32BE; exports.readU24BE = readU24BE; exports.readU16BE = readU16BE; exports.readI = readI; exports.readI64 = readI64; exports.readI56 = readI56; exports.readI48 = readI48; exports.readI40 = readI40; exports.readI32 = readI32; exports.readI24 = readI24; exports.readI16 = readI16; exports.readI8 = readI8; exports.readIBE = readIBE; exports.readI64BE = readI64BE; exports.readI56BE = readI56BE; exports.readI48BE = readI48BE; exports.readI40BE = readI40BE; exports.readI32BE = readI32BE; exports.readI24BE = readI24BE; exports.readI16BE = readI16BE; exports.readFloat = readFloat; exports.readFloatBE = readFloatBE; exports.readDouble = readDouble; exports.readDoubleBE = readDoubleBE; exports.writeU = writeU; exports.writeU64 = writeU64; exports.writeU56 = writeU56; exports.writeU48 = writeU48; exports.writeU40 = writeU40; exports.writeU32 = writeU32; exports.writeU24 = writeU24; exports.writeU16 = writeU16; exports.writeU8 = writeU8; exports.writeUBE = writeUBE; exports.writeU64BE = writeU64BE; exports.writeU56BE = writeU56BE; exports.writeU48BE = writeU48BE; exports.writeU40BE = writeU40BE; exports.writeU32BE = writeU32BE; exports.writeU24BE = writeU24BE; exports.writeU16BE = writeU16BE; exports.writeI = writeI; exports.writeI64 = writeI64; exports.writeI56 = writeI56; exports.writeI48 = writeI48; exports.writeI40 = writeI40; exports.writeI32 = writeI32; exports.writeI24 = writeI24; exports.writeI16 = writeI16; exports.writeI8 = writeI8; exports.writeIBE = writeIBE; exports.writeI64BE = writeI64BE; exports.writeI56BE = writeI56BE; exports.writeI48BE = writeI48BE; exports.writeI40BE = writeI40BE; exports.writeI32BE = writeI32BE; exports.writeI24BE = writeI24BE; exports.writeI16BE = writeI16BE; exports.writeFloat = writeFloat; exports.writeFloatBE = writeFloatBE; exports.writeDouble = writeDouble; exports.writeDoubleBE = writeDoubleBE; exports.readVarint = readVarint; exports.writeVarint = writeVarint; exports.sizeVarint = sizeVarint; exports.readVarint2 = readVarint2; exports.writeVarint2 = writeVarint2; exports.sizeVarint2 = sizeVarint2; exports.sliceBytes = sliceBytes; exports.readBytes = readBytes; exports.writeBytes = writeBytes; exports.readString = readString; exports.writeString = writeString; exports.realloc = realloc; exports.copy = copy; exports.concat = concat; exports.sizeVarBytes = sizeVarBytes; exports.sizeVarlen = sizeVarlen; exports.sizeVarString = sizeVarString; }], [/* 6 */ 'bufio', '/lib/enforce.js', function(exports, module, __filename, __dirname, __meta) { /*! * enforce.js - type enforcement for bcoin * Copyright (c) 2014-2017, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcoin */ 'use strict'; /* * Enforce */ function enforce(value, name, type) { if (!value) { const err = new TypeError(`'${name}' must be a(n) ${type}.`); if (Error.captureStackTrace) Error.captureStackTrace(err, enforce); throw err; } } /* * Expose */ module.exports = enforce; }], [/* 7 */ 'bufio', '/lib/error.js', function(exports, module, __filename, __dirname, __meta) { /*! * error.js - encoding error 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'; /** * Encoding Error * @extends {Error} */ class EncodingError extends Error { /** * Create an encoding error. * @constructor * @param {Number} offset * @param {String} reason */ constructor(offset, reason, start) { super(); this.type = 'EncodingError'; this.name = 'EncodingError'; this.code = 'ERR_ENCODING'; this.message = `${reason} (offset=${offset}).`; if (Error.captureStackTrace) Error.captureStackTrace(this, start || EncodingError); } } /* * Expose */ module.exports = EncodingError; }], [/* 8 */ 'bufio', '/lib/reader.js', function(exports, module, __filename, __dirname, __meta) { /*! * reader.js - buffer reader 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'; const enforce = __node_require__(6 /* './enforce' */); const encoding = __node_require__(5 /* './encoding' */); const EncodingError = __node_require__(7 /* './error' */); /* * Constants */ const EMPTY = Buffer.alloc(0); /** * Buffer Reader */ class BufferReader { /** * Create a buffer reader. * @constructor * @param {Buffer} data * @param {Boolean?} zeroCopy - Do not reallocate buffers when * slicing. Note that this can lead to memory leaks if not used * carefully. */ constructor(data, zeroCopy = false) { enforce(Buffer.isBuffer(data), 'data', 'buffer'); enforce(typeof zeroCopy === 'boolean', 'zeroCopy', 'boolean'); this.data = data; this.offset = 0; this.zeroCopy = zeroCopy; this.stack = []; } /** * Assertion. * @param {Number} size */ check(size) { if (this.offset + size > this.data.length) throw new EncodingError(this.offset, 'Out of bounds read', this.check); } /** * Get total size of passed-in Buffer. * @returns {Buffer} */ getSize() { return this.data.length; } /** * Calculate number of bytes left to read. * @returns {Number} */ left() { this.check(0); return this.data.length - this.offset; } /** * Seek to a position to read from by offset. * @param {Number} off - Offset (positive or negative). */ seek(off) { enforce(Number.isSafeInteger(off), 'off', 'integer'); if (this.offset + off < 0) throw new EncodingError(this.offset, 'Out of bounds read'); this.check(off); this.offset += off; return this; } /** * Mark the current starting position. */ start() { this.stack.push(this.offset); return this.offset; } /** * Stop reading. Pop the start position off the stack * and calculate the size of the data read. * @returns {Number} Size. * @throws on empty stack. */ end() { if (this.stack.length === 0) throw new Error('Cannot end without a stack item.'); const start = this.stack.pop(); return this.offset - start; } /** * Stop reading. Pop the start position off the stack * and return the data read. * @param {Bolean?} zeroCopy - Do a fast buffer * slice instead of allocating a new buffer (warning: * may cause memory leaks if not used with care). * @returns {Buffer} Data read. * @throws on empty stack. */ endData(zeroCopy = false) { enforce(typeof zeroCopy === 'boolean', 'zeroCopy', 'boolean'); if (this.stack.length === 0) throw new Error('Cannot end without a stack item.'); const start = this.stack.pop(); const end = this.offset; const size = end - start; const data = this.data; if (size === data.length) return data; if (this.zeroCopy || zeroCopy) return data.slice(start, end); const ret = Buffer.allocUnsafeSlow(size); data.copy(ret, 0, start, end); return ret; } /** * Destroy the reader. Remove references to the data. */ destroy() { this.data = EMPTY; this.offset = 0; this.stack.length = 0; return this; } /** * Read uint8. * @returns {Number} */ readU8() { this.check(1); const ret = this.data[this.offset]; this.offset += 1; return ret; } /** * Read uint16le. * @returns {Number} */ readU16() { this.check(2); const ret = encoding.readU16(this.data, this.offset); this.offset += 2; return ret; } /** * Read uint16be. * @returns {Number} */ readU16BE() { this.check(2); const ret = encoding.readU16BE(this.data, this.offset); this.offset += 2; return ret; } /** * Read uint24le. * @returns {Number} */ readU24() { this.check(3); const ret = encoding.readU24(this.data, this.offset); this.offset += 3; return ret; } /** * Read uint24be. * @returns {Number} */ readU24BE() { this.check(3); const ret = encoding.readU24BE(this.data, this.offset); this.offset += 3; return ret; } /** * Read uint32le. * @returns {Number} */ readU32() { this.check(4); const ret = encoding.readU32(this.data, this.offset); this.offset += 4; return ret; } /** * Read uint32be. * @returns {Number} */ readU32BE() { this.check(4); const ret = encoding.readU32BE(this.data, this.offset); this.offset += 4; return ret; } /** * Read uint40le. * @returns {Number} */ readU40() { this.check(5); const ret = encoding.readU40(this.data, this.offset); this.offset += 5; return ret; } /** * Read uint40be. * @returns {Number} */ readU40BE() { this.check(5); const ret = encoding.readU40BE(this.data, this.offset); this.offset += 5; return ret; } /** * Read uint48le. * @returns {Number} */ readU48() { this.check(6); const ret = encoding.readU48(this.data, this.offset); this.offset += 6; return ret; } /** * Read uint48be. * @returns {Number} */ readU48BE() { this.check(6); const ret = encoding.readU48BE(this.data, this.offset); this.offset += 6; return ret; } /** * Read uint56le. * @returns {Number} */ readU56() { this.check(7); const ret = encoding.readU56(this.data, this.offset); this.offset += 7; return ret; } /** * Read uint56be. * @returns {Number} */ readU56BE() { this.check(7); const ret = encoding.readU56BE(this.data, this.offset); this.offset += 7; return ret; } /** * Read uint64le as a js number. * @returns {Number} * @throws on num > MAX_SAFE_INTEGER */ readU64() { this.check(8); const ret = encoding.readU64(this.data, this.offset); this.offset += 8; return ret; } /** * Read uint64be as a js number. * @returns {Number} * @throws on num > MAX_SAFE_INTEGER */ readU64BE() { this.check(8); const ret = encoding.readU64BE(this.data, this.offset); this.offset += 8; return ret; } /** * Read int8. * @returns {Number} */ readI8() { this.check(1); const ret = encoding.readI8(this.data, this.offset); this.offset += 1; return ret; } /** * Read int16le. * @returns {Number} */ readI16() { this.check(2); const ret = encoding.readI16(this.data, this.offset); this.offset += 2; return ret; } /** * Read int16be. * @returns {Number} */ readI16BE() { this.check(2); const ret = encoding.readI16BE(this.data, this.offset); this.offset += 2; return ret; } /** * Read int24le. * @returns {Number} */ readI24() { this.check(3); const ret = encoding.readI24(this.data, this.offset); this.offset += 3; return ret; } /** * Read int24be. * @returns {Number} */ readI24BE() { this.check(3); const ret = encoding.readI24BE(this.data, this.offset); this.offset += 3; return ret; } /** * Read int32le. * @returns {Number} */ readI32() { this.check(4); const ret = encoding.readI32(this.data, this.offset); this.offset += 4; return ret; } /** * Read int32be. * @returns {Number} */ readI32BE() { this.check(4); const ret = encoding.readI32BE(this.data, this.offset); this.offset += 4; return ret; } /** * Read int40le. * @returns {Number} */ readI40() { this.check(5); const ret = encoding.readI40(this.data, this.offset); this.offset += 5; return ret; } /** * Read int40be. * @returns {Number} */ readI40BE() { this.check(5); const ret = encoding.readI40BE(this.data, this.offset); this.offset += 5; return ret; } /** * Read int48le. * @returns {Number} */ readI48() { this.check(6); const ret = encoding.readI48(this.data, this.offset); this.offset += 6; return ret; } /** * Read int48be. * @returns {Number} */ readI48BE() { this.check(6); const ret = encoding.readI48BE(this.data, this.offset); this.offset += 6; return ret; } /** * Read int56le. * @returns {Number} */ readI56() { this.check(7); const ret = encoding.readI56(this.data, this.offset); this.offset += 7; return ret; } /** * Read int56be. * @returns {Number} */ readI56BE() { this.check(7); const ret = encoding.readI56BE(this.data, this.offset); this.offset += 7; return ret; } /** * Read int64le as a js number. * @returns {Number} * @throws on num > MAX_SAFE_INTEGER */ readI64() { this.check(8); const ret = encoding.readI64(this.data, this.offset); this.offset += 8; return ret; } /** * Read int64be as a js number. * @returns {Number} * @throws on num > MAX_SAFE_INTEGER */ readI64BE() { this.check(8); const ret = encoding.readI64BE(this.data, this.offset); this.offset += 8; return ret; } /** * Read float le. * @returns {Number} */ readFloat() { this.check(4); const ret = encoding.readFloat(this.data, this.offset); this.offset += 4; return ret; } /** * Read float be. * @returns {Number} */ readFloatBE() { this.check(4); const ret = encoding.readFloatBE(this.data, this.offset); this.offset += 4; return ret; } /** * Read double float le. * @returns {Number} */ readDouble() { this.check(8); const ret = encoding.readDouble(this.data, this.offset); this.offset += 8; return ret; } /** * Read double float be. * @returns {Number} */ readDoubleBE() { this.check(8); const ret = encoding.readDoubleBE(this.data, this.offset); this.offset += 8; return ret; } /** * Read a varint. * @returns {Number} */ readVarint() { const {size, value} = encoding.readVarint(this.data, this.offset); this.offset += size; return value; } /** * Read a varint (type 2). * @returns {Number} */ readVarint2() { const {size, value} = encoding.readVarint2(this.data, this.offset); this.offset += size; return value; } /** * Read N bytes (will do a fast slice if zero copy). * @param {Number} size * @param {Bolean?} zeroCopy - Do a fast buffer * slice instead of allocating a new buffer (warning: * may cause memory leaks if not used with care). * @returns {Buffer} */ readBytes(size, zeroCopy = false) { enforce((size >>> 0) === size, 'size', 'integer'); enforce(typeof zeroCopy === 'boolean', 'zeroCopy', 'boolean'); this.check(size); let ret; if (this.zeroCopy || zeroCopy) { ret = this.data.slice(this.offset, this.offset + size); } else { ret = Buffer.allocUnsafeSlow(size); this.data.copy(ret, 0, this.offset, this.offset + size); } this.offset += size; return ret; } /** * Read a varint number of bytes (will do a fast slice if zero copy). * @param {Bolean?} zeroCopy - Do a fast buffer * slice instead of allocating a new buffer (warning: * may cause memory leaks if not used with care). * @returns {Buffer} */ readVarBytes(zeroCopy = false) { return this.readBytes(this.readVarint(), zeroCopy); } /** * Slice N bytes and create a child reader. * @param {Number} size * @returns {BufferReader} */ readChild(size) { enforce((size >>> 0) === size, 'size', 'integer'); this.check(size); const data = this.data.slice(0, this.offset + size); const br = new this.constructor(data); br.offset = this.offset; this.offset += size; return br; } /** * Read a string. * @param {Number} size * @param {String} enc - Any buffer-supported encoding. * @returns {String} */ readString(size, enc) { if (enc == null) enc = 'binary'; enforce((size >>> 0) === size, 'size', 'integer'); enforce(typeof enc === 'string', 'enc', 'string'); this.check(size); const ret = this.data.toString(enc, this.offset, this.offset + size); this.offset += size; return ret; } /** * Read a 32-byte hash. * @param {String} enc - `"hex"` or `null`. * @returns {Hash|Buffer} */ readHash(enc) { if (enc) return this.readString(32, enc); return this.readBytes(32); } /** * Read string of a varint length. * @param {String} enc - Any buffer-supported encoding. * @param {Number?} limit - Size limit. * @returns {String} */ readVarString(enc, limit = 0) { if (enc == null) enc = 'binary'; enforce(typeof enc === 'string', 'enc', 'string'); enforce((limit >>> 0) === limit, 'limit', 'integer'); const size = this.readVarint(); if (limit !== 0 && size > limit) throw new EncodingError(this.offset, 'String exceeds limit'); return this.readString(size, enc); } /** * Read a null-terminated string. * @param {String} enc - Any buffer-supported encoding. * @returns {String} */ readNullString(enc) { if (enc == null) enc = 'binary'; enforce(typeof enc === 'string', 'enc', 'string'); let i = this.offset; for (; i < this.data.length; i++) { if (this.data[i] === 0) break; } if (i === this.data.length) throw new EncodingError(this.offset, 'No NUL terminator'); const ret = this.readString(i - this.offset, enc); this.offset = i + 1; return ret; } /** * Create a checksum from the last start position. * @param {Function} hash * @returns {Number} Checksum. */ createChecksum(hash) { if (!hash || typeof hash.digest !== 'function') enforce(typeof hash === 'function', 'hash', 'function'); let start = 0; if (this.stack.length > 0) start = this.stack[this.stack.length - 1]; const data = this.data.slice(start, this.offset); const raw = hash.digest ? hash.digest(data) : hash(data); return encoding.readU32(raw, 0); } /** * Verify a 4-byte checksum against a calculated checksum. * @param {Function} hash * @returns {Number} checksum * @throws on bad checksum */ verifyChecksum(hash) { const checksum = this.createChecksum(hash); const expect = this.readU32(); if (checksum !== expect) throw new EncodingError(this.offset, 'Checksum mismatch'); return checksum; } } /* * Expose */ module.exports = BufferReader; }], [/* 9 */ 'bufio', '/lib/writer.js', function(exports, module, __filename, __dirname, __meta) { /*! * writer.js - buffer writer 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'; const enforce = __node_require__(6 /* './enforce' */); const encoding = __node_require__(5 /* './encoding' */); const EncodingError = __node_require__(7 /* './error' */); /* * Constants */ const SEEK = 0; const U8 = 1; const U16 = 2; const U16BE = 3; const U24 = 4; const U24BE = 5; const U32 = 6; const U32BE = 7; const U40 = 8; const U40BE = 9; const U48 = 10; const U48BE = 11; const U56 = 12; const U56BE = 13; const U64 = 14; const U64BE = 15; const I8 = 16; const I16 = 17; const I16BE = 18; const I24 = 19; const I24BE = 20; const I32 = 21; const I32BE = 22; const I40 = 23; const I40BE = 24; const I48 = 25; const I48BE = 26; const I56 = 27; const I56BE = 28; const I64 = 29; const I64BE = 30; const FL = 31; const FLBE = 32; const DBL = 33; const DBLBE = 34; const VARINT = 35; const VARINT2 = 36; const BYTES = 37; const STR = 38; const CHECKSUM = 39; const FILL = 40; /** * Buffer Writer */ class BufferWriter { /** * Create a buffer writer. * @constructor */ constructor() { this.ops = []; this.offset = 0; } /** * Allocate and render the final buffer. * @returns {Buffer} Rendered buffer. */ render() { const data = Buffer.allocUnsafeSlow(this.offset); let off = 0; for (const op of this.ops) { switch (op.type) { case SEEK: off += op.value; break; case U8: off = encoding.writeU8(data, op.value, off); break; case U16: off = encoding.writeU16(data, op.value, off); break; case U16BE: off = encoding.writeU16BE(data, op.value, off); break; case U24: off = encoding.writeU24(data, op.value, off); break; case U24BE: off = encoding.writeU24BE(data, op.value, off); break; case U32: off = encoding.writeU32(data, op.value, off); break; case U32BE: off = encoding.writeU32BE(data, op.value, off); break; case U40: off = encoding.writeU40(data, op.value, off); break; case U40BE: off = encoding.writeU40BE(data, op.value, off); break; case U48: off = encoding.writeU48(data, op.value, off); break; case U48BE: off = encoding.writeU48BE(data, op.value, off); break; case U56: off = encoding.writeU56(data, op.value, off); break; case U56BE: off = encoding.writeU56BE(data, op.value, off); break; case U64: off = encoding.writeU64(data, op.value, off); break; case U64BE: off = encoding.writeU64BE(data, op.value, off); break; case I8: off = encoding.writeI8(data, op.value, off); break; case I16: off = encoding.writeI16(data, op.value, off); break; case I16BE: off = encoding.writeI16BE(data, op.value, off); break; case I24: off = encoding.writeI24(data, op.value, off); break; case I24BE: off = encoding.writeI24BE(data, op.value, off); break; case I32: off = encoding.writeI32(data, op.value, off); break; case I32BE: off = encoding.writeI32BE(data, op.value, off); break; case I40: off = encoding.writeI40(data, op.value, off); break; case I40BE: off = encoding.writeI40BE(data, op.value, off); break; case I48: off = encoding.writeI48(data, op.value, off); break; case I48BE: off = encoding.writeI48BE(data, op.value, off); break; case I56: off = encoding.writeI56(data, op.value, off); break; case I56BE: off = encoding.writeI56BE(data, op.value, off); break; case I64: off = encoding.writeI64(data, op.value, off); break; case I64BE: off = encoding.writeI64BE(data, op.value, off); break; case FL: off = encoding.writeFloat(data, op.value, off); break; case FLBE: off = encoding.writeFloatBE(data, op.value, off); break; case DBL: off = encoding.writeDouble(data, op.value, off); break; case DBLBE: off = encoding.writeDoubleBE(data, op.value, off); break; case VARINT: off = encoding.writeVarint(data, op.value, off); break; case VARINT2: off = encoding.writeVarint2(data, op.value, off); break; case BYTES: off += op.data.copy(data, off); break; case STR: off += data.write(op.value, off, op.enc); break; case CHECKSUM: off += op.func(data.slice(0, off)).copy(data, off, 0, 4); break; case FILL: data.fill(op.value, off, off + op.size); off += op.size; break; default: throw new Error('Invalid type.'); } } if (off !== data.length) throw new EncodingError(off, 'Out of bounds write'); this.destroy(); return data; } /** * Get size of data written so far. * @returns {Number} */ getSize() { return this.offset; } /** * Seek to relative offset. * @param {Number} offset */ seek(off) { enforce(Number.isSafeInteger(off), 'off', 'integer'); if (this.offset + off < 0) throw new EncodingError(this.offset, 'Out of bounds write'); this.offset += off; this.ops.push(new NumberOp(SEEK, off)); return this; } /** * Destroy the buffer writer. Remove references to `ops`. */ destroy() { this.ops.length = 0; this.offset = 0; return this; } /** * Write uint8. * @param {Number} value */ writeU8(value) { this.offset += 1; this.ops.push(new NumberOp(U8, value)); return this; } /** * Write uint16le. * @param {Number} value */ writeU16(value) { this.offset += 2; this.ops.push(new NumberOp(U16, value)); return this; } /** * Write uint16be. * @param {Number} value */ writeU16BE(value) { this.offset += 2; this.ops.push(new NumberOp(U16BE, value)); return this; } /** * Write uint24le. * @param {Number} value */ writeU24(value) { this.offset += 3; this.ops.push(new NumberOp(U24, value)); return this; } /** * Write uint24be. * @param {Number} value */ writeU24BE(value) { this.offset += 3; this.ops.push(new NumberOp(U24BE, value)); return this; } /** * Write uint32le. * @param {Number} value */ writeU32(value) { this.offset += 4; this.ops.push(new NumberOp(U32, value)); return this; } /** * Write uint32be. * @param {Number} value */ writeU32BE(value) { this.offset += 4; this.ops.push(new NumberOp(U32BE, value)); return this; } /** * Write uint40le. * @param {Number} value */ writeU40(value) { this.offset += 5; this.ops.push(new NumberOp(U40, value)); return this; } /** * Write uint40be. * @param {Number} value */ writeU40BE(value) { this.offset += 5; this.ops.push(new NumberOp(U40BE, value)); return this; } /** * Write uint48le. * @param {Number} value */ writeU48(value) { this.offset += 6; this.ops.push(new NumberOp(U48, value)); return this; } /** * Write uint48be. * @param {Number} value */ writeU48BE(value) { this.offset += 6; this.ops.push(new NumberOp(U48BE, value)); return this; } /** * Write uint56le. * @param {Number} value */ writeU56(value) { this.offset += 7; this.ops.push(new NumberOp(U56, value)); return this; } /** * Write uint56be. * @param {Number} value */ writeU56BE(value) { this.offset += 7; this.ops.push(new NumberOp(U56BE, value)); return this; } /** * Write uint64le. * @param {Number} value */ writeU64(value) { this.offset += 8; this.ops.push(new NumberOp(U64, value)); return this; } /** * Write uint64be. * @param {Number} value */ writeU64BE(value) { this.offset += 8; this.ops.push(new NumberOp(U64BE, value)); return this; } /** * Write int8. * @param {Number} value */ writeI8(value) { this.offset += 1; this.ops.push(new NumberOp(I8, value)); return this; } /** * Write int16le. * @param {Number} value */ writeI16(value) { this.offset += 2; this.ops.push(new NumberOp(I16, value)); return this; } /** * Write int16be. * @param {Number} value */ writeI16BE(value) { this.offset += 2; this.ops.push(new NumberOp(I16BE, value)); return this; } /** * Write int24le. * @param {Number} value */ writeI24(value) { this.offset += 3; this.ops.push(new NumberOp(I24, value)); return this; } /** * Write int24be. * @param {Number} value */ writeI24BE(value) { this.offset += 3; this.ops.push(new NumberOp(I24BE, value)); return this; } /** * Write int32le. * @param {Number} value */ writeI32(value) { this.offset += 4; this.ops.push(new NumberOp(I32, value)); return this; } /** * Write int32be. * @param {Number} value */ writeI32BE(value) { this.offset += 4; this.ops.push(new NumberOp(I32BE, value)); return this; } /** * Write int40le. * @param {Number} value */ writeI40(value) { this.offset += 5; this.ops.push(new NumberOp(I40, value)); return this; } /** * Write int40be. * @param {Number} value */ writeI40BE(value) { this.offset += 5; this.ops.push(new NumberOp(I40BE, value)); return this; } /** * Write int48le. * @param {Number} value */ writeI48(value) { this.offset += 6; this.ops.push(new NumberOp(I48, value)); return this; } /** * Write int48be. * @param {Number} value */ writeI48BE(value) { this.offset += 6; this.ops.push(new NumberOp(I48BE, value)); return this; } /** * Write int56le. * @param {Number} value */ writeI56(value) { this.offset += 7; this.ops.push(new NumberOp(I56, value)); return this; } /** * Write int56be. * @param {Number} value */ writeI56BE(value) { this.offset += 7; this.ops.push(new NumberOp(I56BE, value)); return this; } /** * Write int64le. * @param {Number} value */ writeI64(value) { this.offset += 8; this.ops.push(new NumberOp(I64, value)); return this; } /** * Write int64be. * @param {Number} value */ writeI64BE(value) { this.offset += 8; this.ops.push(new NumberOp(I64BE, value)); return this; } /** * Write float le. * @param {Number} value */ writeFloat(value) { this.offset += 4; this.ops.push(new NumberOp(FL, value)); return this; } /** * Write float be. * @param {Number} value */ writeFloatBE(value) { this.offset += 4; this.ops.push(new NumberOp(FLBE, value)); return this; } /** * Write double le. * @param {Number} value */ writeDouble(value) { this.offset += 8; this.ops.push(new NumberOp(DBL, value)); return this; } /** * Write double be. * @param {Number} value */ writeDoubleBE(value) { this.offset += 8; this.ops.push(new NumberOp(DBLBE, value)); return this; } /** * Write a varint. * @param {Number} value */ writeVarint(value) { this.offset += encoding.sizeVarint(value); this.ops.push(new NumberOp(VARINT, value)); return this; } /** * Write a varint (type 2). * @param {Number} value */ writeVarint2(value) { this.offset += encoding.sizeVarint2(value); this.ops.push(new NumberOp(VARINT2, value)); return this; } /** * Write bytes. * @param {Buffer} value */ writeBytes(value) { enforce(Buffer.isBuffer(value), 'value', 'buffer'); if (value.length === 0) return this; this.offset += value.length; this.ops.push(new BufferOp(BYTES, value)); return this; } /** * Write bytes with a varint length before them. * @param {Buffer} value */ writeVarBytes(value) { enforce(Buffer.isBuffer(value), 'value', 'buffer'); this.offset += encoding.sizeVarint(value.length); this.ops.push(new NumberOp(VARINT, value.length)); if (value.length === 0) return this; this.offset += value.length; this.ops.push(new BufferOp(BYTES, value)); return this; } /** * Copy bytes. * @param {Buffer} value * @param {Number} start * @param {Number} end */ copy(value, start, end) { enforce(Buffer.isBuffer(value), 'value', 'buffer'); enforce((start >>> 0) === start, 'start', 'integer'); enforce((end >>> 0) === end, 'end', 'integer'); enforce(end >= start, 'start', 'integer'); const buf = value.slice(start, end); this.writeBytes(buf); return this; } /** * Write string to buffer. * @param {String} value * @param {String?} enc - Any buffer-supported encoding. */ writeString(value, enc) { if (enc == null) enc = 'binary'; enforce(typeof value === 'string', 'value', 'string'); enforce(typeof enc === 'string', 'enc', 'string'); if (value.length === 0) return this; this.offset += Buffer.byteLength(value, enc); this.ops.push(new StringOp(STR, value, enc)); return this; } /** * Write a 32 byte hash. * @param {Hash} value */ writeHash(value) { if (typeof value !== 'string') { enforce(Buffer.isBuffer(value), 'value', 'buffer'); enforce(value.length === 32, 'value', '32-byte hash'); this.writeBytes(value); return this; } enforce(value.length === 64, 'value', '32-byte hash'); this.writeString(value, 'hex'); return this; } /** * Write a string with a varint length before it. * @param {String} * @param {String?} enc - Any buffer-supported encoding. */ writeVarString(value, enc) { if (enc == null) enc = 'binary'; enforce(typeof value === 'string', 'value', 'string'); enforce(typeof enc === 'string', 'enc', 'string'); if (value.length === 0) { this.ops.push(new NumberOp(VARINT, 0)); return this; } const size = Buffer.byteLength(value, enc); this.offset += encoding.sizeVarint(size); this.offset += size; this.ops.push(new NumberOp(VARINT, size)); this.ops.push(new StringOp(STR, value, enc)); return this; } /** * Write a null-terminated string. * @param {String|Buffer} * @param {String?} enc - Any buffer-supported encoding. */ writeNullString(value, enc) { this.writeString(value, enc); this.writeU8(0); return this; } /** * Calculate and write a checksum for the data written so far. * @param {Function} hash */ writeChecksum(hash) { if (hash && typeof hash.digest === 'function') hash = hash.digest.bind(hash); enforce(typeof hash === 'function', 'hash', 'function'); this.offset += 4; this.ops.push(new FunctionOp(CHECKSUM, hash)); return this; } /** * Fill N bytes with value. * @param {Number} value * @param {Number} size */ fill(value, size) { enforce((value & 0xff) === value, 'value', 'byte'); enforce((size >>> 0) === size, 'size', 'integer'); if (size === 0) return this; this.offset += size; this.ops.push(new FillOp(FILL, value, size)); return this; } } /* * Helpers */ class WriteOp { constructor(type) { this.type = type; } } class NumberOp extends WriteOp { constructor(type, value) { super(type); this.value = value; } } class BufferOp extends WriteOp { constructor(type, data) { super(type); this.data = data; } } class StringOp extends WriteOp { constructor(type, value, enc) { super(type); this.value = value; this.enc = enc; } } class FunctionOp extends WriteOp { constructor(type, func) { super(type); this.func = func; } } class FillOp extends WriteOp { constructor(type, value, size) { super(type); this.value = value; this.size = size; } } /* * Expose */ module.exports = BufferWriter; }], [/* 10 */ 'bufio', '/lib/staticwriter.js', function(exports, module, __filename, __dirname, __meta) { /*! * staticwriter.js - buffer writer for bcoin * Copyright (c) 2014-2017, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcoin */ 'use strict'; const enforce = __node_require__(6 /* './enforce' */); const encoding = __node_require__(5 /* './encoding' */); const EncodingError = __node_require__(7 /* './error' */); /* * Constants */ const EMPTY = Buffer.alloc(0); const POOL_SIZE = 100 << 10; let POOL = null; /** * Statically Allocated Writer */ class StaticWriter { /** * Statically allocated buffer writer. * @constructor * @param {Number|Buffer} options */ constructor(options) { this.data = EMPTY; this.offset = 0; if (options != null) this.init(options); } /** * Assertion. * @param {Number} size */ check(size) { if (this.offset + size > this.data.length) throw new EncodingError(this.offset, 'Out of bounds write', this.check); } /** * Initialize options. * @param {Object} options */ init(options) { if (Buffer.isBuffer(options)) { this.data = options; this.offset = 0; return this; } enforce((options >>> 0) === options, 'size', 'integer'); this.data = Buffer.allocUnsafeSlow(options); this.offset = 0; return this; } /** * Allocate writer from preallocated 100kb pool. * @param {Number} size * @returns {StaticWriter} */ static pool(size) { enforce((size >>> 0) === size, 'size', 'integer'); if (size <= POOL_SIZE) { if (!POOL) POOL = Buffer.allocUnsafeSlow(POOL_SIZE); const bw = new StaticWriter(); bw.data = POOL.slice(0, size); return bw; } return new StaticWriter(size); } /** * Allocate and render the final buffer. * @returns {Buffer} Rendered buffer. */ render() { const {data, offset} = this; if (offset !== data.length) throw new EncodingError(offset, 'Out of bounds write'); this.destroy(); return data; } /** * Slice the final buffer at written offset. * @returns {Buffer} Rendered buffer. */ slice() { const {data, offset} = this; if (offset > data.length) throw new EncodingError(offset, 'Out of bounds write'); this.destroy(); return data.slice(0, offset); } /** * Get size of data written so far. * @returns {Number} */ getSize() { return this.offset; } /** * Seek to relative offset. * @param {Number} off */ seek(off) { enforce(Number.isSafeInteger(off), 'off', 'integer'); if (this.offset + off < 0) throw new EncodingError(this.offset, 'Out of bounds write'); this.check(off); this.offset += off; return this; } /** * Destroy the buffer writer. */ destroy() { this.data = EMPTY; this.offset = 0; return this; } /** * Write uint8. * @param {Number} value */ writeU8(value) { this.check(1); this.offset = encoding.writeU8(this.data, value, this.offset); return this; } /** * Write uint16le. * @param {Number} value */ writeU16(value) { this.check(2); this.offset = encoding.writeU16(this.data, value, this.offset); return this; } /** * Write uint16be. * @param {Number} value */ writeU16BE(value) { this.check(2); this.offset = encoding.writeU16BE(this.data, value, this.offset); return this; } /** * Write uint24le. * @param {Number} value */ writeU24(value) { this.check(3); this.offset = encoding.writeU24(this.data, value, this.offset); return this; } /** * Write uint24be. * @param {Number} value */ writeU24BE(value) { this.check(3); this.offset = encoding.writeU24BE(this.data, value, this.offset); return this; } /** * Write uint32le. * @param {Number} value */ writeU32(value) { this.check(4); this.offset = encoding.writeU32(this.data, value, this.offset); return this; } /** * Write uint32be. * @param {Number} value */ writeU32BE(value) { this.check(4); this.offset = encoding.writeU32BE(this.data, value, this.offset); return this; } /** * Write uint40le. * @param {Number} value */ writeU40(value) { this.check(5); this.offset = encoding.writeU40(this.data, value, this.offset); return this; } /** * Write uint40be. * @param {Number} value */ writeU40BE(value) { this.check(5); this.offset = encoding.writeU40BE(this.data, value, this.offset); return this; } /** * Write uint48le. * @param {Number} value */ writeU48(value) { this.check(6); this.offset = encoding.writeU48(this.data, value, this.offset); return this; } /** * Write uint48be. * @param {Number} value */ writeU48BE(value) { this.check(6); this.offset = encoding.writeU48BE(this.data, value, this.offset); return this; } /** * Write uint56le. * @param {Number} value */ writeU56(value) { this.check(7); this.offset = encoding.writeU56(this.data, value, this.offset); return this; } /** * Write uint56be. * @param {Number} value */ writeU56BE(value) { this.check(7); this.offset = encoding.writeU56BE(this.data, value, this.offset); return this; } /** * Write uint64le. * @param {Number} value */ writeU64(value) { this.check(8); this.offset = encoding.writeU64(this.data, value, this.offset); return this; } /** * Write uint64be. * @param {Number} value */ writeU64BE(value) { this.check(8); this.offset = encoding.writeU64BE(this.data, value, this.offset); return this; } /** * Write int8. * @param {Number} value */ writeI8(value) { this.check(1); this.offset = encoding.writeI8(this.data, value, this.offset); return this; } /** * Write int16le. * @param {Number} value */ writeI16(value) { this.check(2); this.offset = encoding.writeI16(this.data, value, this.offset); return this; } /** * Write int16be. * @param {Number} value */ writeI16BE(value) { this.check(2); this.offset = encoding.writeI16BE(this.data, value, this.offset); return this; } /** * Write int24le. * @param {Number} value */ writeI24(value) { this.check(3); this.offset = encoding.writeI24(this.data, value, this.offset); return this; } /** * Write int24be. * @param {Number} value */ writeI24BE(value) { this.check(3); this.offset = encoding.writeI24BE(this.data, value, this.offset); return this; } /** * Write int32le. * @param {Number} value */ writeI32(value) { this.check(4); this.offset = encoding.writeI32(this.data, value, this.offset); return this; } /** * Write int32be. * @param {Number} value */ writeI32BE(value) { this.check(4); this.offset = encoding.writeI32BE(this.data, value, this.offset); return this; } /** * Write int40le. * @param {Number} value */ writeI40(value) { this.check(5); this.offset = encoding.writeI40(this.data, value, this.offset); return this; } /** * Write int40be. * @param {Number} value */ writeI40BE(value) { this.check(5); this.offset = encoding.writeI40BE(this.data, value, this.offset); return this; } /** * Write int48le. * @param {Number} value */ writeI48(value) { this.check(6); this.offset = encoding.writeI48(this.data, value, this.offset); return this; } /** * Write int48be. * @param {Number} value */ writeI48BE(value) { this.check(6); this.offset = encoding.writeI48BE(this.data, value, this.offset); return this; } /** * Write int56le. * @param {Number} value */ writeI56(value) { this.check(7); this.offset = encoding.writeI56(this.data, value, this.offset); return this; } /** * Write int56be. * @param {Number} value */ writeI56BE(value) { this.check(7); this.offset = encoding.writeI56BE(this.data, value, this.offset); return this; } /** * Write int64le. * @param {Number} value */ writeI64(value) { this.check(8); this.offset = encoding.writeI64(this.data, value, this.offset); return this; } /** * Write int64be. * @param {Number} value */ writeI64BE(value) { this.check(8); this.offset = encoding.writeI64BE(this.data, value, this.offset); return this; } /** * Write float le. * @param {Number} value */ writeFloat(value) { this.check(4); this.offset = encoding.writeFloat(this.data, value, this.offset); return this; } /** * Write float be. * @param {Number} value */ writeFloatBE(value) { this.check(4); this.offset = encoding.writeFloatBE(this.data, value, this.offset); return this; } /** * Write double le. * @param {Number} value */ writeDouble(value) { this.check(8); this.offset = encoding.writeDouble(this.data, value, this.offset); return this; } /** * Write double be. * @param {Number} value */ writeDoubleBE(value) { this.check(8); this.offset = encoding.writeDoubleBE(this.data, value, this.offset); return this; } /** * Write a varint. * @param {Number} value */ writeVarint(value) { this.offset = encoding.writeVarint(this.data, value, this.offset); return this; } /** * Write a varint (type 2). * @param {Number} value */ writeVarint2(value) { this.offset = encoding.writeVarint2(this.data, value, this.offset); return this; } /** * Write bytes. * @param {Buffer} value */ writeBytes(value) { enforce(Buffer.isBuffer(value), 'value', 'buffer'); this.check(value.length); this.offset += value.copy(this.data, this.offset); return this; } /** * Write bytes with a varint length before them. * @param {Buffer} value */ writeVarBytes(value) { enforce(Buffer.isBuffer(value), 'value', 'buffer'); this.writeVarint(value.length); this.writeBytes(value); return this; } /** * Copy bytes. * @param {Buffer} value * @param {Number} start * @param {Number} end */ copy(value, start, end) { enforce(Buffer.isBuffer(value), 'value', 'buffer'); enforce((start >>> 0) === start, 'start', 'integer'); enforce((end >>> 0) === end, 'end', 'integer'); enforce(end >= start, 'start', 'integer'); this.check(end - start); this.offset += value.copy(this.data, this.offset, start, end); return this; } /** * Write string to buffer. * @param {String} value * @param {String?} enc - Any buffer-supported encoding. */ writeString(value, enc) { if (enc == null) enc = 'binary'; enforce(typeof value === 'string', 'value', 'string'); enforce(typeof enc === 'string', 'enc', 'string'); if (value.length === 0) return this; const size = Buffer.byteLength(value, enc); this.check(size); this.offset += this.data.write(value, this.offset, enc); return this; } /** * Write a 32 byte hash. * @param {Hash} value */ writeHash(value) { if (typeof value !== 'string') { enforce(Buffer.isBuffer(value), 'value', 'buffer'); enforce(value.length === 32, 'value', '32-byte hash'); this.writeBytes(value); return this; } enforce(value.length === 64, 'value', '32-byte hash'); this.check(32); this.offset += this.data.write(value, this.offset, 'hex'); return this; } /** * Write a string with a varint length before it. * @param {String} * @param {String?} enc - Any buffer-supported encoding. */ writeVarString(value, enc) { if (enc == null) enc = 'binary'; enforce(typeof value === 'string', 'value', 'string'); enforce(typeof enc === 'string', 'enc', 'string'); if (value.length === 0) { this.writeVarint(0); return this; } const size = Buffer.byteLength(value, enc); this.writeVarint(size); this.check(size); this.offset += this.data.write(value, this.offset, enc); return this; } /** * Write a null-terminated string. * @param {String|Buffer} * @param {String?} enc - Any buffer-supported encoding. */ writeNullString(value, enc) { this.writeString(value, enc); this.writeU8(0); return this; } /** * Calculate and write a checksum for the data written so far. * @param {Function} hash */ writeChecksum(hash) { if (!hash || typeof hash.digest !== 'function') enforce(typeof hash === 'function', 'hash', 'function'); this.check(4); const data = this.data.slice(0, this.offset); const raw = hash.digest ? hash.digest(data) : hash(data); raw.copy(this.data, this.offset, 0, 4); this.offset += 4; return this; } /** * Fill N bytes with value. * @param {Number} value * @param {Number} size */ fill(value, size) { enforce((value & 0xff) === value, 'value', 'byte'); enforce((size >>> 0) === size, 'size', 'integer'); this.check(size); this.data.fill(value, this.offset, this.offset + size); this.offset += size; return this; } } /* * Expose */ module.exports = StaticWriter; }], [/* 11 */ 'bufio', '/lib/struct.js', function(exports, module, __filename, __dirname, __meta) { /*! * struct.js - struct object for bcoin * Copyright (c) 2018, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcoin */ 'use strict'; const enforce = __node_require__(6 /* './enforce' */); const BufferReader = __node_require__(8 /* './reader' */); const BufferWriter = __node_require__(9 /* './writer' */); const StaticWriter = __node_require__(10 /* './staticwriter' */); const {custom} = __node_require__(4 /* './custom' */); /** * Struct */ class Struct { constructor() {} inject(obj) { enforce(obj instanceof this.constructor, 'obj', 'struct'); return this.decode(obj.encode()); } clone() { const copy = new this.constructor(); return copy.inject(this); } /* * Bindable */ getSize(extra) { return -1; } write(bw, extra) { return bw; } read(br, extra) { return this; } toString() { return Object.prototype.toString.call(this); } fromString(str, extra) { return this; } getJSON() { return this; } fromJSON(json, extra) { return this; } fromOptions(options, extra) { return this; } from(options, extra) { return this.fromOptions(options, extra); } format() { return this.getJSON(); } /* * API */ encode(extra) { const size = this.getSize(extra); const bw = size === -1 ? new BufferWriter() : new StaticWriter(size); this.write(bw, extra); return bw.render(); } decode(data, extra) { const br = new BufferReader(data); this.read(br, extra); return this; } toHex(extra) { return this.encode(extra).toString('hex'); } fromHex(str, extra) { enforce(typeof str === 'string', 'str', 'string'); const size = str.length >>> 1; const data = Buffer.from(str, 'hex'); if (data.length !== size) throw new Error('Invalid hex string.'); return this.decode(data, extra); } toBase64(extra) { return this.encode(extra).toString('base64'); } fromBase64(str, extra) { enforce(typeof str === 'string', 'str', 'string'); const data = Buffer.from(str, 'base64'); if (str.length > size64(data.length)) throw new Error('Invalid base64 string.'); return this.decode(data, extra); } toJSON() { return this.getJSON(); } [custom]() { return this.format(); } /* * Static API */ static read(br, extra) { return new this().read(br, extra); } static decode(data, extra) { return new this().decode(data, extra); } static fromHex(str, extra) { return new this().fromHex(str, extra); } static fromBase64(str, extra) { return new this().fromBase64(str, extra); } static fromString(str, extra) { return new this().fromString(str, extra); } static fromJSON(json, extra) { return new this().fromJSON(json, extra); } static fromOptions(options, extra) { return new this().fromOptions(options, extra); } static from(options, extra) { return new this().from(options, extra); } /* * Aliases */ toWriter(bw, extra) { return this.write(bw, extra); } fromReader(br, extra) { return this.read(br, extra); } toRaw(extra) { return this.encode(extra); } fromRaw(data, extra) { return this.decode(data, extra); } /* * Static Aliases */ static fromReader(br, extra) { return this.read(br, extra); } static fromRaw(data, extra) { return this.decode(data, extra); } } /* * Helpers */ function size64(size) { const expect = ((4 * size / 3) + 3) & ~3; return expect >>> 0; } /* * Expose */ module.exports = Struct; }], [/* 12 */ 'bcrypto', '/lib/encoding/base58-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * base58.js - base58 for bcrypto * Copyright (c) 2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; module.exports = __node_require__(13 /* '../js/base58' */); }], [/* 13 */ 'bcrypto', '/lib/js/base58.js', function(exports, module, __filename, __dirname, __meta) { /*! * base58.js - base58 for bcrypto * Copyright (c) 2014-2015, Fedor Indutny (MIT License) * Copyright (c) 2014-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Parts of this software are based on bitcoin/bitcoin: * Copyright (c) 2009-2019, The Bitcoin Core Developers (MIT License). * Copyright (c) 2009-2019, The Bitcoin Developers (MIT License). * https://github.com/bitcoin/bitcoin * * Resources: * https://github.com/bitcoin/bitcoin/blob/master/src/base58.cpp */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); /* * Constants */ const CHARSET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; const TABLE = [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18, 19, 20, 21, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1 ]; const pool = Buffer.alloc(128); /** * Encode a base58 string. * @param {Buffer} data * @returns {String} */ function encode(data) { assert(Buffer.isBuffer(data)); let zeroes = 0; let i = 0; for (; i < data.length; i++) { if (data[i] !== 0) break; zeroes += 1; } const size = (((data.length - zeroes) * 138 / 100) | 0) + 1; const b58 = size <= 128 ? pool.fill(0) : Buffer.alloc(size); let length = 0; for (; i < data.length; i++) { let carry = data[i]; let j = 0; for (let k = size - 1; k >= 0; k--, j++) { if (carry === 0 && j >= length) break; carry += b58[k] * 256; b58[k] = carry % 58; carry = (carry / 58) | 0; } assert(carry === 0); length = j; } i = size - length; while (i < size && b58[i] === 0) i += 1; let str = ''; for (let j = 0; j < zeroes; j++) str += '1'; while (i < size) str += CHARSET[b58[i++]]; return str; } /** * Decode a base58 string. * @param {String} str * @returns {Buffer} * @throws on non-base58 character. */ function decode(str) { assert(typeof str === 'string'); let zeroes = 0; let i = 0; for (; i < str.length; i++) { if (str[i] !== '1') break; zeroes += 1; } const size = ((str.length * 733) / 1000 | 0) + 1; const b256 = size <= 128 ? pool.fill(0) : Buffer.alloc(size); let length = 0; for (; i < str.length; i++) { const ch = str.charCodeAt(i); if (ch & 0xff80) throw new Error('Invalid base58 string.'); const val = TABLE[ch]; if (val === -1) throw new Error('Invalid base58 string.'); let carry = val; let j = 0; for (let k = size - 1; k >= 0; k--, j++) { if (carry === 0 && j >= length) break; carry += b256[k] * 58; b256[k] = carry; carry >>>= 8; } assert(carry === 0); length = j; } // See: https://github.com/bitcoin/bitcoin/commit/2bcf1fc4 i = size - length; const out = Buffer.alloc(zeroes + (size - i)); let j; for (j = 0; j < zeroes; j++) out[j] = 0; while (i < size) out[j++] = b256[i++]; return out; } /** * Test whether the string is a base58 string. * @param {String} str * @returns {Buffer} */ function test(str) { assert(typeof str === 'string'); for (let i = 0; i < str.length; i++) { const ch = str.charCodeAt(i); if (ch & 0xff80) return false; if (TABLE[ch] === -1) return false; } return true; } /* * Expose */ exports.native = 0; exports.encode = encode; exports.decode = decode; exports.test = test; }], [/* 14 */ 'bcrypto', '/lib/internal/assert.js', function(exports, module, __filename, __dirname, __meta) { /*! * assert.js - assert for bcrypto * Copyright (c) 2020, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; /* * Assert */ function assert(val, msg) { if (!val) { const err = new Error(msg || 'Assertion failed'); if (Error.captureStackTrace) Error.captureStackTrace(err, assert); throw err; } } /* * Expose */ module.exports = assert; }], [/* 15 */ 'bcrypto', '/lib/sha512-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * sha512.js - sha512 for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; module.exports = __node_require__(16 /* './js/sha512' */); }], [/* 16 */ 'bcrypto', '/lib/js/sha512.js', function(exports, module, __filename, __dirname, __meta) { /*! * sha512.js - SHA512 implementation for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Parts of this software are based on indutny/hash.js: * Copyright (c) 2014, Fedor Indutny (MIT License). * https://github.com/indutny/hash.js * * Resources: * https://en.wikipedia.org/wiki/SHA-2 * https://tools.ietf.org/html/rfc4634 * https://github.com/indutny/hash.js/blob/master/lib/hash/sha/512.js */ /* eslint camelcase: "off" */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); const HMAC = __node_require__(17 /* '../internal/hmac' */); /* * Constants */ const FINALIZED = -1; const DESC = Buffer.alloc(16, 0x00); const PADDING = Buffer.alloc(128, 0x00); PADDING[0] = 0x80; const K = new Uint32Array([ 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 ]); /** * SHA512 */ class SHA512 { constructor() { this.state = new Uint32Array(16); this.msg = new Uint32Array(160); this.block = Buffer.alloc(128); this.size = FINALIZED; } init() { this.state[0] = 0x6a09e667; this.state[1] = 0xf3bcc908; this.state[2] = 0xbb67ae85; this.state[3] = 0x84caa73b; this.state[4] = 0x3c6ef372; this.state[5] = 0xfe94f82b; this.state[6] = 0xa54ff53a; this.state[7] = 0x5f1d36f1; this.state[8] = 0x510e527f; this.state[9] = 0xade682d1; this.state[10] = 0x9b05688c; this.state[11] = 0x2b3e6c1f; this.state[12] = 0x1f83d9ab; this.state[13] = 0xfb41bd6b; this.state[14] = 0x5be0cd19; this.state[15] = 0x137e2179; this.size = 0; return this; } update(data) { assert(Buffer.isBuffer(data)); this._update(data, data.length); return this; } final() { return this._final(Buffer.alloc(64)); } _update(data, len) { assert(this.size !== FINALIZED, 'Context is not initialized.'); let pos = this.size & 127; let off = 0; this.size += len; if (pos > 0) { let want = 128 - pos; if (want > len) want = len; data.copy(this.block, pos, off, off + want); pos += want; len -= want; off += want; if (pos < 128) return; this._transform(this.block, 0); } while (len >= 128) { this._transform(data, off); off += 128; len -= 128; } if (len > 0) data.copy(this.block, 0, off, off + len); } /** * Finalize SHA512 context. * @private * @param {Buffer} out * @returns {Buffer} */ _final(out) { assert(this.size !== FINALIZED, 'Context is not initialized.'); const pos = this.size & 127; const len = this.size * 8; writeU32(DESC, (len * (1 / 0x100000000)) >>> 0, 8); writeU32(DESC, len >>> 0, 12); this._update(PADDING, 1 + ((239 - pos) & 127)); this._update(DESC, 16); for (let i = 0; i < 16; i++) { writeU32(out, this.state[i], i * 4); this.state[i] = 0; } for (let i = 0; i < 160; i++) this.msg[i] = 0; for (let i = 0; i < 128; i++) this.block[i] = 0; this.size = FINALIZED; return out; } _prepare(chunk, pos) { const W = this.msg; let i = 0; for (; i < 32; i++) W[i] = readU32(chunk, pos + i * 4); for (; i < 160; i += 2) { const c0_hi = g1_512_hi(W[i - 4], W[i - 3]); const c0_lo = g1_512_lo(W[i - 4], W[i - 3]); const c1_hi = W[i - 14]; const c1_lo = W[i - 13]; const c2_hi = g0_512_hi(W[i - 30], W[i - 29]); const c2_lo = g0_512_lo(W[i - 30], W[i - 29]); const c3_hi = W[i - 32]; const c3_lo = W[i - 31]; W[i + 0] = sum64_4_hi(c0_hi, c0_lo, c1_hi, c1_lo, c2_hi, c2_lo, c3_hi, c3_lo); W[i + 1] = sum64_4_lo(c0_hi, c0_lo, c1_hi, c1_lo, c2_hi, c2_lo, c3_hi, c3_lo); } } _transform(chunk, pos) { const W = this.msg; this._prepare(chunk, pos); let ah = this.state[0]; let al = this.state[1]; let bh = this.state[2]; let bl = this.state[3]; let ch = this.state[4]; let cl = this.state[5]; let dh = this.state[6]; let dl = this.state[7]; let eh = this.state[8]; let el = this.state[9]; let fh = this.state[10]; let fl = this.state[11]; let gh = this.state[12]; let gl = this.state[13]; let hh = this.state[14]; let hl = this.state[15]; for (let i = 0; i < W.length; i += 2) { let c0_hi = hh; let c0_lo = hl; let c1_hi = s1_512_hi(eh, el); let c1_lo = s1_512_lo(eh, el); const c2_hi = ch64_hi(eh, el, fh, fl, gh, gl); const c2_lo = ch64_lo(eh, el, fh, fl, gh, gl); const c3_hi = K[i + 0]; const c3_lo = K[i + 1]; const c4_hi = W[i + 0]; const c4_lo = W[i + 1]; const T1_hi = sum64_5_hi(c0_hi, c0_lo, c1_hi, c1_lo, c2_hi, c2_lo, c3_hi, c3_lo, c4_hi, c4_lo); const T1_lo = sum64_5_lo(c0_hi, c0_lo, c1_hi, c1_lo, c2_hi, c2_lo, c3_hi, c3_lo, c4_hi, c4_lo); c0_hi = s0_512_hi(ah, al); c0_lo = s0_512_lo(ah, al); c1_hi = maj64_hi(ah, al, bh, bl, ch, cl); c1_lo = maj64_lo(ah, al, bh, bl, ch, cl); const T2_hi = sum64_hi(c0_hi, c0_lo, c1_hi, c1_lo); const T2_lo = sum64_lo(c0_hi, c0_lo, c1_hi, c1_lo); hh = gh; hl = gl; gh = fh; gl = fl; fh = eh; fl = el; eh = sum64_hi(dh, dl, T1_hi, T1_lo); el = sum64_lo(dl, dl, T1_hi, T1_lo); dh = ch; dl = cl; ch = bh; cl = bl; bh = ah; bl = al; ah = sum64_hi(T1_hi, T1_lo, T2_hi, T2_lo); al = sum64_lo(T1_hi, T1_lo, T2_hi, T2_lo); } sum64(this.state, 0, ah, al); sum64(this.state, 2, bh, bl); sum64(this.state, 4, ch, cl); sum64(this.state, 6, dh, dl); sum64(this.state, 8, eh, el); sum64(this.state, 10, fh, fl); sum64(this.state, 12, gh, gl); sum64(this.state, 14, hh, hl); } static hash() { return new SHA512(); } static hmac() { return new HMAC(SHA512, 128); } static digest(data) { return SHA512.ctx.init().update(data).final(); } static root(left, right) { assert(Buffer.isBuffer(left) && left.length === 64); assert(Buffer.isBuffer(right) && right.length === 64); return SHA512.ctx.init().update(left).update(right).final(); } static multi(x, y, z) { const {ctx} = SHA512; ctx.init(); ctx.update(x); ctx.update(y); if (z) ctx.update(z); return ctx.final(); } static mac(data, key) { return SHA512.hmac().init(key).update(data).final(); } } /* * Static */ SHA512.native = 0; SHA512.id = 'SHA512'; SHA512.size = 64; SHA512.bits = 512; SHA512.blockSize = 128; SHA512.zero = Buffer.alloc(64, 0x00); SHA512.ctx = new SHA512(); /* * Helpers */ function sum64(buf, pos, ah, al) { const bh = buf[pos + 0]; const bl = buf[pos + 1]; const lo = (al + bl) >>> 0; const hi = (lo < al) + ah + bh; buf[pos + 0] = hi >>> 0; buf[pos + 1] = lo; } function sum64_hi(ah, al, bh, bl) { const lo = (al + bl) >>> 0; const hi = (lo < al) + ah + bh; return hi >>> 0; } function sum64_lo(ah, al, bh, bl) { const lo = al + bl; return lo >>> 0; } function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) { let carry = 0; let lo = al; lo = (lo + bl) >>> 0; carry += (lo < al); lo = (lo + cl) >>> 0; carry += (lo < cl); lo = (lo + dl) >>> 0; carry += (lo < dl); const hi = ah + bh + ch + dh + carry; return hi >>> 0; } function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) { const lo = al + bl + cl + dl; return lo >>> 0; } function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { let carry = 0; let lo = al; lo = (lo + bl) >>> 0; carry += (lo < al); lo = (lo + cl) >>> 0; carry += (lo < cl); lo = (lo + dl) >>> 0; carry += (lo < dl); lo = (lo + el) >>> 0; carry += (lo < el); const hi = ah + bh + ch + dh + eh + carry; return hi >>> 0; } function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { const lo = al + bl + cl + dl + el; return lo >>> 0; } function rotr64_hi(ah, al, num) { const r = (al << (32 - num)) | (ah >>> num); return r >>> 0; } function rotr64_lo(ah, al, num) { const r = (ah << (32 - num)) | (al >>> num); return r >>> 0; } function shr64_hi(ah, al, num) { return ah >>> num; } function shr64_lo(ah, al, num) { const r = (ah << (32 - num)) | (al >>> num); return r >>> 0; } function ch64_hi(xh, xl, yh, yl, zh, zl) { const r = (xh & yh) ^ ((~xh) & zh); return r >>> 0; } function ch64_lo(xh, xl, yh, yl, zh, zl) { const r = (xl & yl) ^ ((~xl) & zl); return r >>> 0; } function maj64_hi(xh, xl, yh, yl, zh, zl) { const r = (xh & yh) ^ (xh & zh) ^ (yh & zh); return r >>> 0; } function maj64_lo(xh, xl, yh, yl, zh, zl) { const r = (xl & yl) ^ (xl & zl) ^ (yl & zl); return r >>> 0; } function s0_512_hi(xh, xl) { const c0_hi = rotr64_hi(xh, xl, 28); const c1_hi = rotr64_hi(xl, xh, 2); // 34 const c2_hi = rotr64_hi(xl, xh, 7); // 39 const r = c0_hi ^ c1_hi ^ c2_hi; return r >>> 0; } function s0_512_lo(xh, xl) { const c0_lo = rotr64_lo(xh, xl, 28); const c1_lo = rotr64_lo(xl, xh, 2); // 34 const c2_lo = rotr64_lo(xl, xh, 7); // 39 const r = c0_lo ^ c1_lo ^ c2_lo; return r >>> 0; } function s1_512_hi(xh, xl) { const c0_hi = rotr64_hi(xh, xl, 14); const c1_hi = rotr64_hi(xh, xl, 18); const c2_hi = rotr64_hi(xl, xh, 9); // 41 const r = c0_hi ^ c1_hi ^ c2_hi; return r >>> 0; } function s1_512_lo(xh, xl) { const c0_lo = rotr64_lo(xh, xl, 14); const c1_lo = rotr64_lo(xh, xl, 18); const c2_lo = rotr64_lo(xl, xh, 9); // 41 const r = c0_lo ^ c1_lo ^ c2_lo; return r >>> 0; } function g0_512_hi(xh, xl) { const c0_hi = rotr64_hi(xh, xl, 1); const c1_hi = rotr64_hi(xh, xl, 8); const c2_hi = shr64_hi(xh, xl, 7); const r = c0_hi ^ c1_hi ^ c2_hi; return r >>> 0; } function g0_512_lo(xh, xl) { const c0_lo = rotr64_lo(xh, xl, 1); const c1_lo = rotr64_lo(xh, xl, 8); const c2_lo = shr64_lo(xh, xl, 7); const r = c0_lo ^ c1_lo ^ c2_lo; return r >>> 0; } function g1_512_hi(xh, xl) { const c0_hi = rotr64_hi(xh, xl, 19); const c1_hi = rotr64_hi(xl, xh, 29); // 61 const c2_hi = shr64_hi(xh, xl, 6); const r = c0_hi ^ c1_hi ^ c2_hi; return r >>> 0; } function g1_512_lo(xh, xl) { const c0_lo = rotr64_lo(xh, xl, 19); const c1_lo = rotr64_lo(xl, xh, 29); // 61 const c2_lo = shr64_lo(xh, xl, 6); const r = c0_lo ^ c1_lo ^ c2_lo; return r >>> 0; } function readU32(data, off) { return (data[off++] * 0x1000000 + data[off++] * 0x10000 + data[off++] * 0x100 + data[off]); } function writeU32(data, num, off) { data[off++] = num >>> 24; data[off++] = num >>> 16; data[off++] = num >>> 8; data[off++] = num; return off; } /* * Expose */ module.exports = SHA512; }], [/* 17 */ 'bcrypto', '/lib/internal/hmac.js', function(exports, module, __filename, __dirname, __meta) { /*! * hmac.js - hmac for bcrypto * Copyright (c) 2016-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Parts of this software are based on indutny/hash.js: * Copyright (c) 2014, Fedor Indutny (MIT License). * https://github.com/indutny/hash.js * * Resources: * https://en.wikipedia.org/wiki/HMAC * https://tools.ietf.org/html/rfc2104 * https://github.com/indutny/hash.js/blob/master/lib/hash/hmac.js */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); /** * HMAC */ class HMAC { /** * Create an HMAC. * @param {Function} Hash * @param {Number} size * @param {Array} [x=[]] * @param {Array} [y=[]] */ constructor(Hash, size, x = [], y = []) { assert(typeof Hash === 'function'); assert((size >>> 0) === size); assert(Array.isArray(x)); assert(Array.isArray(y)); this.hash = Hash; this.size = size; this.x = x; this.y = y; this.inner = new Hash(); this.outer = new Hash(); } /** * Initialize HMAC context. * @param {Buffer} data */ init(key) { assert(Buffer.isBuffer(key)); // Shorten key if (key.length > this.size) { const Hash = this.hash; const h = new Hash(); h.init(...this.x); h.update(key); key = h.final(...this.y); assert(key.length <= this.size); } // Pad key const pad = Buffer.alloc(this.size); for (let i = 0; i < key.length; i++) pad[i] = key[i] ^ 0x36; for (let i = key.length; i < pad.length; i++) pad[i] = 0x36; this.inner.init(...this.x); this.inner.update(pad); for (let i = 0; i < key.length; i++) pad[i] = key[i] ^ 0x5c; for (let i = key.length; i < pad.length; i++) pad[i] = 0x5c; this.outer.init(...this.x); this.outer.update(pad); return this; } /** * Update HMAC context. * @param {Buffer} data */ update(data) { this.inner.update(data); return this; } /** * Finalize HMAC context. * @returns {Buffer} */ final() { this.outer.update(this.inner.final(...this.y)); return this.outer.final(...this.y); } } /* * Expose */ module.exports = HMAC; }], [/* 18 */ 'bcrypto', '/lib/hash160-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * hash160.js - hash160 for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; module.exports = __node_require__(19 /* './js/hash160' */); }], [/* 19 */ 'bcrypto', '/lib/js/hash160.js', function(exports, module, __filename, __dirname, __meta) { /*! * hash160.js - Hash160 implementation for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Resources: * https://github.com/bitcoin/bitcoin/blob/master/src/hash.h */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); const SHA256 = __node_require__(20 /* './sha256' */); const RIPEMD160 = __node_require__(21 /* './ripemd160' */); const HMAC = __node_require__(17 /* '../internal/hmac' */); /* * Constants */ const rmd = new RIPEMD160(); /** * Hash160 */ class Hash160 { constructor() { this.ctx = new SHA256(); } init() { this.ctx.init(); return this; } update(data) { this.ctx.update(data); return this; } final() { const out = Buffer.alloc(32); this.ctx._final(out); rmd.init(); rmd.update(out); rmd._final(out); return out.slice(0, 20); } static hash() { return new Hash160(); } static hmac() { return new HMAC(Hash160, 64); } static digest(data) { return Hash160.ctx.init().update(data).final(); } static root(left, right) { assert(Buffer.isBuffer(left) && left.length === 20); assert(Buffer.isBuffer(right) && right.length === 20); return Hash160.ctx.init().update(left).update(right).final(); } static multi(x, y, z) { const {ctx} = Hash160; ctx.init(); ctx.update(x); ctx.update(y); if (z) ctx.update(z); return ctx.final(); } static mac(data, key) { return Hash160.hmac().init(key).update(data).final(); } } /* * Static */ Hash160.native = 0; Hash160.id = 'HASH160'; Hash160.size = 20; Hash160.bits = 160; Hash160.blockSize = 64; Hash160.zero = Buffer.alloc(20, 0x00); Hash160.ctx = new Hash160(); /* * Expose */ module.exports = Hash160; }], [/* 20 */ 'bcrypto', '/lib/js/sha256.js', function(exports, module, __filename, __dirname, __meta) { /*! * sha256.js - SHA256 implementation for bcrypto * Copyright (c) 2016-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Parts of this software are based on indutny/hash.js: * Copyright (c) 2014, Fedor Indutny (MIT License). * https://github.com/indutny/hash.js * * Resources: * https://en.wikipedia.org/wiki/SHA-2 * https://tools.ietf.org/html/rfc4634 * https://github.com/indutny/hash.js/blob/master/lib/hash/sha/256.js */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); const HMAC = __node_require__(17 /* '../internal/hmac' */); /* * Constants */ const FINALIZED = -1; const DESC = Buffer.alloc(8, 0x00); const PADDING = Buffer.alloc(64, 0x00); PADDING[0] = 0x80; const K = new Uint32Array([ 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 ]); /** * SHA256 */ class SHA256 { constructor() { this.state = new Uint32Array(8); this.msg = new Uint32Array(64); this.block = Buffer.alloc(64); this.size = FINALIZED; } init() { this.state[0] = 0x6a09e667; this.state[1] = 0xbb67ae85; this.state[2] = 0x3c6ef372; this.state[3] = 0xa54ff53a; this.state[4] = 0x510e527f; this.state[5] = 0x9b05688c; this.state[6] = 0x1f83d9ab; this.state[7] = 0x5be0cd19; this.size = 0; return this; } update(data) { assert(Buffer.isBuffer(data)); this._update(data, data.length); return this; } final() { return this._final(Buffer.alloc(32)); } _update(data, len) { assert(this.size !== FINALIZED, 'Context is not initialized.'); let pos = this.size & 63; let off = 0; this.size += len; if (pos > 0) { let want = 64 - pos; if (want > len) want = len; data.copy(this.block, pos, off, off + want); pos += want; len -= want; off += want; if (pos < 64) return; this._transform(this.block, 0); } while (len >= 64) { this._transform(data, off); off += 64; len -= 64; } if (len > 0) data.copy(this.block, 0, off, off + len); } _final(out) { assert(this.size !== FINALIZED, 'Context is not initialized.'); const pos = this.size & 63; const len = this.size * 8; writeU32(DESC, (len * (1 / 0x100000000)) >>> 0, 0); writeU32(DESC, len >>> 0, 4); this._update(PADDING, 1 + ((119 - pos) & 63)); this._update(DESC, 8); for (let i = 0; i < 8; i++) { writeU32(out, this.state[i], i * 4); this.state[i] = 0; } for (let i = 0; i < 64; i++) this.msg[i] = 0; for (let i = 0; i < 64; i++) this.block[i] = 0; this.size = FINALIZED; return out; } _transform(chunk, pos) { const W = this.msg; let a = this.state[0]; let b = this.state[1]; let c = this.state[2]; let d = this.state[3]; let e = this.state[4]; let f = this.state[5]; let g = this.state[6]; let h = this.state[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++) { const t1 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; const t2 = Sigma0(a) + Maj(a, b, c); h = g; g = f; f = e; e = (d + t1) >>> 0; d = c; c = b; b = a; a = (t1 + t2) >>> 0; } this.state[0] += a; this.state[1] += b; this.state[2] += c; this.state[3] += d; this.state[4] += e; this.state[5] += f; this.state[6] += g; this.state[7] += h; } static hash() { return new SHA256(); } static hmac() { return new HMAC(SHA256, 64); } static digest(data) { return SHA256.ctx.init().update(data).final(); } static root(left, right) { assert(Buffer.isBuffer(left) && left.length === 32); assert(Buffer.isBuffer(right) && right.length === 32); return SHA256.ctx.init().update(left).update(right).final(); } static multi(x, y, z) { const {ctx} = SHA256; ctx.init(); ctx.update(x); ctx.update(y); if (z) ctx.update(z); return ctx.final(); } static mac(data, key) { return SHA256.hmac().init(key).update(data).final(); } } /* * Static */ SHA256.native = 0; SHA256.id = 'SHA256'; SHA256.size = 32; SHA256.bits = 256; SHA256.blockSize = 64; SHA256.zero = Buffer.alloc(32, 0x00); SHA256.ctx = new SHA256(); /* * Helpers */ 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 readU32(data, off) { return (data[off++] * 0x1000000 + data[off++] * 0x10000 + data[off++] * 0x100 + data[off]); } function writeU32(data, num, off) { data[off++] = num >>> 24; data[off++] = num >>> 16; data[off++] = num >>> 8; data[off++] = num; return off; } /* * Expose */ module.exports = SHA256; }], [/* 21 */ 'bcrypto', '/lib/js/ripemd160.js', function(exports, module, __filename, __dirname, __meta) { /*! * ripemd160.js - RIPEMD160 implementation for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Parts of this software are based on indutny/hash.js: * Copyright (c) 2014, Fedor Indutny (MIT License). * https://github.com/indutny/hash.js * * Resources: * https://en.wikipedia.org/wiki/RIPEMD-160 * https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf * https://github.com/indutny/hash.js/blob/master/lib/hash/ripemd.js */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); const HMAC = __node_require__(17 /* '../internal/hmac' */); /* * Constants */ const FINALIZED = -1; const DESC = Buffer.alloc(8, 0x00); const PADDING = Buffer.alloc(64, 0x00); PADDING[0] = 0x80; const r = new Uint8Array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 ]); const rh = new Uint8Array([ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 ]); const s = new Uint8Array([ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 ]); const sh = new Uint8Array([ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 ]); /** * RIPEMD160 */ class RIPEMD160 { constructor() { this.state = new Uint32Array(5); this.msg = new Uint32Array(16); this.block = Buffer.alloc(64); this.size = FINALIZED; } init() { this.state[0] = 0x67452301; this.state[1] = 0xefcdab89; this.state[2] = 0x98badcfe; this.state[3] = 0x10325476; this.state[4] = 0xc3d2e1f0; this.size = 0; return this; } update(data) { assert(Buffer.isBuffer(data)); this._update(data, data.length); return this; } final() { return this._final(Buffer.alloc(20)); } _update(data, len) { assert(this.size !== FINALIZED, 'Context is not initialized.'); let pos = this.size & 63; let off = 0; this.size += len; if (pos > 0) { let want = 64 - pos; if (want > len) want = len; data.copy(this.block, pos, off, off + want); pos += want; len -= want; off += want; if (pos < 64) return; this._transform(this.block, 0); } while (len >= 64) { this._transform(data, off); off += 64; len -= 64; } if (len > 0) data.copy(this.block, 0, off, off + len); } _final(out) { assert(this.size !== FINALIZED, 'Context is not initialized.'); const pos = this.size & 63; const len = this.size * 8; writeU32(DESC, len >>> 0, 0); writeU32(DESC, (len * (1 / 0x100000000)) >>> 0, 4); this._update(PADDING, 1 + ((119 - pos) & 63)); this._update(DESC, 8); for (let i = 0; i < 5; i++) { writeU32(out, this.state[i], i * 4); this.state[i] = 0; } for (let i = 0; i < 16; i++) this.msg[i] = 0; for (let i = 0; i < 64; i++) this.block[i] = 0; this.size = FINALIZED; return out; } _transform(chunk, pos) { const W = this.msg; let A = this.state[0]; let B = this.state[1]; let C = this.state[2]; let D = this.state[3]; let E = this.state[4]; let Ah = A; let Bh = B; let Ch = C; let Dh = D; let Eh = E; for (let i = 0; i < 16; i++) W[i] = readU32(chunk, pos + i * 4); for (let j = 0; j < 80; j++) { let a = A + f(j, B, C, D) + W[r[j]] + K(j); let b = rotl32(a, s[j]); let T = b + E; A = E; E = D; D = rotl32(C, 10); C = B; B = T; a = Ah + f(79 - j, Bh, Ch, Dh) + W[rh[j]] + Kh(j); b = rotl32(a, sh[j]); T = b + Eh; Ah = Eh; Eh = Dh; Dh = rotl32(Ch, 10); Ch = Bh; Bh = T; } const T = this.state[1] + C + Dh; this.state[1] = this.state[2] + D + Eh; this.state[2] = this.state[3] + E + Ah; this.state[3] = this.state[4] + A + Bh; this.state[4] = this.state[0] + B + Ch; this.state[0] = T; } static hash() { return new RIPEMD160(); } static hmac() { return new HMAC(RIPEMD160, 64); } static digest(data) { return RIPEMD160.ctx.init().update(data).final(); } static root(left, right) { assert(Buffer.isBuffer(left) && left.length === 20); assert(Buffer.isBuffer(right) && right.length === 20); return RIPEMD160.ctx.init().update(left).update(right).final(); } static multi(x, y, z) { const {ctx} = RIPEMD160; ctx.init(); ctx.update(x); ctx.update(y); if (z) ctx.update(z); return ctx.final(); } static mac(data, key) { return RIPEMD160.hmac().init(key).update(data).final(); } } /* * Static */ RIPEMD160.native = 0; RIPEMD160.id = 'RIPEMD160'; RIPEMD160.size = 20; RIPEMD160.bits = 160; RIPEMD160.blockSize = 64; RIPEMD160.zero = Buffer.alloc(20, 0x00); RIPEMD160.ctx = new RIPEMD160(); /* * Helpers */ function rotl32(w, b) { return (w << b) | (w >>> (32 - b)); } function f(j, x, y, z) { if (j <= 15) return x ^ y ^ z; if (j <= 31) return (x & y) | ((~x) & z); if (j <= 47) return (x | (~y)) ^ z; if (j <= 63) return (x & z) | (y & (~z)); return x ^ (y | (~z)); } function K(j) { if (j <= 15) return 0x00000000; if (j <= 31) return 0x5a827999; if (j <= 47) return 0x6ed9eba1; if (j <= 63) return 0x8f1bbcdc; return 0xa953fd4e; } function Kh(j) { if (j <= 15) return 0x50a28be6; if (j <= 31) return 0x5c4dd124; if (j <= 47) return 0x6d703ef3; if (j <= 63) return 0x7a6d76e9; return 0x00000000; } function readU32(data, off) { return (data[off++] + data[off++] * 0x100 + data[off++] * 0x10000 + data[off] * 0x1000000); } function writeU32(dst, num, off) { dst[off++] = num; num >>>= 8; dst[off++] = num; num >>>= 8; dst[off++] = num; num >>>= 8; dst[off++] = num; return off; } /* * Expose */ module.exports = RIPEMD160; }], [/* 22 */ 'bcrypto', '/lib/hash256-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * hash256.js - hash256 for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; module.exports = __node_require__(23 /* './js/hash256' */); }], [/* 23 */ 'bcrypto', '/lib/js/hash256.js', function(exports, module, __filename, __dirname, __meta) { /*! * hash256.js - Hash256 implementation for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Resources: * https://github.com/bitcoin/bitcoin/blob/master/src/hash.h */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); const SHA256 = __node_require__(20 /* './sha256' */); const HMAC = __node_require__(17 /* '../internal/hmac' */); /** * Hash256 */ class Hash256 { constructor() { this.ctx = new SHA256(); } init() { this.ctx.init(); return this; } update(data) { this.ctx.update(data); return this; } final() { const out = Buffer.alloc(32); this.ctx._final(out); this.ctx.init(); this.ctx.update(out); this.ctx._final(out); return out; } static hash() { return new Hash256(); } static hmac() { return new HMAC(Hash256, 64); } static digest(data) { return Hash256.ctx.init().update(data).final(); } static root(left, right) { assert(Buffer.isBuffer(left) && left.length === 32); assert(Buffer.isBuffer(right) && right.length === 32); return Hash256.ctx.init().update(left).update(right).final(); } static multi(x, y, z) { const {ctx} = Hash256; ctx.init(); ctx.update(x); ctx.update(y); if (z) ctx.update(z); return ctx.final(); } static mac(data, key) { return Hash256.hmac().init(key).update(data).final(); } } /* * Static */ Hash256.native = 0; Hash256.id = 'HASH256'; Hash256.size = 32; Hash256.bits = 256; Hash256.blockSize = 64; Hash256.zero = Buffer.alloc(32, 0x00); Hash256.ctx = new Hash256(); /* * Expose */ module.exports = Hash256; }], [/* 24 */ 'bcrypto', '/lib/cleanse-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * cleanse.js - cleanse for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; module.exports = __node_require__(25 /* './js/cleanse' */); }], [/* 25 */ 'bcrypto', '/lib/js/cleanse.js', function(exports, module, __filename, __dirname, __meta) { /*! * cleanse.js - memzero for bcrypto * Copyright (c) 2016-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); const random = __node_require__(26 /* '../random' */); /** * A maybe-secure memzero. * @param {Buffer} data */ function cleanse(data) { assert(Buffer.isBuffer(data)); random.randomFill(data, 0, data.length); } /* * Static */ cleanse.native = 0; /* * Expose */ module.exports = cleanse; }], [/* 26 */ 'bcrypto', '/lib/random-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * random.js - random for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; module.exports = __node_require__(27 /* './js/random' */); }], [/* 27 */ 'bcrypto', '/lib/js/random.js', function(exports, module, __filename, __dirname, __meta) { /*! * random.js - random number generator for bcrypto * Copyright (c) 2014-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Resources: * https://wiki.openssl.org/index.php/Random_Numbers * https://csrc.nist.gov/projects/random-bit-generation/ * http://www.pcg-random.org/posts/bounded-rands.html * https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); /* * Constants */ const crypto = global.crypto || global.msCrypto; const HAS_CRYPTO = crypto && typeof crypto.getRandomValues === 'function'; const randomValues = HAS_CRYPTO ? crypto.getRandomValues.bind(crypto) : null; const pool = new Uint32Array(16); const MAX_BYTES = 65536; let poolPos = 0; /** * Generate pseudo-random bytes. * @param {Number} size * @returns {Buffer} */ function randomBytes(size) { assert((size >>> 0) === size); const data = Buffer.alloc(size); randomFillSync(data, 0, size); return data; } /** * Generate pseudo-random bytes. * @param {Buffer} data * @param {Number} [off=0] * @param {Number} [size=data.length-off] * @returns {Buffer} */ function randomFill(data, off, size) { assert(Buffer.isBuffer(data)); if (off == null) off = 0; assert((off >>> 0) === off); if (size == null) size = data.length - off; assert((size >>> 0) === size); assert(off + size <= data.length); randomFillSync(data, off, size); return data; } /** * Generate a random uint32. * @returns {Number} */ function randomInt() { if ((poolPos & 15) === 0) { getRandomValues(pool); poolPos = 0; } return pool[poolPos++]; } /** * Generate a random uint32 within a range. * @param {Number} min - Inclusive. * @param {Number} max - Exclusive. * @returns {Number} */ function randomRange(min, max) { assert((min >>> 0) === min); assert((max >>> 0) === max); assert(max >= min); const space = max - min; if (space === 0) return min; const top = -space >>> 0; let x, r; do { x = randomInt(); r = x % space; } while (x - r > top); return r + min; } /* * Helpers */ function getRandomValues(array) { if (!HAS_CRYPTO) throw new Error('Entropy source not available.'); return randomValues(array); } function randomFillSync(data, off, size) { assert(Buffer.isBuffer(data)); assert(data.buffer instanceof ArrayBuffer); assert((data.byteOffset >>> 0) === data.byteOffset); assert((data.byteLength >>> 0) === data.byteLength); assert((off >>> 0) === off); assert((size >>> 0) === size); assert(off + size <= data.byteLength); if (size > 2 ** 31 - 1) throw new RangeError('The value "size" is out of range.'); const offset = data.byteOffset + off; const array = new Uint8Array(data.buffer, offset, size); if (array.length > MAX_BYTES) { for (let i = 0; i < array.length; i += MAX_BYTES) { let j = i + MAX_BYTES; if (j > array.length) j = array.length; getRandomValues(array.subarray(i, j)); } } else { if (array.length > 0) getRandomValues(array); } } /* * Expose */ exports.native = 0; exports.randomBytes = randomBytes; exports.randomFill = randomFill; exports.randomInt = randomInt; exports.randomRange = randomRange; }], [/* 28 */ 'bcrypto', '/lib/secp256k1-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * secp256k1.js - secp256k1 for bcrypto * Copyright (c) 2014-2015, Fedor Indutny (MIT License) * Copyright (c) 2014-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; module.exports = __node_require__(29 /* './js/secp256k1' */); }], [/* 29 */ 'bcrypto', '/lib/js/secp256k1.js', function(exports, module, __filename, __dirname, __meta) { /*! * secp256k1.js - secp256k1 for bcrypto * Copyright (c) 2014-2015, Fedor Indutny (MIT License) * Copyright (c) 2014-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; const ECDSA = __node_require__(30 /* './ecdsa' */); const SHA256 = __node_require__(39 /* '../sha256' */); const pre = __node_require__(43 /* './precomputed/secp256k1.json' */); /* * Expose */ module.exports = new ECDSA('SECP256K1', SHA256, SHA256, pre); }], [/* 30 */ 'bcrypto', '/lib/js/ecdsa.js', function(exports, module, __filename, __dirname, __meta) { /*! * ecdsa.js - ECDSA for bcrypto * Copyright (c) 2018-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Parts of this software are based on indutny/elliptic: * Copyright (c) 2014, Fedor Indutny (MIT License). * https://github.com/indutny/elliptic * * References: * * [SEC1] SEC 1: Elliptic Curve Cryptography, Version 2.0 * Certicom Research * http://www.secg.org/sec1-v2.pdf * * [FIPS186] Suite B Implementer's Guide to FIPS 186-3 (ECDSA) * https://tinyurl.com/fips186-guide * * [GECC] Guide to Elliptic Curve Cryptography * D. Hankerson, A. Menezes, and S. Vanstone * https://tinyurl.com/guide-to-ecc * * [RFC6979] Deterministic Usage of the Digital Signature * Algorithm (DSA) and Elliptic Curve Digital * Signature Algorithm (ECDSA) * T. Pornin * https://tools.ietf.org/html/rfc6979 */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); const BN = __node_require__(31 /* '../bn' */); const rng = __node_require__(26 /* '../random' */); const asn1 = __node_require__(34 /* '../internal/asn1' */); const Schnorr = __node_require__(35 /* './schnorr-legacy' */); const HmacDRBG = __node_require__(40 /* '../hmac-drbg' */); const elliptic = __node_require__(42 /* './elliptic' */); /** * ECDSA */ class ECDSA { constructor(name, hash, xof, pre) { assert(typeof name === 'string'); assert(hash); assert(xof); this.id = name; this.type = 'ecdsa'; this.hash = hash; this.xof = xof; this.native = 0; this._pre = pre || null; this._curve = null; this._schnorr = null; } get curve() { if (!this._curve) { this._curve = elliptic.curve(this.id, this._pre); this._curve.precompute(rng); this._pre = null; } return this._curve; } get schnorr() { if (!this._schnorr) this._schnorr = new Schnorr(this.curve, this.xof); return this._schnorr; } get size() { return this.curve.fieldSize; } get bits() { return this.curve.fieldBits; } privateKeyGenerate() { const a = this.curve.randomScalar(rng); return this.curve.encodeScalar(a); } privateKeyVerify(key) { assert(Buffer.isBuffer(key)); let a; try { a = this.curve.decodeScalar(key); } catch (e) { return false; } return !a.isZero() && a.cmp(this.curve.n) < 0; } privateKeyExport(key) { const pub = this.publicKeyCreate(key, false); const {x, y} = this.publicKeyExport(pub); return { d: Buffer.from(key), x, y }; } privateKeyImport(json) { assert(json && typeof json === 'object'); const a = BN.decode(json.d, this.curve.endian); if (a.isZero() || a.cmp(this.curve.n) >= 0) throw new Error('Invalid private key.'); return this.curve.encodeScalar(a); } privateKeyTweakAdd(key, tweak) { const t = this.curve.decodeScalar(tweak); if (t.cmp(this.curve.n) >= 0) throw new Error('Invalid scalar.'); const a = this.curve.decodeScalar(key); if (a.isZero() || a.cmp(this.curve.n) >= 0) throw new Error('Invalid private key.'); const k = a.add(t).imod(this.curve.n); if (k.isZero()) throw new Error('Invalid private key.'); return this.curve.encodeScalar(k); } privateKeyTweakMul(key, tweak) { const t = this.curve.decodeScalar(tweak); if (t.isZero() || t.cmp(this.curve.n) >= 0) throw new Error('Invalid scalar.'); const a = this.curve.decodeScalar(key); if (a.isZero() || a.cmp(this.curve.n) >= 0) throw new Error('Invalid private key.'); const k = a.mul(t).imod(this.curve.n); if (k.isZero()) throw new Error('Invalid private key.'); return this.curve.encodeScalar(k); } privateKeyNegate(key) { const a = this.curve.decodeScalar(key); if (a.isZero() || a.cmp(this.curve.n) >= 0) throw new Error('Invalid private key.'); const k = a.neg().imod(this.curve.n); return this.curve.encodeScalar(k); } privateKeyInvert(key) { const a = this.curve.decodeScalar(key); if (a.isZero() || a.cmp(this.curve.n) >= 0) throw new Error('Invalid private key.'); const k = a.invert(this.curve.n); return this.curve.encodeScalar(k); } publicKeyCreate(key, compress) { const a = this.curve.decodeScalar(key); if (a.isZero() || a.cmp(this.curve.n) >= 0) throw new Error('Invalid private key.'); const A = this.curve.g.mulBlind(a); return A.encode(compress); } publicKeyConvert(key, compress) { const A = this.curve.decodePoint(key); return A.encode(compress); } publicKeyFromUniform(bytes, compress) { const u = this.curve.decodeUniform(bytes); const A = this.curve.pointFromUniform(u); return A.encode(compress); } publicKeyToUniform(key, hint = rng.randomInt()) { const A = this.curve.decodePoint(key); const u = this.curve.pointToUniform(A, hint); return this.curve.encodeUniform(u, hint >>> 8); } publicKeyFromHash(bytes, compress) { const A = this.curve.pointFromHash(bytes); return A.encode(compress); } publicKeyToHash(key) { const A = this.curve.decodePoint(key); return this.curve.pointToHash(A, 0, rng); } publicKeyVerify(key) { assert(Buffer.isBuffer(key)); try { this.curve.decodePoint(key); } catch (e) { return false; } return true; } publicKeyExport(key) { const {x, y} = this.curve.decodePoint(key); return { x: this.curve.encodeField(x.fromRed()), y: this.curve.encodeField(y.fromRed()) }; } publicKeyImport(json, compress) { assert(json && typeof json === 'object'); const x = BN.decode(json.x, this.curve.endian); if (x.cmp(this.curve.p) >= 0) throw new Error('Invalid point.'); if (json.y != null) { const y = BN.decode(json.y, this.curve.endian); if (y.cmp(this.curve.p) >= 0) throw new Error('Invalid point.'); const A = this.curve.point(x, y); if (!A.validate()) throw new Error('Invalid point.'); return A.encode(compress); } const A = this.curve.pointFromX(x, json.sign); return A.encode(compress); } publicKeyTweakAdd(key, tweak, compress) { const t = this.curve.decodeScalar(tweak); if (t.cmp(this.curve.n) >= 0) throw new Error('Invalid scalar.'); const A = this.curve.decodePoint(key); const T = this.curve.g.jmul(t); const P = T.add(A); return P.encode(compress); } publicKeyTweakMul(key, tweak, compress) { const t = this.curve.decodeScalar(tweak); if (t.isZero() || t.cmp(this.curve.n) >= 0) throw new Error('Invalid scalar.'); const A = this.curve.decodePoint(key); const P = A.mul(t); return P.encode(compress); } publicKeyCombine(keys, compress) { assert(Array.isArray(keys)); let P = this.curve.jpoint(); for (const key of keys) { const A = this.curve.decodePoint(key); P = P.add(A); } return P.encode(compress); } publicKeyNegate(key, compress) { const A = this.curve.decodePoint(key); const P = A.neg(); return P.encode(compress); } signatureNormalize(sig) { const [r, s] = this._decodeCompact(sig); if (s.cmp(this.curve.nh) > 0) s.ineg().imod(this.curve.n); return this._encodeCompact(r, s); } signatureNormalizeDER(sig) { const [r, s] = this._decodeDER(sig, false); if (s.cmp(this.curve.nh) > 0) s.ineg().imod(this.curve.n); return this._encodeDER(r, s); } signatureExport(sig) { const [r, s] = this._decodeCompact(sig); return this._encodeDER(r, s); } signatureImport(sig) { const [r, s] = this._decodeDER(sig, false); return this._encodeCompact(r, s); } isLowS(sig) { assert(Buffer.isBuffer(sig)); let s; try { [, s] = this._decodeCompact(sig); } catch (e) { return false; } return s.cmp(this.curve.nh) <= 0; } isLowDER(sig) { assert(Buffer.isBuffer(sig)); let s; try { [, s] = this._decodeDER(sig, false); } catch (e) { return false; } return s.cmp(this.curve.nh) <= 0; } sign(msg, key) { const [r, s] = this._sign(msg, key); return this._encodeCompact(r, s); } signRecoverable(msg, key) { const [r, s, param] = this._sign(msg, key); return [this._encodeCompact(r, s), param]; } signDER(msg, key) { const [r, s] = this._sign(msg, key); return this._encodeDER(r, s); } signRecoverableDER(msg, key) { const [r, s, param] = this._sign(msg, key); return [this._encodeDER(r, s), param]; } _sign(msg, key) { // ECDSA Signing. // // [SEC1] Page 44, Section 4.1.3. // [GECC] Algorithm 4.29, Page 184, Section 4.4.1. // [RFC6979] Page 9, Section 2.4. // [RFC6979] Page 10, Section 3.2. // // Assumptions: // // - Let `m` be an integer reduced from bytes. // - Let `a` be a secret non-zero scalar. // - Let `k` be a random non-zero scalar. // - R != O, r != 0, s != 0. // // Computation: // // k = random integer in [1,n-1] // R = G * k // r = x(R) mod n // s = (r * a + m) / k mod n // s = -s mod n, if s > n / 2 // S = (r, s) // // We can blind the scalar arithmetic // with a random integer `b` like so: // // b = random integer in [1,n-1] // s = (r * (a * b) + m * b) / (k * b) mod n // // Note that `k` must remain secret, // otherwise an attacker can compute: // // a = (s * k - m) / r mod n // // This means that if two signatures // share the same `r` value, an attacker // can compute: // // k = (m1 - m2) / (+-s1 - +-s2) mod n // a = (s1 * k - m1) / r mod n // // Assuming: // // s1 = (r * a + m1) / k mod n // s2 = (r * a + m2) / k mod n // // To mitigate this, `k` can be generated // deterministically using the HMAC-DRBG // construction described in [RFC6979]. const {n, nh} = this.curve; const G = this.curve.g; const a = this.curve.decodeScalar(key); if (a.isZero() || a.cmp(n) >= 0) throw new Error('Invalid private key.'); const m = this._reduce(msg); const nonce = this.curve.encodeScalar(m); const drbg = new HmacDRBG(this.hash, key, nonce); for (;;) { const bytes = drbg.generate(this.curve.scalarSize); const k = this._truncate(bytes); if (k.isZero() || k.cmp(n) >= 0) continue; const R = G.mulBlind(k); if (R.isInfinity()) continue; const x = R.getX(); const r = x.mod(n); if (r.isZero()) continue; const b = this.curve.randomScalar(rng); const ki = k.mul(b).fermat(n); const ba = a.mul(b).imod(n); const bm = m.mul(b).imod(n); const sk = r.mul(ba).iadd(bm).imod(n); const s = sk.mul(ki).imod(n); if (s.isZero()) continue; let param = R.isOdd() | (!x.eq(r) << 1); if (s.cmp(nh) > 0) { s.ineg().imod(n); param ^= 1; } return [r, s, param]; } } verify(msg, sig, key) { assert(Buffer.isBuffer(msg)); assert(Buffer.isBuffer(sig)); assert(Buffer.isBuffer(key)); let r, s; try { [r, s] = this._decodeCompact(sig); } catch (e) { return false; } try { return this._verify(msg, r, s, key); } catch (e) { return false; } } verifyDER(msg, sig, key) { assert(Buffer.isBuffer(msg)); assert(Buffer.isBuffer(sig)); assert(Buffer.isBuffer(key)); let r, s; try { [r, s] = this._decodeDER(sig, false); } catch (e) { return false; } try { return this._verify(msg, r, s, key); } catch (e) { return false; } } _verify(msg, r, s, key) { // ECDSA Verification. // // [SEC1] Page 46, Section 4.1.4. // [GECC] Algorithm 4.30, Page 184, Section 4.4.1. // // Assumptions: // // - Let `m` be an integer reduced from bytes. // - Let `r` and `s` be signature elements. // - Let `A` be a valid group element. // - r != 0, r < n. // - s != 0, s < n. // - R != O. // // Computation: // // u1 = m / s mod n // u2 = r / s mod n // R = G * u1 + A * u2 // r == x(R) mod n // // Note that the signer can verify their // own signatures more efficiently with: // // R = G * ((u1 + u2 * a) mod n) // // Furthermore, we can avoid affinization // of `R` by scaling `r` by `z^2` and // repeatedly adding `n * z^2` to it up // to a certain threshold. const {n} = this.curve; const G = this.curve.g; const m = this._reduce(msg); const A = this.curve.decodePoint(key); if (r.isZero() || r.cmp(n) >= 0) return false; if (s.isZero() || s.cmp(n) >= 0) return false; const si = s.invert(n); const u1 = m.mul(si).imod(n); const u2 = r.mul(si).imod(n); const R = G.jmulAdd(u1, A, u2); return R.eqR(r); } recover(msg, sig, param, compress) { assert(Buffer.isBuffer(msg)); assert(Buffer.isBuffer(sig)); assert((param >>> 0) === param); assert((param & 3) === param, 'The recovery param is more than two bits.'); let r, s; try { [r, s] = this._decodeCompact(sig); } catch (e) { return null; } let A; try { A = this._recover(msg, r, s, param); } catch (e) { return null; } return A.encode(compress); } recoverDER(msg, sig, param, compress) { assert(Buffer.isBuffer(msg)); assert(Buffer.isBuffer(sig)); assert((param >>> 0) === param); assert((param & 3) === param, 'The recovery param is more than two bits.'); let r, s; try { [r, s] = this._decodeDER(sig, false); } catch (e) { return null; } let A; try { A = this._recover(msg, r, s, param); } catch (e) { return null; } return A.encode(compress); } _recover(msg, r, s, param) { // ECDSA Public Key Recovery. // // [SEC1] Page 47, Section 4.1.6. // // Assumptions: // // - Let `m` be an integer reduced from bytes. // - Let `r` and `s` be signature elements. // - Let `i` be an integer in [0,3]. // - x^3 + a * x + b is square in F(p). // - If i > 1 then r < (p mod n). // - r != 0, r < n. // - s != 0, s < n. // - A != O. // // Computation: // // x = r + n, if i > 1 // = r, otherwise // R' = (x, sqrt(x^3 + a * x + b)) // R = -R', if i mod 2 == 1 // = +R', otherwise // s1 = m / r mod n // s2 = s / r mod n // A = R * s2 - G * s1 // // Note that this implementation will have // trouble on curves where `p / n > 1`. const {n, pmodn} = this.curve; const G = this.curve.g; const m = this._reduce(msg); if (r.isZero() || r.cmp(n) >= 0) throw new Error('Invalid R value.'); if (s.isZero() || s.cmp(n) >= 0) throw new Error('Invalid S value.'); const sign = (param & 1) !== 0; const high = param >>> 1; let x = r; if (high) { if (this.curve.highOrder) throw new Error('Invalid high bit.'); if (x.cmp(pmodn) >= 0) throw new Error('Invalid R value.'); x = x.add(n); } const R = this.curve.pointFromX(x, sign); const ri = r.invert(n); const s1 = m.mul(ri).ineg().imod(n); const s2 = s.mul(ri).imod(n); const A = G.mulAdd(s1, R, s2); if (A.isInfinity()) throw new Error('Invalid point.'); return A; } derive(pub, priv, compress) { const A = this.curve.decodePoint(pub); const a = this.curve.decodeScalar(priv); if (a.isZero() || a.cmp(this.curve.n) >= 0) throw new Error('Invalid private key.'); if (this.curve.h.cmpn(1) > 0) { if (A.isSmall()) throw new Error('Invalid point.'); } const P = A.mulBlind(a, rng); return P.encode(compress); } /* * Schnorr */ schnorrSign(msg, key) { return this.schnorr.sign(msg, key); } schnorrVerify(msg, sig, key) { return this.schnorr.verify(msg, sig, key); } schnorrVerifyBatch(batch) { return this.schnorr.verifyBatch(batch); } /* * Helpers */ _encodeCompact(r, s) { return Buffer.concat([ this.curve.encodeScalar(r), this.curve.encodeScalar(s) ]); } _decodeCompact(sig) { assert(Buffer.isBuffer(sig)); const {n} = this.curve; const size = this.curve.scalarSize; if (sig.length !== size * 2) throw new Error('Invalid signature size.'); const Rraw = sig.slice(0, size); const Sraw = sig.slice(size, size * 2); const r = this.curve.decodeScalar(Rraw); const s = this.curve.decodeScalar(Sraw); if (r.cmp(n) >= 0 || s.cmp(n) >= 0) throw new Error('Invalid signature.'); return [r, s]; } _encodeDER(r, s) { const size = asn1.sizeInt(r) + asn1.sizeInt(s); const out = Buffer.alloc(asn1.sizeSeq(size)); let pos = 0; pos = asn1.writeSeq(out, pos, size); pos = asn1.writeInt(out, pos, r); pos = asn1.writeInt(out, pos, s); assert(pos === out.length); return out; } _decodeDER(sig, strict) { assert(Buffer.isBuffer(sig)); assert(typeof strict === 'boolean'); const {n} = this.curve; let pos = 0; let r, s; pos = asn1.readSeq(sig, pos, strict); [r, pos] = asn1.readInt(sig, pos, strict); [s, pos] = asn1.readInt(sig, pos, strict); if (strict && pos !== sig.length) throw new Error('Trailing bytes.'); if (r.cmp(n) >= 0 || s.cmp(n) >= 0) throw new Error('Invalid signature.'); return [r, s]; } _truncate(msg) { // Byte array to integer conversion. // // [SEC1] Step 5, Page 45, Section 4.1.3. // [FIPS186] Page 25, Section B.2. // // The two sources above disagree on this. // // FIPS186 simply modulos the entire byte // array by the order, whereas SEC1 takes // the left-most ceil(log2(n+1)) bits modulo // the order (and maybe does other stuff). // // Instead of trying to decipher all of // this nonsense, we simply replicate the // OpenSSL behavior (which, in actuality, // is more similar to the SEC1 behavior). assert(Buffer.isBuffer(msg)); const bits = this.curve.n.bitLength(); const bytes = (bits + 7) >>> 3; if (msg.length > bytes) msg = msg.slice(0, bytes); const m = BN.decode(msg, this.curve.endian); const d = msg.length * 8 - bits; if (d > 0) m.iushrn(d); return m; } _reduce(msg) { return this._truncate(msg).imod(this.curve.n); } } /* * Expose */ module.exports = ECDSA; }], [/* 31 */ 'bcrypto', '/lib/bn-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * bn.js - big numbers for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; module.exports = __node_require__(32 /* './js/bn' */); }], [/* 32 */ 'bcrypto', '/lib/js/bn.js', function(exports, module, __filename, __dirname, __meta) { /*! * bn.js - big numbers for bcrypto * Copyright (c) 2018-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Parts of this software are based on indutny/bn.js: * Copyright (c) 2015, Fedor Indutny (MIT License). * https://github.com/indutny/bn.js * * Parts of this software are based on golang/go: * Copyright (c) 2009, The Go Authors. All rights reserved. * https://github.com/golang/go * * Parts of this software are based on openssl/openssl: * Copyright (c) 1998-2018, The OpenSSL Project (Apache License v2.0). * Copyright (c) 1995-1998, Eric A. Young, Tim J. Hudson. All rights reserved. * https://github.com/openssl/openssl * * Parts of this software are based on libgmp: * Copyright (c) 1991-1997, 1999-2014, Free Software Foundation, Inc. * https://gmplib.org/ * * Parts of this software are based on v8/v8: * Copyright (c) 2017, The V8 Project Authors (BSD-Style License). * https://github.com/v8/v8 * * Resources: * https://github.com/indutny/bn.js/blob/master/lib/bn.js * https://github.com/indutny/miller-rabin/blob/master/lib/mr.js * https://github.com/golang/go/blob/master/src/math/big/int.go * https://github.com/golang/go/blob/master/src/math/big/nat.go * https://github.com/golang/go/blob/master/src/math/big/prime.go * https://github.com/openssl/openssl/tree/master/crypto/bn * https://github.com/openssl/openssl/blob/master/crypto/bn/bn_kron.c * https://github.com/gnutls/nettle/blob/master/mini-gmp.c * https://github.com/v8/v8/blob/master/src/objects/bigint.cc */ /* eslint valid-typeof: "off" */ 'use strict'; const {custom} = __node_require__(33 /* '../internal/custom' */); /* * Constants */ const zeros = [ '', '0', '00', '000', '0000', '00000', '000000', '0000000', '00000000', '000000000', '0000000000', '00000000000', '000000000000', '0000000000000', '00000000000000', '000000000000000', '0000000000000000', '00000000000000000', '000000000000000000', '0000000000000000000', '00000000000000000000', '000000000000000000000', '0000000000000000000000', '00000000000000000000000', '000000000000000000000000', '0000000000000000000000000' ]; const groupSizes = [ 0x00, 0x19, 0x10, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05 ]; const groupBases = [ 0x00000000, 0x02000000, 0x0290d741, 0x01000000, 0x02e90edd, 0x039aa400, 0x0267bf47, 0x01000000, 0x0290d741, 0x00989680, 0x012959c3, 0x0222c000, 0x03bd7765, 0x0072e440, 0x00adcea1, 0x01000000, 0x01704f61, 0x0206fc40, 0x02cddcf9, 0x03d09000, 0x003e5185, 0x004ea360, 0x006235f7, 0x00798000, 0x009502f9, 0x00b54ba0, 0x00daf26b, 0x01069c00, 0x0138f9ad, 0x0172c9e0, 0x01b4d89f, 0x02000000, 0x025528a1, 0x02b54a20, 0x03216b93, 0x039aa400 ]; const primes = { p192: null, p224: null, p521: null, k256: null, p251: null, p25519: null, p448: null }; const modes = { NONE: 0, QUO: 1, REM: 2, BOTH: 3, EUCLID: 4, ALL: 7 }; const WND_WIDTH = 4; const WND_SIZE = 1 << (WND_WIDTH - 1); const HAS_BIGINT = typeof BigInt === 'function'; /** * BN */ class BN { constructor(num, base, endian) { this.words = [0]; this.length = 1; this.negative = 0; this.red = null; this.from(num, base, endian); } /* * Addition Engine */ _iadd(a, b) { let carry = 0; let i = 0; // a.length > b.length if (a.length < b.length) [a, b] = [b, a]; if (a !== this) this._alloc(a.length); for (; i < b.length; i++) { const r = (a.words[i] | 0) + (b.words[i] | 0) + carry; this.words[i] = r & 0x3ffffff; carry = r >>> 26; } for (; carry !== 0 && i < a.length; i++) { const r = (a.words[i] | 0) + carry; this.words[i] = r & 0x3ffffff; carry = r >>> 26; } this.length = a.length; if (carry !== 0) { this._alloc(this.length + 1); this.words[this.length++] = carry; } else if (a !== this) { // Copy the rest of the words. for (; i < a.length; i++) this.words[i] = a.words[i]; } // Note: we shouldn't need to strip here. return this; } _iaddn(num) { this.words[0] += num; if (this.words[0] < 0x4000000) return this; // Carry. let i = 0; this._alloc(this.length + 1); this.words[this.length] = 0; for (; i < this.length && this.words[i] >= 0x4000000; i++) { this.words[i] -= 0x4000000; this.words[i + 1] += 1; } this.length = Math.max(this.length, i + 1); // Note: we shouldn't need to strip here. return this; } /* * Addition */ iadd(num) { enforce(BN.isBN(num), 'num', 'bignum'); if (this.negative === num.negative) { // x + y == x + y // (-x) + (-y) == -(x + y) this._iadd(this, num); } else { // x + (-y) == x - y == -(y - x) // (-x) + y == y - x == -(x - y) const cmp = this.ucmp(num); // x + (-x) == (-x) + x == 0 if (cmp === 0) { this.words[0] = 0; this.length = 1; this.negative = 0; return this; } if (cmp < 0) { this._isub(num, this); this.negative ^= 1; } else { this._isub(this, num); } } return this; } iaddn(num) { enforce(isSMI(num), 'num', 'smi'); const negative = (num < 0) | 0; if (negative) num = -num; if (this.negative === negative) { // x + y == x + y // (-x) + (-y) == -(x + y) this._iaddn(num); } else { // x + (-y) == x - y == -(y - x) // (-x) + y == y - x == -(x - y) if (this.length === 1 && this.words[0] < num) { this.words[0] = num - this.words[0]; this.negative ^= 1; } else { this._isubn(num); } } return this; } add(num) { enforce(BN.isBN(num), 'num', 'bignum'); if (num.length > this.length) return num.clone().iadd(this); return this.clone().iadd(num); } addn(num) { return this.clone().iaddn(num); } /* * Subtraction Engine */ _isub(a, b) { let carry = 0; let i = 0; // a > b assert(a.length >= b.length); if (a !== this) this._alloc(a.length); for (; i < b.length; i++) { const r = (a.words[i] | 0) - (b.words[i] | 0) + carry; carry = r >> 26; this.words[i] = r & 0x3ffffff; } for (; carry !== 0 && i < a.length; i++) { const r = (a.words[i] | 0) + carry; carry = r >> 26; this.words[i] = r & 0x3ffffff; } assert(carry === 0); // Copy rest of the words. if (a !== this) { for (; i < a.length; i++) this.words[i] = a.words[i]; } this.length = Math.max(this.length, i); return this._strip(); } _isubn(num) { this.words[0] -= num; if (this.words[0] >= 0) return this._normalize(); assert(this.length !== 1); // Carry. this._alloc(this.length + 1); for (let i = 0; i < this.length && this.words[i] < 0; i++) { this.words[i] += 0x4000000; this.words[i + 1] -= 1; } this.words[this.length] = 0; return this._strip(); } /* * Subtraction */ isub(num) { enforce(BN.isBN(num), 'num', 'bignum'); if (this.negative !== num.negative) { // x - (-y) == x + y // (-x) - y == -(x + y) this._iadd(this, num); } else { // x - y == x - y == -(y - x) // (-x) - (-y) == y - x == -(x - y) const cmp = this.ucmp(num); // x - x == 0 if (cmp === 0) { this.words[0] = 0; this.length = 1; this.negative = 0; return this; } if (cmp < 0) { this._isub(num, this); this.negative ^= 1; } else { this._isub(this, num); } } return this; } isubn(num) { enforce(isSMI(num), 'num', 'smi'); const negative = (num < 0) | 0; if (negative) num = -num; if (this.negative !== negative) { // x - (-y) == x + y // (-x) - y == -(x + y) this._iaddn(num); } else { // x - y == x - y == -(y - x) // (-x) - (-y) == y - x == -(x - y) if (this.length === 1 && this.words[0] < num) { this.words[0] = num - this.words[0]; this.negative ^= 1; } else { this._isubn(num); } } return this; } sub(num) { return this.clone().isub(num); } subn(num) { return this.clone().isubn(num); } /* * Multiplication Engine */ _mul(num, out) { enforce(BN.isBN(num), 'num', 'bignum'); enforce(BN.isBN(out), 'out', 'bignum'); if (this.length === 10 && num.length === 10) return comb10MulTo(this, num, out); const len = this.length + num.length; if (len < 63) return smallMulTo(this, num, out); if (len < 1024) return bigMulTo(this, num, out); return jumboMulTo(this, num, out); } /* * Multiplication */ imul(num) { return this.mul(num)._move(this); } imuln(num) { enforce(isSMI(num), 'num', 'smi'); const neg = (num < 0) | 0; if (neg) num = -num; // Carry. let carry = 0; for (let i = 0; i < this.length; i++) { const w = this.words[i] * num; const lo = (w & 0x3ffffff) + (carry & 0x3ffffff); carry >>= 26; carry += (w / 0x4000000) | 0; carry += lo >>> 26; this.words[i] = lo & 0x3ffffff; } this.negative ^= neg; if (carry !== 0) { this._alloc(this.length + 1); this.words[this.length++] = carry; } else { this._strip(); } return this; } mul(num) { enforce(BN.isBN(num), 'num', 'bignum'); const len = this.length + num.length; const out = new BN(); out.words = new Array(len); for (let i = 0; i < len; i ++) out.words[i] = 0; return this._mul(num, out); } muln(num) { return this.clone().imuln(num); } /* * Multiplication + Shift */ mulShift(num, bits) { enforce(BN.isBN(num), 'num', 'bignum'); enforce((bits >>> 0) === bits, 'bits', 'uint32'); const r = this.mul(num); const b = r.utestn(bits - 1); r.iushrn(bits); if (this.negative ^ num.negative) return r.isubn(b); return r.iaddn(b); } /* * Division Engine */ _div(num, flags) { enforce(BN.isBN(num), 'num', 'bignum'); assert((flags & modes.ALL) === flags); assert(flags !== modes.NONE); const a = this; const b = num; nonzero(!b.isZero()); if (a.isZero()) return [new BN(0), new BN(0)]; const as = a.negative; const bs = b.negative; a.negative = 0; b.negative = 0; let q = null; let r = null; if (a.ucmp(b) < 0) { if (flags & modes.QUO) q = new BN(0); if (flags & modes.REM) r = a.clone(); } else if (b.length === 1) { if (flags & modes.QUO) q = a.quon(b.words[0]); if (flags & modes.REM) r = a.remn(b.words[0]); } else { [q, r] = a._wordDiv(b, flags); } a.negative = as; b.negative = bs; if (flags & modes.QUO) { q.negative = a.negative ^ b.negative; q._normalize(); } if (flags & modes.REM) { r.negative = a.negative; r._normalize(); } if (flags & modes.EUCLID) { if (flags & modes.QUO) { assert((flags & modes.REM) !== 0); if (r.negative !== 0) { if (b.negative !== 0) q.iaddn(1); else q.isubn(1); } } if (flags & modes.REM) { if (r.negative !== 0) { if (b.negative !== 0) r.isub(b); else r.iadd(b); } } } return [q, r]; } _wordDiv(num, flags) { let a = this.clone(); let b = num; let q = null; let hi; // Normalize. const word = b.words[b.length - 1] | 0; const shift = 26 - countBits(word); if (shift !== 0) { b = b.clone(); a.iushln(shift); b.iushln(shift); hi = b.words[b.length - 1] | 0; } else { hi = word; } // Initialize quotient. const m = a.length - b.length; assert(m >= 0); if (flags & modes.QUO) { q = new BN(0); q.length = m + 1; q.words = new Array(q.length); for (let i = 0; i < q.length; i++) q.words[i] = 0; } // Diff. const d = a.clone(); d._ishlnsubmul(b, 1, m); if (d.negative === 0) { if (q) q.words[m] = 1; a = d; } // Divide. for (let j = m - 1; j >= 0; j--) { const ahi = a.words[b.length + j]; const alo = a.words[b.length + j - 1]; const quo = ((ahi * 0x4000000 + alo) / hi) | 0; let qj = Math.min(quo, 0x3ffffff); a._ishlnsubmul(b, qj, j); while (a.negative !== 0) { qj -= 1; a.negative = 0; a._ishlnsubmul(b, 1, j); a.ineg(); } if (q) q.words[j] = qj; } // Strip. if (q) q._strip(); // Denormalize. // Note: we shouldn't need to strip `a` here. if ((flags & modes.REM) && shift !== 0) a.iushrn(shift); return [q, a]; } _ishlnsubmul(num, mul, shift) { let carry = 0; let i = 0; this._expand(num.length + shift); for (; i < num.length; i++) { const k = (this.words[i + shift] | 0) + carry; const r = num.words[i] * mul; const w = k - (r & 0x3ffffff); carry = (w >> 26) - ((r / 0x4000000) | 0); this.words[i + shift] = w & 0x3ffffff; } for (; i < this.length - shift; i++) { const w = (this.words[i + shift] | 0) + carry; carry = w >> 26; this.words[i + shift] = w & 0x3ffffff; } if (carry === 0) return this._strip(); // Subtraction overflow. assert(carry === -1); carry = 0; for (let i = 0; i < this.length; i++) { const w = -(this.words[i] | 0) + carry; carry = w >> 26; this.words[i] = w & 0x3ffffff; } this.negative = 1; return this._strip(); } /* * Truncation Division + Modulo */ quorem(num) { return this._div(num, modes.BOTH); } /* * Truncation Division */ iquo(num) { return this.quo(num)._move(this); } iquon(num) { enforce(isSMI(num), 'num', 'smi'); nonzero(num !== 0); const neg = (num < 0) | 0; if (neg) num = -num; let carry = 0; for (let i = this.length - 1; i >= 0; i--) { const w = (this.words[i] | 0) + carry * 0x4000000; this.words[i] = (w / num) | 0; carry = w % num; } this.negative ^= neg; return this._strip(); } quo(num) { return this._div(num, modes.QUO)[0]; } quon(num) { return this.clone().iquon(num); } /* * Truncation Modulo */ irem(num) { return this.rem(num)._move(this); } iremn(num) { let m = this.remrn(num); if (m < 0) m = -m; this.words[0] = m; this.length = 1; return this._normalize(); } rem(num) { return this._div(num, modes.REM)[1]; } remn(num) { return this.clone().iremn(num); } remrn(num) { enforce(isSMI(num), 'num', 'smi'); nonzero(num !== 0); if (num < 0) num = -num; const p = (1 << 26) % num; let acc = 0; for (let i = this.length - 1; i >= 0; i--) acc = (p * acc + (this.words[i] | 0)) % num; return this.negative !== 0 ? (-acc | 0) : acc; } /* * Euclidean Division + Modulo */ divmod(num) { return this._div(num, modes.BOTH | modes.EUCLID); } /* * Euclidean Division */ idiv(num) { return this.div(num)._move(this); } idivn(num) { if (this.negative === 0) return this.iquon(num); const r = this.remrn(num); this.iquon(num); if (r < 0) { if (num < 0) this.iaddn(1); else this.isubn(1); } return this; } div(num) { return this._div(num, modes.BOTH | modes.EUCLID)[0]; } divn(num) { return this.clone().idivn(num); } /* * Euclidean Modulo */ imod(num) { if (this.ucmp(num) < 0) { if (this.negative !== 0) { this._isub(num, this); this.negative = 0; } return this; } return this.mod(num)._move(this); } imodn(num) { this.words[0] = this.modrn(num); this.length = 1; this.negative = 0; return this; } mod(num) { return this._div(num, modes.REM | modes.EUCLID)[1]; } modn(num) { return this.clone().imodn(num); } modrn(num) { enforce(isSMI(num), 'num', 'smi'); let r = this.remrn(num); if (r < 0) { if (num < 0) r -= num; else r += num; } return r; } /* * Round Division */ divRound(num) { const [q, r] = this.quorem(num); // Fast case - exact division. if (r.isZero()) return q; const bit = num.words[0] & 1; num.iushrn(1); const cmp = r.ucmp(num); num.iushln(1); num.words[0] |= bit; // Round down. if (cmp < 0 || (num.isOdd() && cmp === 0)) return q; // Round up. if (this.negative ^ num.negative) return q.isubn(1); return q.iaddn(1); } /* * Exponentiation */ ipow(num) { return this.pow(num)._move(this); } ipown(num) { return this.pown(num)._move(this); } pow(num) { enforce(BN.isBN(num), 'num', 'bignum'); let b = countBits(num.words[num.length - 1]); let r = new BN(1); for (let i = num.length - 1; i >= 0; i--) { const word = num.words[i]; for (let j = b - 1; j >= 0; j--) { r = r.sqr(); if ((word >> j) & 1) r = r.mul(this); } b = 26; } return r; } pown(num) { enforce(isSMI(num), 'num', 'smi'); if (num < 0) num = -num; if (num === 0) return new BN(1); if (num === 1) return this.clone(); const bits = countBits(num); let r = this; for (let i = bits - 2; i >= 0; i--) { r = r.sqr(); if ((num >> i) & 1) r = r.mul(this); } return r; } isqr() { return this.imul(this); } sqr() { return this.mul(this); } /* * Roots Engine */ _rootrem(pow, rem) { enforce((pow >>> 0) === pow, 'num', 'uint32'); if (pow === 0) throw new RangeError('Zeroth root.'); if (~pow & this.negative) throw new RangeError('Negative with even root.'); if (this.ucmpn(1) <= 0) return [this.clone(), new BN(0)]; let u = new BN(0); let t = BN.shift(1, this.bitLength() / pow + 1 | 0); let v, r; if (this.negative !== 0) t.ineg(); if (pow === 2) { do { u = t; t = this.quo(u); t.iadd(u); t.iushrn(1); } while (t.ucmp(u) < 0); } else { do { u = t; t = u.pown(pow - 1); t = this.quo(t); v = u.muln(pow - 1); t.iadd(v); t = t.quon(pow); } while (t.ucmp(u) < 0); } if (rem) { t = u.pown(pow); r = this.sub(t); } return [u, r]; } /* * Roots */ rootrem(pow) { return this._rootrem(pow, 1); } iroot(pow) { return this.root(pow)._move(this); } root(pow) { return this._rootrem(pow, 0)[0]; } isPower(pow) { enforce((pow >>> 0) === pow, 'num', 'uint32'); if (pow === 0 || (~pow & this.negative)) return false; const [, r] = this.rootrem(pow); return r.sign() === 0; } sqrtrem() { return this.rootrem(2); } isqrt() { return this.sqrt()._move(this); } sqrt() { return this.root(2); } isSquare() { return this.isPower(2); } /* * AND */ iand(num) { enforce(BN.isBN(num), 'num', 'bignum'); let x = this; let y = num; if (x === y) return x; if ((x.negative | y.negative) === 0) return x.iuand(y); if ((x.negative & y.negative) === 1) { // (-x) & (-y) == ~(x-1) & ~(y-1) // == ~((x-1) | (y-1)) // == -(((x-1) | (y-1)) + 1) x.iaddn(1); y.iaddn(1); x.iuor(y); x.isubn(1); y.isubn(1); return x; } // Assume x is the positive number. if (x.negative !== 0) [x, y] = [y.clone(), x]; // x & (-y) == x & ~(y-1) // == x & ~(y-1) const width = x.bitLength(); y.iaddn(1); y.inotn(width); x.iuand(y); y.inotn(width); y.isubn(1); return x._move(this); } iandn(num) { enforce(isSMI(num), 'num', 'smi'); if ((this.negative | (num < 0)) !== 0) return this.iand(new BN(num)); this.words[0] &= num; this.length = 1; return this; } and(num) { return this.clone().iand(num); } andn(num) { return this.clone().iandn(num); } andrn(num) { enforce(isSMI(num), 'num', 'smi'); if ((this.negative | (num < 0)) !== 0) { const n = this.iand(new BN(num)); if (n.length > 1) throw new RangeError('Number exceeds 26 bits.'); return n.negative !== 0 ? -n.words[0] : n.words[0]; } return this.words[0] & num; } /* * Unsigned AND */ iuand(num) { enforce(BN.isBN(num), 'num', 'bignum'); this.length = Math.min(this.length, num.length); for (let i = 0; i < this.length; i++) this.words[i] &= num.words[i]; return this._strip(); } iuandn(num) { enforce(isSMI(num), 'num', 'smi'); this.words[0] &= Math.abs(num); this.length = 1; return this._normalize(); } uand(num) { return this.clone().iuand(num); } uandn(num) { return this.clone().iuandn(num); } uandrn(num) { enforce(isSMI(num), 'num', 'smi'); const n = this.words[0] & Math.abs(num); return this.negative !== 0 ? (-n | 0) : n; } /* * OR */ ior(num) { enforce(BN.isBN(num), 'num', 'bignum'); let x = this; let y = num; if (x === y) return x; if ((x.negative | y.negative) === 0) return x.iuor(y); if ((x.negative & y.negative) === 1) { // (-x) | (-y) == ~(x-1) | ~(y-1) // == ~((x-1) & (y-1)) // == -(((x-1) & (y-1)) + 1) x.iaddn(1); y.iaddn(1); x.iuand(y); x.isubn(1); y.isubn(1); return x; } // Assume x is the positive number. y = y.clone(); if (x.negative !== 0) [x, y] = [y, x]; // x | (-y) == x | ~(y-1) // == ~((y-1) & ~x) // == -(((y-1) & ~x) + 1) y.iaddn(1); x.inotn(y.bitLength()); y.iuand(x); y.isubn(1); return y._move(this); } iorn(num) { enforce(isSMI(num), 'num', 'smi'); if ((this.negative | (num < 0)) !== 0) return this.ior(new BN(num)); this.words[0] |= num; return this; } or(num) { return this.clone().ior(num); } orn(num) { return this.clone().iorn(num); } /* * Unsigned OR */ iuor(num) { enforce(BN.isBN(num), 'num', 'bignum'); this._expand(num.length); for (let i = 0; i < num.length; i++) this.words[i] |= num.words[i]; // Note: we shouldn't need to strip here. return this; } iuorn(num) { enforce(isSMI(num), 'num', 'smi'); this.words[0] |= Math.abs(num); return this; } uor(num) { return this.clone().iuor(num); } uorn(num) { return this.clone().iuorn(num); } /* * XOR */ ixor(num) { enforce(BN.isBN(num), 'num', 'bignum'); let x = this; let y = num; if (x === y) { x.words[0] = 0; x.length = 1; x.negative = 0; return x; } if ((x.negative | y.negative) === 0) return x.iuxor(y); if ((x.negative & y.negative) === 1) { // (-x) ^ (-y) == ~(x-1) ^ ~(y-1) // == (x-1) ^ (y-1) x.iaddn(1); y.iaddn(1); x.iuxor(y); x.ineg(); y.isubn(1); return x; } // Assume x is the positive number. if (x.negative !== 0) [x, y] = [y.clone(), x]; // x ^ (-y) == x ^ ~(y-1) // == ~(x ^ (y-1)) // == -((x ^ (y-1)) + 1) y.iaddn(1); x.iuxor(y); x.iaddn(1); x.ineg(); y.isubn(1); return x._move(this); } ixorn(num) { enforce(isSMI(num), 'num', 'smi'); if ((this.negative | (num < 0)) !== 0) return this.ixor(new BN(num)); this.words[0] ^= num; return this; } xor(num) { return this.clone().ixor(num); } xorn(num) { return this.clone().ixorn(num); } /* * Unsigned XOR */ iuxor(num) { enforce(BN.isBN(num), 'num', 'bignum'); let a = this; let b = num; if (a.length < b.length) [a, b] = [b, a]; let i = 0; for (; i < b.length; i++) this.words[i] = a.words[i] ^ b.words[i]; if (a !== this) { this._alloc(a.length); for (; i < a.length; i++) this.words[i] = a.words[i]; } this.length = a.length; return this._strip(); } iuxorn(num) { enforce(isSMI(num), 'num', 'smi'); this.words[0] ^= Math.abs(num); return this._normalize(); } uxor(num) { return this.clone().iuxor(num); } uxorn(num) { return this.clone().iuxorn(num); } /* * NOT */ inot() { if (this.negative !== 0) { // ~(-x) == ~(~(x-1)) == x-1 this.ineg().isubn(1); } else { // ~x == -x-1 == -(x+1) this.iaddn(1).ineg(); } return this; } not() { return this.clone().inot(); } inotn(width) { enforce((width >>> 0) === width, 'width', 'uint32'); const r = width % 26; let s = Math.ceil(width / 26); let i = 0; // Extend the buffer with leading zeroes. this._expand(s); if (r > 0) s -= 1; // Handle complete words. for (; i < s; i++) this.words[i] ^= 0x3ffffff; // Handle the residue. if (r > 0) this.words[i] ^= (1 << r) - 1; // And remove leading zeroes. return this._strip(); } notn(width) { return this.clone().inotn(width); } /* * Left Shift */ ishl(num) { enforce(BN.isBN(num), 'bits', 'bignum'); enforce(num.bitLength() <= 32, 'bits', 'uint32'); return this.ishln(num.toNumber()); } ishln(bits) { return this.iushln(bits); } shl(num) { return this.clone().ishl(num); } shln(bits) { return this.clone().ishln(bits); } /* * Unsigned Left Shift */ iushl(num) { enforce(BN.isBN(num), 'bits', 'bignum'); enforce(num.bitLength() <= 32, 'bits', 'uint32'); return this.iushln(num.toNumber()); } iushln(bits) { enforce((bits >>> 0) === bits, 'bits', 'uint32'); const r = bits % 26; const s = (bits - r) / 26; const mask = ((1 << r) - 1) << (26 - r); if (r !== 0) { let carry = 0; for (let i = 0; i < this.length; i++) { const ncarry = this.words[i] & mask; const c = ((this.words[i] | 0) - ncarry) << r; this.words[i] = c | carry; carry = ncarry >>> (26 - r); } if (carry !== 0) { this._alloc(this.length + 1); this.words[this.length++] = carry; } } if (s !== 0) { this._alloc(this.length + s); for (let i = this.length - 1; i >= 0; i--) this.words[i + s] = this.words[i]; for (let i = 0; i < s; i++) this.words[i] = 0; this.length += s; } return this._strip(); } ushl(num) { return this.clone().iushl(num); } ushln(bits) { return this.clone().iushln(bits); } /* * Right Shift Engine */ _split(bits, output) { const r = bits % 26; const s = Math.min((bits - r) / 26, this.length); const mask = (1 << r) - 1; // Extended mode, copy masked part. if (output) { output._alloc(s); for (let i = 0; i < s; i++) output.words[i] = this.words[i]; output.length = s; } if (s === 0) { // No-op, we should not move anything at all. } else if (this.length > s) { this.length -= s; for (let i = 0; i < this.length; i++) this.words[i] = this.words[i + s]; } else { this.words[0] = 0; this.length = 1; } let carry = 0; if (r !== 0) { for (let i = this.length - 1; i >= 0; i--) { const word = this.words[i] | 0; this.words[i] = (carry << (26 - r)) | (word >>> r); carry = word & mask; } } // Push carried bits as a mask. if (output) { if (carry !== 0) { output._alloc(output.length + 1); output.words[output.length++] = carry; } else { if (output.length === 0) output.words[output.length++] = 0; output._strip(); } } return this._strip(); } /* * Right Shift */ ishr(num) { enforce(BN.isBN(num), 'bits', 'bignum'); enforce(num.bitLength() <= 32, 'bits', 'uint32'); return this.ishrn(num.toNumber()); } ishrn(bits) { enforce((bits >>> 0) === bits, 'bits', 'uint32'); if (this.negative !== 0) { // (-x) >> y == ~(x-1) >> y // == ~((x-1) >> y) // == -(((x-1) >> y) + 1) this.iaddn(1); this.iushrn(bits); this.isubn(1); return this; } return this.iushrn(bits); } shr(num) { return this.clone().ishr(num); } shrn(bits) { return this.clone().ishrn(bits); } /* * Unsigned Right Shift */ iushr(num) { enforce(BN.isBN(num), 'bits', 'bignum'); enforce(num.bitLength() <= 32, 'bits', 'uint32'); return this.iushrn(num.toNumber()); } iushrn(bits) { enforce((bits >>> 0) === bits, 'bits', 'uint32'); return this._split(bits, null); } ushr(num) { return this.clone().iushr(num); } ushrn(bits) { return this.clone().iushrn(bits); } /* * Bit Manipulation */ setn(bit, val) { enforce((bit >>> 0) === bit, 'bit', 'uint32'); if (this.negative !== 0) { this.iaddn(1); this.usetn(bit, !val); this.isubn(1); return this; } return this.usetn(bit, val); } usetn(bit, val) { enforce((bit >>> 0) === bit, 'bit', 'uint32'); const r = bit % 26; const s = (bit - r) / 26; this._expand(s + 1); if (val) this.words[s] |= (1 << r); else this.words[s] &= ~(1 << r); return this._strip(); } testn(bit) { enforce((bit >>> 0) === bit, 'bit', 'uint32'); const r = bit % 26; const s = (bit - r) / 26; // Fast case: bit is much higher than all existing words. if (this.length <= s) return this.negative; // Check bit and return. const w = this.words[s]; const val = (w >> r) & 1; if (this.negative !== 0) { if (r > 0 && (w & ((1 << r) - 1))) return val ^ 1; let j = s; while (j--) { if (this.words[j] > 0) return val ^ 1; } } return val; } utestn(bit) { enforce((bit >>> 0) === bit, 'bit', 'uint32'); const r = bit % 26; const s = (bit - r) / 26; // Fast case: bit is much higher than all existing words. if (this.length <= s) return 0; // Check bit and return. return (this.words[s] >> r) & 1; } imaskn(bits) { enforce((bits >>> 0) === bits, 'bits', 'uint32'); if (this.negative !== 0) { this.iaddn(1); this.inotn(bits + 1); this.ineg(); } return this.iumaskn(bits); } maskn(bits) { return this.clone().imaskn(bits); } iumaskn(bits) { enforce((bits >>> 0) === bits, 'bits', 'uint32'); const r = bits % 26; let s = (bits - r) / 26; if (this.length <= s) return this; if (r !== 0) s += 1; this.length = Math.min(s, this.length); if (r !== 0) this.words[this.length - 1] &= (1 << r) - 1; if (this.length === 0) this.words[this.length++] = 0; return this._strip(); } umaskn(bits) { return this.clone().iumaskn(bits); } andln(num) { return this.words[0] & num; } bit(pos) { return this.utestn(pos); } bits(pos, width) { enforce((pos >>> 0) === pos, 'pos', 'uint32'); enforce((width >>> 0) === width, 'width', 'uint32'); enforce(width <= 26, 'width', 'width'); const shift = pos % 26; const index = (pos - shift) / 26; if (index >= this.length) return 0; let bits = (this.words[index] >> shift) & ((1 << width) - 1); if (shift + width > 26 && index + 1 < this.length) { const more = shift + width - 26; const next = this.words[index + 1] & ((1 << more) - 1); bits |= next << (26 - shift); } return bits; } /* * Negation */ ineg() { if (!this.isZero()) this.negative ^= 1; return this; } neg() { return this.clone().ineg(); } iabs() { this.negative = 0; return this; } abs() { return this.clone().iabs(); } /* * Comparison */ cmp(num) { enforce(BN.isBN(num), 'num', 'bignum'); if (this.negative !== num.negative) return num.negative - this.negative; const res = this.ucmp(num); if (this.negative !== 0) return -res | 0; return res; } cmpn(num) { enforce(isSMI(num), 'num', 'smi'); const negative = (num < 0) | 0; if (this.negative !== negative) return negative - this.negative; const res = this.ucmpn(num); if (this.negative !== 0) return -res | 0; return res; } eq(num) { return this.cmp(num) === 0; } eqn(num) { return this.cmpn(num) === 0; } gt(num) { return this.cmp(num) > 0; } gtn(num) { return this.cmpn(num) > 0; } gte(num) { return this.cmp(num) >= 0; } gten(num) { return this.cmpn(num) >= 0; } lt(num) { return this.cmp(num) < 0; } ltn(num) { return this.cmpn(num) < 0; } lte(num) { return this.cmp(num) <= 0; } lten(num) { return this.cmpn(num) <= 0; } sign() { if (this.negative !== 0) return -1; if (this.length === 1 && this.words[0] === 0) return 0; return 1; } isZero() { return this.length === 1 && this.words[0] === 0; } isNeg() { return this.negative !== 0; } isPos() { return this.negative === 0; } isOdd() { return (this.words[0] & 1) === 1; } isEven() { return (this.words[0] & 1) === 0; } /* * Unsigned Comparison */ ucmp(num) { enforce(BN.isBN(num), 'num', 'bignum'); if (this.length < num.length) return -1; if (this.length > num.length) return 1; for (let i = this.length - 1; i >= 0; i--) { const a = this.words[i] | 0; const b = num.words[i] | 0; if (a === b) continue; return (a > b) - (a < b); } return 0; } ucmpn(num) { enforce(isSMI(num), 'num', 'smi'); if (this.length > 1) return 1; const w = this.words[0] | 0; if (num < 0) num = -num; return (w > num) - (w < num); } /* * Number Theoretic Functions */ legendre(num) { const red = HAS_BIGINT ? BN.red(num) : BN.mont(num); return this.toRed(red).redLegendre(); } jacobi(num) { // See: A Binary Algorithm for the Jacobi Symbol // J. Shallit, J. Sorenson // Page 3, Section 3 enforce(BN.isBN(num), 'num', 'bignum'); if (num.isZero() || num.isEven()) throw new Error('jacobi: `num` must be odd.'); let a = this._cloneNormal(); let b = num.clone(); let j = 1; if (b.isNeg()) { if (a.isNeg()) j = -1; b.ineg(); } if (a.isNeg() || a.ucmp(b) >= 0) a.imod(b); while (!a.isZero()) { const bits = a._makeOdd(); if (bits & 1) { const bmod8 = b.andln(7); if (bmod8 === 3 || bmod8 === 5) j = -j; } if (a.ucmp(b) < 0) { [a, b] = [b, a]; if (a.andln(3) === 3 && b.andln(3) === 3) j = -j; } a._isub(a, b).iushrn(1); const bmod8 = b.andln(7); if (bmod8 === 3 || bmod8 === 5) j = -j; } if (b.cmpn(1) !== 0) return 0; return j; } kronecker(num) { enforce(BN.isBN(num), 'num', 'bignum'); const table = [ 0, 1, 0, -1, 0, -1, 0, 1 ]; let a = this._cloneNormal(); let b = num.clone(); let k = 1; if (b.isZero()) return a.ucmpn(1) === 0 ? k : 0; if (!a.isOdd() && !b.isOdd()) return 0; const bits = b._makeOdd(); if (bits & 1) k = table[a.andln(7)]; if (b.isNeg()) { if (a.isNeg()) k = -k; b.ineg(); } while (!a.isZero()) { const bits = a._makeOdd(); if (bits & 1) k *= table[b.andln(7)]; const w = a.words[0] ^ (a.negative * 0x3ffffff); if (w & b.words[0] & 2) k = -k; b.imod(a); [a, b] = [b, a]; b.negative = 0; } if (b.cmpn(1) !== 0) return 0; return k; } igcd(num) { return this.gcd(num)._move(this); } gcd(num) { enforce(BN.isBN(num), 'num', 'bignum'); if (this.isZero()) return num.abs(); if (num.isZero()) return this.abs(); let a = this.clone(); let b = num.clone(); a.negative = 0; b.negative = 0; // Remove common factor of two. const shift = a._factor2(b); if (shift !== 0) { a.iushrn(shift); b.iushrn(shift); } for (;;) { a._makeOdd(); b._makeOdd(); const cmp = a.ucmp(b); if (cmp < 0) { // a > b [a, b] = [b, a]; } else if (cmp === 0 || b.ucmpn(1) === 0) { // Break if a == b. // Break if b == 1 to avoid repeated subtraction. break; } a._isub(a, b); } return b.iushln(shift); } ilcm(num) { return this.lcm(num)._move(this); } lcm(num) { enforce(BN.isBN(num), 'num', 'bignum'); if (this.isZero() || num.isZero()) return new BN(0); return this.quo(this.gcd(num)).mul(num).iabs(); } egcd(num) { enforce(BN.isBN(num), 'num', 'bignum'); if (this.isZero()) { return [ new BN(0), new BN(num.sign()), num.abs() ]; } if (num.isZero()) { return [ new BN(this.sign()), new BN(0), this.abs() ]; } const x = this.clone(); const y = num.clone(); x.negative = 0; y.negative = 0; // A * x + B * y = x const A = new BN(1); const B = new BN(0); // C * x + D * y = y const C = new BN(0); const D = new BN(1); // Remove common factor of two. const g = x._factor2(y); if (g > 0) { x.iushrn(g); y.iushrn(g); } const xp = x.clone(); const yp = y.clone(); while (!x.isZero()) { let i = x._makeOdd(); let j = y._makeOdd(); while (i--) { if (A.isOdd() || B.isOdd()) { A.iadd(yp); B.isub(xp); } A.iushrn(1); B.iushrn(1); } while (j--) { if (C.isOdd() || D.isOdd()) { C.iadd(yp); D.isub(xp); } C.iushrn(1); D.iushrn(1); } if (x.cmp(y) >= 0) { x.isub(y); A.isub(C); B.isub(D); } else { y.isub(x); C.isub(A); D.isub(B); } } if (this.negative !== 0) C.ineg(); if (num.negative !== 0) D.ineg(); return [C, D, y.iushln(g)]; } iinvert(num) { return this.invert(num)._move(this); } invert(num) { enforce(BN.isBN(num), 'num', 'bignum'); range(num.sign() > 0, 'invert'); if (num.isOdd()) return this._invertp(num); if (num.cmpn(1) === 0) throw new RangeError('Not invertible.'); const [s,, g] = this.egcd(num); if (g.cmpn(1) !== 0) throw new RangeError('Not invertible.'); return s.imod(num); } ifermat(num) { return this.fermat(num)._move(this); } fermat(num) { const red = HAS_BIGINT ? BN.red(num) : BN.mont(num); return this.toRed(red).redFermat().fromRed(); } ipowm(y, m, mont) { return this.powm(y, m, mont)._move(this); } powm(y, m, mont) { const red = !HAS_BIGINT && mont ? BN.mont(m) : BN.red(m); return this.toRed(red).redPow(y).fromRed(); } ipowmn(y, m, mont) { return this.powmn(y, m, mont)._move(this); } powmn(y, m, mont) { const red = mont ? BN.mont(m) : BN.red(m); return this.toRed(red).redPown(y).fromRed(); } isqrtm(p) { return this.sqrtm(p)._move(this); } sqrtm(p) { enforce(BN.isBN(p), 'p', 'bignum'); let red; if (p.andln(3) === 3 || p.andln(7) === 5) { // Probably not worth the setup. red = BN.red(p); } else { red = BN.mont(p); } return this.toRed(red).redSqrt().fromRed(); } isqrtpq(p, q) { return this.sqrtpq(p, q)._move(this); } sqrtpq(p, q) { const sp = this.sqrtm(p); const sq = this.sqrtm(q); const [mp, mq] = p.egcd(q); const lhs = sq.mul(mp).mul(p); const rhs = sp.mul(mq).mul(q); const n = p.mul(q); return lhs.iadd(rhs).imod(n); } /* * Primality Testing */ isPrime(rng, reps, limit) { enforce((reps >>> 0) === reps, 'reps', 'uint32'); if (!this.isPrimeMR(rng, reps + 1, true)) return false; if (!this.isPrimeLucas(limit)) return false; return true; } isPrimeMR(rng, reps, force2 = false) { enforce((reps >>> 0) === reps, 'reps', 'uint32'); enforce(reps > 0, 'reps', 'integer'); enforce(typeof force2 === 'boolean', 'force2', 'boolean'); const n = this; if (n.cmpn(7) < 0) { return n.cmpn(2) === 0 || n.cmpn(3) === 0 || n.cmpn(5) === 0; } if (n.isEven()) return false; const nm1 = n.subn(1); const nm3 = nm1.subn(2); const k = nm1.zeroBits(); const q = nm1.ushrn(k); const red = BN.red(n); const rnm1 = nm1.toRed(red); const rone = new BN(1).toRed(red); next: for (let i = 0; i < reps; i++) { let x; if (i === reps - 1 && force2) { x = new BN(2); } else { x = BN.random(rng, 0, nm3); x.iaddn(2); } let y = x.toRed(red).redPow(q); if (y.cmp(rone) === 0 || y.cmp(rnm1) === 0) continue; for (let j = 1; j < k; j++) { y = y.redSqr(); if (y.cmp(rnm1) === 0) continue next; if (y.cmp(rone) === 0) return false; } return false; } return true; } isPrimeLucas(limit = 0) { enforce((limit >>> 0) === limit, 'limit', 'uint32'); const n = this; // Ignore 0 and 1. if (n.cmpn(1) <= 0) return false; // Two is the only even prime. if (n.isEven()) return n.cmpn(2) === 0; let p = 3; for (;;) { if (p > 10000) { // Thought to be impossible. throw new Error(`Cannot find (D/n) = -1 for ${n.toString(10)}.`); } if (limit !== 0 && p > limit) { // Optional DoS limit. return false; } const d = new BN(p * p - 4); const j = d.jacobi(n); if (j === -1) break; if (j === 0) return n.cmpn(p + 2) === 0; if (p === 40) { if (n.isSquare()) return false; } p += 1; } const s = n.addn(1); const r = s._makeOdd(); let vk = new BN(2); let vk1 = new BN(p); for (let i = s.bitLength(); i >= 0; i--) { if (s.utestn(i)) { vk = vk.mul(vk1).isubn(p).imod(n); vk1 = vk1.sqr().isubn(2).imod(n); } else { vk1 = vk1.mul(vk).isubn(p).imod(n); vk = vk.sqr().isubn(2).imod(n); } } if (vk.cmpn(2) === 0 || vk.cmp(n.subn(2)) === 0) { const a = vk.muln(p).imod(n); const b = vk1.ushln(1).imod(n); if (a.cmp(b) === 0) return true; } for (let t = 0; t < r - 1; t++) { if (vk.isZero()) return true; if (vk.cmpn(2) === 0) return false; vk = vk.sqr().isubn(2).imod(n); } return false; } /* * Twos Complement */ toTwos(width) { if (this.negative !== 0) return this.abs().inotn(width).iaddn(1); return this.clone(); } fromTwos(width) { enforce((width >>> 0) === width, 'width', 'uint32'); range(width > 0, 'width'); if (this.testn(width - 1)) return this.notn(width).iaddn(1).ineg(); return this.clone(); } /* * Reduction Context */ toRed(ctx) { enforce(ctx instanceof Red, 'ctx', 'reduction context'); if (this.red) throw new Error('Already in reduction context.'); return ctx.convertTo(this); } fromRed() { red(this.red, 'fromRed'); return this.red.convertFrom(this); } forceRed(ctx) { enforce(ctx instanceof Red, 'ctx', 'reduction context'); if (this.red) { if (!ctx.m.eq(this.red.m) || ctx.mont !== this.red.mont) throw new Error('Already in reduction context.'); } else { range(this.negative === 0, 'red'); range(this.ucmp(ctx.m) < 0, 'red'); } return this.clone()._forceRed(ctx); } redIAdd(num) { enforce(BN.isBN(num), 'num', 'bignum'); red(this.red, 'redIAdd'); return this.red.iadd(this, num); } redAdd(num) { enforce(BN.isBN(num), 'num', 'bignum'); red(this.red, 'redAdd'); return this.red.add(this, num); } redIAddn(num) { enforce(isSMI(num), 'num', 'smi'); red(this.red, 'redIAddn'); return this.red.iaddn(this, num); } redAddn(num) { enforce(isSMI(num), 'num', 'smi'); red(this.red, 'redAddn'); return this.red.addn(this, num); } redISub(num) { enforce(BN.isBN(num), 'num', 'bignum'); red(this.red, 'redISub'); return this.red.isub(this, num); } redSub(num) { enforce(BN.isBN(num), 'num', 'bignum'); red(this.red, 'redSub'); return this.red.sub(this, num); } redISubn(num) { enforce(isSMI(num), 'num', 'smi'); red(this.red, 'redISubn'); return this.red.isubn(this, num); } redSubn(num) { enforce(isSMI(num), 'num', 'smi'); red(this.red, 'redSubn'); return this.red.subn(this, num); } redIMul(num) { enforce(BN.isBN(num), 'num', 'bignum'); red(this.red, 'redIMul'); return this.red.imul(this, num); } redMul(num) { enforce(BN.isBN(num), 'num', 'bignum'); red(this.red, 'redMul'); return this.red.mul(this, num); } redIMuln(num) { enforce(isSMI(num), 'num', 'smi'); red(this.red, 'redIMuln'); return this.red.imuln(this, num); } redMuln(num) { enforce(isSMI(num), 'num', 'smi'); red(this.red, 'redMuln'); return this.red.muln(this, num); } redIDiv(num) { enforce(BN.isBN(num), 'num', 'bignum'); red(this.red, 'redIDiv'); return this.red.idiv(this, num); } redDiv(num) { enforce(BN.isBN(num), 'num', 'bignum'); red(this.red, 'redDiv'); return this.red.div(this, num); } redIDivn(num) { enforce(isSMI(num), 'num', 'smi'); red(this.red, 'redIDivn'); return this.red.idivn(this, num); } redDivn(num) { enforce(isSMI(num), 'num', 'smi'); red(this.red, 'redDivn'); return this.red.divn(this, num); } redIPow(num) { enforce(BN.isBN(num), 'num', 'bignum'); red(this.red, 'redIPow'); nonred(!num.red, 'redIPow'); return this.red.ipow(this, num); } redPow(num) { enforce(BN.isBN(num), 'num', 'bignum'); red(this.red, 'redPow'); nonred(!num.red, 'redPow'); return this.red.pow(this, num); } redIPown(num) { enforce(isSMI(num), 'num', 'smi'); red(this.red, 'redIPown'); return this.red.ipown(this, num); } redPown(num) { enforce(isSMI(num), 'num', 'smi'); red(this.red, 'redPown'); return this.red.pown(this, num); } redISqr() { red(this.red, 'redISqr'); return this.red.isqr(this); } redSqr() { red(this.red, 'redSqr'); return this.red.sqr(this); } redISqrt() { red(this.red, 'redISqrt'); return this.red.isqrt(this); } redSqrt() { red(this.red, 'redSqrt'); return this.red.sqrt(this); } redIDivSqrt(v) { red(this.red, 'redIDivSqrt'); return this.red.idivsqrt(this, v); } redDivSqrt(v) { red(this.red, 'redDivSqrt'); return this.red.divsqrt(this, v); } redIsSquare() { red(this.red, 'redIsSquare'); return this.red.isSquare(this); } redIShl(num) { enforce(BN.isBN(num), 'num', 'bignum'); red(this.red, 'redIShl'); nonred(!num.red, 'redIShl'); return this.red.ishl(this, num); } redShl(num) { enforce(BN.isBN(num), 'num', 'bignum'); red(this.red, 'redShl'); nonred(!num.red, 'redShl'); return this.red.shl(this, num); } redIShln(num) { enforce((num >>> 0) === num, 'num', 'uint32'); red(this.red, 'redIShln'); return this.red.ishln(this, num); } redShln(num) { enforce((num >>> 0) === num, 'num', 'uint32'); red(this.red, 'redShln'); return this.red.shln(this, num); } redINeg() { red(this.red, 'redINeg'); return this.red.ineg(this); } redNeg() { red(this.red, 'redNeg'); return this.red.neg(this); } redEq(num) { enforce(BN.isBN(num), 'num', 'bignum'); red(this.red, 'redEq'); return this.red.eq(this, num); } redEqn(num) { enforce(isSMI(num), 'num', 'smi'); red(this.red, 'redEqn'); return this.red.eqn(this, num); } redIsHigh() { red(this.red, 'redIsHigh'); return this.red.isHigh(this); } redIsLow() { red(this.red, 'redIsLow'); return this.red.isLow(this); } redIsOdd() { red(this.red, 'redIsOdd'); return this.red.isOdd(this); } redIsEven() { red(this.red, 'redIsEven'); return this.red.isEven(this); } redLegendre() { red(this.red, 'redLegendre'); return this.red.legendre(this); } redJacobi() { red(this.red, 'redJacobi'); return this.red.jacobi(this); } redKronecker() { red(this.red, 'redKronecker'); return this.red.kronecker(this); } redIInvert() { red(this.red, 'redIInvert'); return this.red.iinvert(this); } redInvert() { red(this.red, 'redInvert'); return this.red.invert(this); } redIFermat() { red(this.red, 'redIFermat'); return this.red.ifermat(this); } redFermat() { red(this.red, 'redFermat'); return this.red.fermat(this); } /* * Internal */ _move(dest) { dest.words = this.words; dest.length = this.length; dest.negative = this.negative; dest.red = this.red; return dest; } _alloc(size) { while (this.words.length < size) this.words.push(0); return this; } _expand(size) { this._alloc(size); while (this.length < size) this.words[this.length++] = 0; return this; } _strip() { while (this.length > 1 && this.words[this.length - 1] === 0) this.length -= 1; return this._normalize(); } _normalize() { assert(this.length > 0); // -0 = 0 if (this.length === 1 && this.words[0] === 0) this.negative = 0; return this; } _check() { // We never have a zero length number. assert(this.length > 0); // Cannot exceed array bounds. assert(this.length <= this.words.length); if (this.length === 1) { // Must be normalized. if (this.words[0] === 0) assert(this.negative === 0); return this; } // Must be stripped. assert(this.words[this.length - 1] !== 0); return this; } _invertp(p) { // Penk's right shift binary EGCD. // // See: The Art of Computer Programming, // Volume 2, Seminumerical Algorithms // Donald E. Knuth // Exercise 4.5.2.39 enforce(BN.isBN(p), 'p', 'bignum'); range(p.sign() > 0, 'invert'); assert(p.isOdd()); if (p.cmpn(1) === 0) throw new RangeError('Not invertible.'); const a = this.clone(); const b = p.clone(); const u = new BN(1); const v = new BN(0); if (a.isNeg() || a.ucmp(b) >= 0) a.imod(b); while (!a.isZero()) { let i = a._makeOdd(); let j = b._makeOdd(); while (i--) { if (u.isOdd()) u._iadd(u, p); u.iushrn(1); } while (j--) { if (v.isOdd()) v._iadd(v, p); v.iushrn(1); } if (a.ucmp(b) >= 0) { a._isub(a, b); if (u.ucmp(v) < 0) { u._isub(v, u); u._isub(p, u); } else { u._isub(u, v); } } else { b._isub(b, a); if (v.ucmp(u) < 0) { v._isub(u, v); v._isub(p, v); } else { v._isub(v, u); } } } if (b.cmpn(1) !== 0) throw new RangeError('Not invertible.'); assert(v.negative === 0); assert(v.ucmp(p) < 0); return v; } _makeOdd() { const shift = this.zeroBits(); if (shift > 0) this.iushrn(shift); return shift; } _factor2(num) { // Find common factor of two. // Expects inputs to be non-zero. if ((this.words[0] | num.words[0]) & 1) return 0; const len = Math.min(this.length, num.length); let r = 0; for (let i = 0; i < len; i++) { const b = zeroBits(this.words[i] | num.words[i]); r += b; if (b !== 26) break; } return r; } _cloneNormal() { return this.red ? this.fromRed() : this.clone(); } _forceRed(ctx) { this.red = ctx; return this; } /* * Helpers */ clone() { const copy = new BN(); copy.words = new Array(this.length); for (let i = 0; i < this.length; i++) copy.words[i] = this.words[i]; copy.length = this.length; copy.negative = this.negative; copy.red = this.red; return copy; } inject(num) { enforce(BN.isBN(num), 'num', 'bignum'); this._alloc(num.length); for (let i = 0; i < num.length; i++) this.words[i] = num.words[i]; this.length = num.length; this.negative = num.negative; this.red = num.red; return this; } set(num, endian) { return this.fromNumber(num, endian); } swap(num) { enforce(BN.isBN(num), 'num', 'bignum'); const x = this; const y = num; [x.words, y.words] = [y.words, x.words]; [x.length, y.length] = [y.length, x.length]; [x.negative, y.negative] = [y.negative, x.negative]; [x.red, y.red] = [y.red, x.red]; return x; } reverse() { const neg = this.negative; this.fromBuffer(this.toBuffer('be'), 'le'); this.negative = neg; return this; } byteLength() { return Math.ceil(this.bitLength() / 8); } bitLength() { const w = this.words[this.length - 1]; const hi = countBits(w); return (this.length - 1) * 26 + hi; } zeroBits() { if (this.isZero()) return 0; if (this.isOdd()) return 0; let r = 0; for (let i = 0; i < this.length; i++) { const b = zeroBits(this.words[i]); r += b; if (b !== 26) break; } return r; } isSafe() { if (this.length <= 2) return true; if (this.length === 3 && this.words[2] === 0x01) return true; return false; } word(pos) { enforce((pos >>> 0) === pos, 'pos', 'uint32'); if (pos >= this.length) return 0; return this.words[pos]; } [custom]() { let prefix = 'BN'; if (this.red) prefix = 'BN-R'; return `<${prefix}: ${this.toString(10)}>`; } /* * Conversion */ toNumber() { let num = this.words[0]; if (this.length === 2) { num += this.words[1] * 0x4000000; } else if (this.length === 3 && this.words[2] === 0x01) { // Note: at this stage it is known that the top bit is set. num += 0x10000000000000 + (this.words[1] * 0x4000000); } else if (this.length > 2) { throw new RangeError('Number can only safely store up to 53 bits.'); } return this.negative !== 0 ? -num : num; } toDouble() { let num = 0; for (let i = this.length - 1; i >= 0; i--) num = (num * 0x4000000) + this.words[i]; return this.negative !== 0 ? -num : num; } valueOf() { return this.toDouble(); } toBigInt() { if (!HAS_BIGINT) throw new Error('BigInt is not supported!'); const s52 = BigInt(52); const s26 = BigInt(26); let i = this.length - 1; let num = BigInt(0); for (; i >= 1; i -= 2) { const hi = this.words[i] * 0x4000000; const lo = this.words[i - 1]; num = (num << s52) | BigInt(hi + lo); } if (i >= 0) num = (num << s26) | BigInt(this.words[0]); return this.negative !== 0 ? -num : num; } toBool() { return !this.isZero(); } toString(base, padding) { base = getBase(base); if (padding == null) padding = 0; if (padding === 0) padding = 1; enforce((base >>> 0) === base, 'base', 'uint32'); enforce((padding >>> 0) === padding, 'padding', 'uint32'); if (base < 2 || base > 36) throw new RangeError('Base ranges between 2 and 36.'); this._check(); if (base === 16) { let out = ''; let off = 0; let carry = 0; for (let i = 0; i < this.length; i++) { const w = this.words[i]; const word = (((w << off) | carry) & 0xffffff).toString(16); carry = (w >>> (24 - off)) & 0xffffff; if (carry !== 0 || i !== this.length - 1) out = zeros[6 - word.length] + word + out; else out = word + out; off += 2; if (off >= 26) { off -= 26; i -= 1; } } if (carry !== 0) out = carry.toString(16) + out; while (out.length % padding !== 0) out = '0' + out; if (this.negative !== 0) out = '-' + out; return out; } const groupSize = groupSizes[base - 1]; const groupBase = groupBases[base - 1]; const c = this.clone(); let out = ''; c.negative = 0; while (!c.isZero()) { const r = c.remrn(groupBase).toString(base); c.iquon(groupBase); if (!c.isZero()) out = zeros[groupSize - r.length] + r + out; else out = r + out; } if (this.isZero()) out = '0'; while (out.length % padding !== 0) out = '0' + out; if (this.negative !== 0) out = '-' + out; return out; } toJSON() { return this.toString(16, 2); } toArray(endian, length) { return this.toArrayLike(Array, endian, length); } toBuffer(endian, length) { return this.toArrayLike(Buffer, endian, length); } toArrayLike(ArrayType, endian, length) { if (endian == null) endian = 'be'; if (length == null) length = 0; enforce(typeof ArrayType === 'function', 'ArrayType', 'function'); enforce(endian === 'be' || endian === 'le', 'endian', 'endianness'); enforce((length >>> 0) === length, 'length', 'uint32'); this._check(); const bytes = this.byteLength(); const size = length || Math.max(1, bytes); if (bytes > size) throw new RangeError('Byte array longer than desired length.'); const res = allocate(ArrayType, size); // See: https://github.com/indutny/bn.js/pull/222 if (endian === 'be') { let pos = res.length - 1; let carry = 0; for (let i = 0; i < this.length; i++) { const shift = (i & 3) << 1; const word = (this.words[i] << shift) | carry; res[pos--] = word & 0xff; if (pos >= 0) res[pos--] = (word >>> 8) & 0xff; if (pos >= 0) res[pos--] = (word >>> 16) & 0xff; if (shift === 6) { if (pos >= 0) res[pos--] = (word >>> 24) & 0xff; carry = 0; } else { carry = word >>> 24; } } if (pos >= 0) { res[pos--] = carry; while (pos >= 0) res[pos--] = 0; carry = 0; } assert(carry === 0); } else { let pos = 0; let carry = 0; for (let i = 0; i < this.length; i++) { const shift = (i & 3) << 1; const word = (this.words[i] << shift) | carry; res[pos++] = word & 0xff; if (pos < res.length) res[pos++] = (word >>> 8) & 0xff; if (pos < res.length) res[pos++] = (word >>> 16) & 0xff; if (shift === 6) { if (pos < res.length) res[pos++] = (word >>> 24) & 0xff; carry = 0; } else { carry = word >>> 24; } } if (pos < res.length) { res[pos++] = carry; while (pos < res.length) res[pos++] = 0; carry = 0; } assert(carry === 0); } return res; } encode(endian, length) { return this.toBuffer(endian, length); } /* * Instantiation */ of(num, endian) { return this.fromNumber(num, endian); } fromNumber(num, endian) { if (endian == null) endian = 'be'; enforce(isInteger(num), 'num', 'integer'); enforce(endian === 'be' || endian === 'le', 'endian', 'endianness'); const neg = (num < 0) | 0; if (neg) num = -num; if (num < 0x4000000) { this.words[0] = num & 0x3ffffff; this.length = 1; } else if (num < 0x10000000000000) { this.words = [ num & 0x3ffffff, (num / 0x4000000) & 0x3ffffff ]; this.length = 2; } else { this.words = [ num & 0x3ffffff, (num / 0x4000000) & 0x3ffffff, 1 ]; this.length = 3; } this.negative = neg; if (endian === 'le') this.reverse(); return this; } fromDouble(num, endian) { if (endian == null) endian = 'be'; enforce(typeof num === 'number', 'num', 'double'); enforce(endian === 'be' || endian === 'le', 'endian', 'endianness'); if (!isFinite(num)) num = 0; const neg = (num <= -1) | 0; if (num < 0) num = -num; num = Math.floor(num); this.words = []; while (num > 0) { const lo = num % 0x4000000; const hi = (num - lo) / 0x4000000; this.words.push(lo); num = hi; } if (this.words.length === 0) this.words.push(0); this.length = this.words.length; this.negative = neg; if (endian === 'le') this.reverse(); return this; } fromBigInt(num, endian) { if (endian == null) endian = 'be'; enforce(typeof num === 'bigint', 'num', 'bigint'); enforce(endian === 'be' || endian === 'le', 'endian', 'endianness'); if (!HAS_BIGINT) throw new Error('BigInt is not supported!'); // You know the implementation has a // problem when strings are twice // as fast as bigints. const start = (num < BigInt(0)) | 0; this._fromHex(num.toString(16), start); this.negative = start; if (endian === 'le') this.reverse(); return this; } fromBool(value) { enforce(typeof value === 'boolean', 'value', 'boolean'); this.words[0] = value | 0; this.length = 1; this.negative = 0; return this; } fromString(str, base, endian) { if (base === 'le' || base === 'be') [base, endian] = [endian, base]; base = getBase(base); if (endian == null) endian = 'be'; enforce(typeof str === 'string', 'string', 'string'); enforce((base >>> 0) === base, 'base', 'uint32'); enforce(endian === 'be' || endian === 'le', 'endian', 'endianness'); if (base < 2 || base > 36) throw new Error('Base ranges between 2 and 36.'); str = str.replace(/\s+/g, ''); let start = 0; if (str.length > 0 && str.charCodeAt(0) === 0x2d) start = 1; if (base === 16) this._fromHex(str, start); else this._fromBase(str, base, start); this.negative = start; this._normalize(); if (endian === 'le') this.reverse(); return this; } _fromHex(str, start) { this.length = Math.max(2, Math.ceil((str.length - start) / 6)); this.words = new Array(this.length); for (let i = 0; i < this.length; i++) this.words[i] = 0; // Scan 24-bit chunks and add them to the number. let off = 0; let i = str.length - 6; let j = 0; for (; i >= start; i -= 6) { const w = parseHex(str, i, i + 6); this.words[j] |= (w << off) & 0x3ffffff; // `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb. this.words[j + 1] |= (w >>> (26 - off)) & 0x3fffff; off += 24; if (off >= 26) { off -= 26; j += 1; } } if (i + 6 !== start) { const w = parseHex(str, start, i + 6); this.words[j] |= (w << off) & 0x3ffffff; this.words[j + 1] |= (w >>> (26 - off)) & 0x3fffff; } return this._strip(); } _fromBase(str, base, start) { // Initialize as zero. this.words[0] = 0; this.length = 1; this.negative = 0; // Find length of limb in base. let limbLen = 0; let limbPow = 1; for (; limbPow <= 0x3ffffff; limbPow *= base) limbLen += 1; limbLen -= 1; limbPow = (limbPow / base) | 0; const total = str.length - start; const mod = total % limbLen; const end = Math.min(total, total - mod) + start; let i = start; for (; i < end; i += limbLen) { const word = parseBase(str, i, i + limbLen, base); this.imuln(limbPow); this._iaddn(word); } if (mod !== 0) { const pow = Math.pow(base, mod); const word = parseBase(str, i, str.length, base); this.imuln(pow); this._iaddn(word); } return this; } fromJSON(json) { if (BN.isBN(json)) { if (json.red) return json.fromRed(); return json.clone(); } if (Array.isArray(json)) { for (const chunk of json) enforce(typeof chunk === 'string', 'chunk', 'string'); json = json.join(''); } return this.fromString(json, 16); } fromBN(num) { return this.inject(num); } fromArray(data, endian) { enforce(Array.isArray(data), 'data', 'array'); return this.fromArrayLike(data, endian); } fromBuffer(data, endian) { enforce(Buffer.isBuffer(data), 'data', 'buffer'); return this.fromArrayLike(data, endian); } fromArrayLike(data, endian) { if (endian == null) endian = 'be'; enforce(data && (data.length >>> 0) === data.length, 'data', 'array-like'); enforce(endian === 'be' || endian === 'le', 'endian', 'endianness'); if (data.length === 0) { this.words[0] = 0; this.length = 1; this.negative = 0; return this; } this.length = Math.max(2, Math.ceil(data.length / 3)); this.words = new Array(this.length); this.negative = 0; for (let i = 0; i < this.length; i++) this.words[i] = 0; const left = data.length % 3; let off = 0; let j = 0; let w = 0; if (endian === 'be') { for (let i = data.length - 1; i >= 2; i -= 3) { const w = data[i] | (data[i - 1] << 8) | (data[i - 2] << 16); this.words[j] |= (w << off) & 0x3ffffff; this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; off += 24; if (off >= 26) { off -= 26; j += 1; } } switch (left) { case 2: w = data[1] | (data[0] << 8); break; case 1: w = data[0]; break; } } else { const len = data.length - left; for (let i = 0; i < len; i += 3) { const w = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16); this.words[j] |= (w << off) & 0x3ffffff; this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; off += 24; if (off >= 26) { off -= 26; j += 1; } } switch (left) { case 2: w = data[len] | (data[len + 1] << 8); break; case 1: w = data[len]; break; } } if (left > 0) { this.words[j] |= (w << off) & 0x3ffffff; this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; } return this._strip(); } decode(data, endian) { return this.fromBuffer(data, endian); } from(num, base, endian) { if (num == null) return this; if (base === 'le' || base === 'be') [base, endian] = [endian, base]; if (typeof num === 'number') return this.fromNumber(num, endian); if (typeof num === 'bigint') return this.fromBigInt(num, endian); if (typeof num === 'string') return this.fromString(num, base, endian); if (typeof num === 'object') { if (BN.isBN(num)) return this.fromBN(num, endian); if ((num.length >>> 0) === num.length) return this.fromArrayLike(num, endian); } if (typeof num === 'boolean') return this.fromBool(num); throw new TypeError('Non-numeric object passed to BN.'); } /* * Static Methods */ static min(...args) { let min = null; for (const num of args) { enforce(BN.isBN(num), 'num', 'bignum'); if (!min || num.cmp(min) < 0) min = num; } return min || new BN(0); } static max(...args) { let max = null; for (const num of args) { enforce(BN.isBN(num), 'num', 'bignum'); if (!max || num.cmp(max) > 0) max = num; } return max || new BN(0); } static cmp(a, b) { enforce(BN.isBN(a), 'a', 'bignum'); return a.cmp(b); } static ucmp(a, b) { enforce(BN.isBN(a), 'a', 'bignum'); return a.ucmp(b); } static red(num) { return new Red(num); } static barrett(num) { return new Barrett(num); } static mont(num) { return new Mont(num); } static _prime(name) { if (primes[name]) return primes[name]; let prime; if (name === 'p192') prime = new P192(); else if (name === 'p224') prime = new P224(); else if (name === 'p521') prime = new P521(); else if (name === 'k256') prime = new K256(); else if (name === 'p251') prime = new P251(); else if (name === 'p25519') prime = new P25519(); else if (name === 'p448') prime = new P448(); else throw new Error(`Unknown prime: "${name}".`); primes[name] = prime; return prime; } static prime(name) { return BN._prime(name).p.clone(); } static pow(num, exp) { if (num === 2) return BN.shift(1, exp); return new BN().fromNumber(num).pown(exp); } static shift(num, bits) { if (num === 1) return new BN(0).usetn(bits, 1); return new BN().fromNumber(num).ishln(bits); } static mask(bits) { return BN.shift(1, bits).isubn(1); } static randomBits(rng, bits) { enforce(rng != null, 'rng', 'rng'); enforce((bits >>> 0) === bits, 'bits', 'uint32'); if (typeof rng === 'object') { enforce(typeof rng.randomBytes === 'function', 'rng', 'rng'); const size = (bits + 7) >>> 3; const total = size * 8; const bytes = rng.randomBytes(size); enforce(Buffer.isBuffer(bytes), 'bytes', 'buffer'); if (bytes.length !== size) throw new RangeError('Invalid number of bytes returned from RNG.'); const num = BN.fromBuffer(bytes); if (total > bits) num.iushrn(total - bits); return num; } enforce(typeof rng === 'function', 'rng', 'rng'); const num = rng(bits); enforce(BN.isBN(num), 'num', 'bignum'); range(num.negative === 0, 'RNG'); nonred(!num.red, 'RNG'); if (num.bitLength() > bits) throw new RangeError('Invalid number of bits returned from RNG.'); return num; } static random(rng, min, max) { min = BN.cast(min, 16); max = BN.cast(max, 16); if (min.cmp(max) > 0) throw new RangeError('Minimum cannot be greater than maximum.'); const space = max.sub(min).iabs(); const bits = space.bitLength(); if (bits === 0) return min.clone(); for (;;) { const num = BN.randomBits(rng, bits); // Maximum is _exclusive_! if (num.cmp(space) >= 0) continue; // Minimum is _inclusive_! num.iadd(min); return num; } } static of(num, endian) { return new BN().of(num, endian); } static fromNumber(num, endian) { return new BN().fromNumber(num, endian); } static fromDouble(num, endian) { return new BN().fromDouble(num, endian); } static fromBigInt(num, endian) { return new BN().fromBigInt(num, endian); } static fromBool(value) { return new BN().fromBool(value); } static fromString(str, base, endian) { return new BN().fromString(str, base, endian); } static fromJSON(json) { return new BN().fromJSON(json); } static fromBN(num) { return new BN().fromBN(num); } static fromArray(data, endian) { return new BN().fromArray(data, endian); } static fromBuffer(data, endian) { return new BN().fromBuffer(data, endian); } static fromArrayLike(data, endian) { return new BN().fromArrayLike(data, endian); } static decode(data, endian) { return new BN().decode(data, endian); } static from(num, base, endian) { return new BN().from(num, base, endian); } static cast(num, base, endian) { if (BN.isBN(num)) return num; return new BN(num, base, endian); } static isBN(obj) { return obj instanceof BN; } } /* * Static */ BN.BN = BN; BN.wordSize = 26; BN.native = 0; /** * Prime */ class Prime { constructor(name, p) { // P = 2^N - K this.name = name; this.p = new BN(p, 16); this.n = this.p.bitLength(); this.k = BN.shift(1, this.n).isub(this.p); this.lo = this.p.clone(); this.one = this.p.clone(); } ireduce(num) { // Assumes that `num` is less than `P^2`: // num = HI * (2^N - K) + HI * K + LO = HI * K + LO (mod P) const neg = num.negative !== 0; // Track bits. let bits = num.bitLength(); // Must be less than P^2. assert(bits <= this.n * 2); // Ensure positive. num.negative = 0; // Reduce. while (bits > this.n) { // lo = num & ((1 << n) - 1) // num = num >> n this.split(num, this.lo); // num = num * K this.imulK(num); // num = num + lo num._iadd(num, this.lo); // bits = bitlen(num) bits = num.bitLength(); } // Final reduction. const cmp = bits < this.n ? -1 : num.ucmp(this.p); if (cmp === 0) { num.words[0] = 0; num.length = 1; } else if (cmp > 0) { num._isub(num, this.p); } else { // Note: we shouldn't need to strip here. } // Adjust sign. if (neg && !num.isZero()) num._isub(this.p, num); return num; } split(input, out) { input._split(this.n, out); } imulK(num) { return num.imul(this.k); } pm2(x1) { // Exponent: p - 2 throw new Error('Not implemented.'); } fermat(x) { return this.pm2(x); } } /** * Prime (3 mod 4) */ class Prime34 extends Prime { constructor(name, p) { super(name, p); } pm3d4(x1) { // Exponent: (p - 3) / 4 throw new Error('Not implemented.'); } pp1d4(x1) { // Exponent: (p + 1) / 4 throw new Error('Not implemented.'); } sqrt(x) { // r = x^((p + 1) / 4) mod p const {red} = x; const r = this.pp1d4(x); if (!red.sqr(r).eq(x)) throw new SquareRootError(r); return r; } divsqrt(u, v) { // x = u^3 * v * (u^5 * v^3)^((p - 3) / 4) mod p const {red} = u; const u2 = red.sqr(u); const u3 = red.mul(u2, u); const u5 = red.mul(u3, u2); const v3 = red.mul(red.sqr(v), v); const p = this.pm3d4(red.mul(u5, v3)); const x = red.mul(red.mul(u3, v), p); const c = red.mul(v, red.sqr(x)); if (c.eq(u)) return x; throw new SquareRootError(x); } } /** * Prime (5 mod 8) */ class Prime58 extends Prime { constructor(name, p, sm1) { super(name, p); this.sm1 = new BN(sm1, 16); } pm5d8(x1) { // Exponent: (p - 5) / 8 throw new Error('Not implemented.'); } pp3d8(x1) { // Exponent: (p + 3) / 8 throw new Error('Not implemented.'); } sqrt(x) { // r = x^((p + 3) / 8) mod p const {red} = x; const sm1 = this.sm1._forceRed(red); const r = this.pp3d8(x); if (red.sqr(r).eq(x)) return r; const c = red.mul(r, sm1); if (red.sqr(c).eq(x)) return c; throw new SquareRootError(r); } divsqrt(u, v) { // x = u * v^3 * (u * v^7)^((p - 5) / 8) mod p const {red} = u; const sm1 = this.sm1._forceRed(red); const v3 = red.mul(red.sqr(v), v); const v7 = red.mul(red.sqr(v3), v); const p = this.pm5d8(red.mul(u, v7)); const x = red.mul(red.mul(u, v3), p); const c = red.mul(v, red.sqr(x)); if (c.eq(u)) return x; const mc = red.ineg(c); if (mc.eq(u)) return red.mul(x, sm1); if (mc.eq(red.mul(u, sm1))) throw new SquareRootError(red.mul(x, sm1)); throw new SquareRootError(x); } } /** * Prime (1 mod 16) */ class Prime116 extends Prime { constructor(name, p, g) { super(name, p); this.g = new BN(g, 16); this.z = this.p.subn(1).zeroBits(); } powS(x1) { // Exponent: (p - 1) / 2^k throw new Error('Not implemented.'); } powE(x1) { // Exponent: (s + 1) / 2 throw new Error('Not implemented.'); } sqrt(x) { // Tonelli-Shanks (variable time). // // Constants: // // k = factors of 2 for (p - 1) // s = (p - 1) / 2^k // e = (s + 1) / 2 // n = first non-square in F(p) // // Algorithm: // // g = n^s mod p // y = x^e mod p // b = x^s mod p // // loop: // t = b // m = 0 // // while t != 1: // t = t^2 mod p // m += 1 // // if m == 0: // break // // if m >= k: // fail // // t = g^(2^(k - m - 1)) mod p // g = t^2 mod p // y = y * t mod p // b = b * g mod p // k = m // // return y // const {red} = x; switch (red.jacobi(x)) { case -1: throw new SquareRootError(x); case 0: return x.clone(); case 1: break; } let g = this.g._forceRed(red); let y = this.powE(x); let b = this.powS(x); let k = this.z; for (;;) { let t = b; let m = 0; while (t.cmpn(1) !== 0 && m < k) { t = red.sqr(t); m += 1; } if (m === 0) break; assert(m < k); t = red.sqrn(g, k - m - 1); g = red.sqr(t); y = red.mul(y, t); b = red.mul(b, g); k = m; } return y; } divsqrt(u, v) { const {red} = u; if (v.isZero()) throw new SquareRootError(v); return this.sqrt(red.div(u, v)); } } /** * P192 */ class P192 extends Prime34 { constructor() { // 2^192 - 2^64 - 1 (= 3 mod 4) super('p192', 'ffffffff ffffffff ffffffff fffffffe' + 'ffffffff ffffffff'); } imulK(num) { // K = 0x10000000000000001 // K = 2^64 + 1 const one = this.one.inject(num); return num.iushln(64)._iadd(num, one); } core(x1) { // Exponent: (p - 3) / 4 // Bits: 127x1 1x0 62x1 const {red} = x1; const x2 = red.sqrnmul(x1, 1, x1); const x3 = red.sqrnmul(x2, 1, x1); const x6 = red.sqrnmul(x3, 3, x3); const x12 = red.sqrnmul(x6, 6, x6); const x24 = red.sqrnmul(x12, 12, x12); const x30 = red.sqrnmul(x24, 6, x6); const x31 = red.sqrnmul(x30, 1, x1); const x62 = red.sqrnmul(x31, 31, x31); const x124 = red.sqrnmul(x62, 62, x62); const x127 = red.sqrnmul(x124, 3, x3); const r0 = red.sqrn(x127, 1); const r1 = red.sqrnmul(r0, 62, x62); return r1; } pm3d4(x1) { // Exponent: (p - 3) / 4 // Bits: 127x1 1x0 62x1 return this.core(x1); } pm2(x1) { // Exponent: p - 2 // Bits: 127x1 1x0 62x1 1x0 1x1 const {red} = x1; const r0 = this.core(x1); const r1 = red.sqrn(r0, 1); const r2 = red.sqrnmul(r1, 1, x1); return r2; } pp1d4(x1) { // Exponent: (p + 1) / 4 // Bits: 128x1 62x0 const {red} = x1; const x2 = red.sqrnmul(x1, 1, x1); const x4 = red.sqrnmul(x2, 2, x2); const x8 = red.sqrnmul(x4, 4, x4); const x16 = red.sqrnmul(x8, 8, x8); const x32 = red.sqrnmul(x16, 16, x16); const x64 = red.sqrnmul(x32, 32, x32); const x128 = red.sqrnmul(x64, 64, x64); const r0 = red.sqrn(x128, 62); return r0; } } /** * P224 */ class P224 extends Prime116 { constructor() { // 2^224 - 2^96 + 1 (1 mod 16) super('p224', 'ffffffff ffffffff ffffffff ffffffff' + '00000000 00000000 00000001', '6a0fec67 8598a792 0c55b2d4 0b2d6ffb' + 'bea3d8ce f3fb3632 dc691b74'); } imulK(num) { // K = 0xffffffffffffffffffffffff // K = 2^96 - 1 const one = this.one.inject(num); return num.iushln(96)._isub(num, one); } powS(x1) { // Exponent: 2^128 - 1 // Bits: 128x1 const {red} = x1; const x2 = red.sqrnmul(x1, 1, x1); const x4 = red.sqrnmul(x2, 2, x2); const x8 = red.sqrnmul(x4, 4, x4); const x16 = red.sqrnmul(x8, 8, x8); const x32 = red.sqrnmul(x16, 16, x16); const x64 = red.sqrnmul(x32, 32, x32); const x128 = red.sqrnmul(x64, 64, x64); return x128; } powE(x1) { // Exponent: 2^127 // Bits: 1x1 127x0 const {red} = x1; const r0 = red.sqrn(x1, 127); return r0; } pm2(x1) { // Exponent: p - 2 // Bits: 127x1 1x0 96x1 const {red} = x1; const x2 = red.sqrnmul(x1, 1, x1); const x3 = red.sqrnmul(x2, 1, x1); const x6 = red.sqrnmul(x3, 3, x3); const x12 = red.sqrnmul(x6, 6, x6); const x24 = red.sqrnmul(x12, 12, x12); const x48 = red.sqrnmul(x24, 24, x24); const x96 = red.sqrnmul(x48, 48, x48); const x120 = red.sqrnmul(x96, 24, x24); const x126 = red.sqrnmul(x120, 6, x6); const x127 = red.sqrnmul(x126, 1, x1); const r0 = red.sqrn(x127, 1); const r1 = red.sqrnmul(r0, 96, x96); return r1; } } /** * P521 */ class P521 extends Prime34 { constructor() { // 2^521 - 1 (= 3 mod 4) super('p521', '000001ff ffffffff ffffffff ffffffff' + 'ffffffff ffffffff ffffffff ffffffff' + 'ffffffff ffffffff ffffffff ffffffff' + 'ffffffff ffffffff ffffffff ffffffff' + 'ffffffff'); } imulK(num) { // K = 0x01 return num; } core(x1) { // Exponent: 2^519 - 1 // Bits: 519x1 const {red} = x1; const x2 = red.sqrnmul(x1, 1, x1); const x3 = red.sqrnmul(x2, 1, x1); const x6 = red.sqrnmul(x3, 3, x3); const x7 = red.sqrnmul(x6, 1, x1); const x8 = red.sqrnmul(x7, 1, x1); const x16 = red.sqrnmul(x8, 8, x8); const x32 = red.sqrnmul(x16, 16, x16); const x64 = red.sqrnmul(x32, 32, x32); const x128 = red.sqrnmul(x64, 64, x64); const x256 = red.sqrnmul(x128, 128, x128); const x512 = red.sqrnmul(x256, 256, x256); const x519 = red.sqrnmul(x512, 7, x7); return x519; } pm3d4(x1) { // Exponent: 2^519 - 1 // Bits: 519x1 return this.core(x1); } pm2(x1) { // Exponent: p - 2 // Bits: 519x1 1x0 1x1 const {red} = x1; const r0 = this.core(x1); const r1 = red.sqrn(r0, 1); const r2 = red.sqrnmul(r1, 1, x1); return r2; } pp1d4(x1) { // Exponent: (p + 1) / 4 // Bits: 1x1 519x0 const {red} = x1; const r0 = red.sqrn(x1, 519); return r0; } } /** * K256 */ class K256 extends Prime34 { constructor() { // 2^256 - 2^32 - 977 (= 3 mod 4) super('k256', 'ffffffff ffffffff ffffffff ffffffff' + 'ffffffff ffffffff fffffffe fffffc2f'); } split(input, output) { // 256 = 9 * 26 + 22 const mask = 0x3fffff; const len = Math.min(input.length, 9); output._alloc(len + 1); for (let i = 0; i < len; i++) output.words[i] = input.words[i]; output.length = len; if (input.length <= 9) { output._strip(); input.words[0] = 0; input.length = 1; return; } // Shift by 9 limbs. let prev = input.words[9]; let i = 10; output.words[output.length++] = prev & mask; output._strip(); for (; i < input.length; i++) { const next = input.words[i] | 0; input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); prev = next; } prev >>>= 22; input.words[i - 10] = prev; if (prev === 0 && input.length > 10) input.length -= 10; else input.length -= 9; input._strip(); // Unsure if we need this. } imulK(num) { // K = 0x1000003d1 = [0x40, 0x3d1] // K = 2^32 + 977 num._expand(num.length + 2); // Bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 let lo = 0; for (let i = 0; i < num.length; i++) { const w = num.words[i]; lo += w * 0x3d1; num.words[i] = lo & 0x3ffffff; lo = w * 0x40 + Math.floor(lo / 0x4000000); } // Fast length reduction. if (num.words[num.length - 1] === 0) { num.length -= 1; if (num.words[num.length - 1] === 0) num.length -= 1; } // Note: we shouldn't need to strip here. return num; } core(x1, x2) { // Exponent: (p - 47) / 64 // Bits: 223x1 1x0 22x1 4x0 const {red} = x1; const x3 = red.sqrnmul(x2, 1, x1); const x6 = red.sqrnmul(x3, 3, x3); const x9 = red.sqrnmul(x6, 3, x3); const x11 = red.sqrnmul(x9, 2, x2); const x22 = red.sqrnmul(x11, 11, x11); const x44 = red.sqrnmul(x22, 22, x22); const x88 = red.sqrnmul(x44, 44, x44); const x176 = red.sqrnmul(x88, 88, x88); const x220 = red.sqrnmul(x176, 44, x44); const x223 = red.sqrnmul(x220, 3, x3); const r0 = red.sqrn(x223, 1); const r1 = red.sqrnmul(r0, 22, x22); const r2 = red.sqrn(r1, 4); return r2; } pm3d4(x1) { // Exponent: (p - 3) / 4 // Bits: 223x1 1x0 22x1 4x0 1x1 1x0 2x1 const {red} = x1; const x2 = red.sqrnmul(x1, 1, x1); const r2 = this.core(x1, x2); const r3 = red.sqrnmul(r2, 1, x1); const r4 = red.sqrn(r3, 1); const r5 = red.sqrnmul(r4, 2, x2); return r5; } pm2(x1) { // Exponent: p - 2 // Bits: 223x1 1x0 22x1 4x0 1x1 1x0 2x1 1x0 1x1 const {red} = x1; const x2 = red.sqrnmul(x1, 1, x1); const r2 = this.core(x1, x2); const r3 = red.sqrnmul(r2, 1, x1); const r4 = red.sqrn(r3, 1); const r5 = red.sqrnmul(r4, 2, x2); const r6 = red.sqrn(r5, 1); const r7 = red.sqrnmul(r6, 1, x1); return r7; } pp1d4(x1) { // Exponent: (p + 1) / 4 // Bits: 223x1 1x0 22x1 4x0 2x1 2x0 const {red} = x1; const x2 = red.sqrnmul(x1, 1, x1); const r2 = this.core(x1, x2); const r3 = red.sqrnmul(r2, 2, x2); const r4 = red.sqrn(r3, 2); return r4; } } /** * P251 */ class P251 extends Prime34 { constructor() { // 2^251 - 9 super('p251', '07ffffff ffffffff ffffffff ffffffff' + 'ffffffff ffffffff ffffffff fffffff7'); } imulK(num) { // K = 0x09 if (num.isZero()) return num; let carry = 0; for (let i = 0; i < num.length; i++) { const w = num.words[i] * 0x09 + carry; carry = w >>> 26; num.words[i] = w & 0x3ffffff; } if (carry !== 0) { num._alloc(num.length + 1); num.words[num.length++] = carry; } // Note: we shouldn't need to strip here. return num; } core(x1) { // Exponent: 2^247 - 1 // Bits: 247x1 const {red} = x1; const x2 = red.sqrnmul(x1, 1, x1); const x3 = red.sqrnmul(x2, 1, x1); const x6 = red.sqrnmul(x3, 3, x3); const x12 = red.sqrnmul(x6, 6, x6); const x24 = red.sqrnmul(x12, 12, x12); const x48 = red.sqrnmul(x24, 24, x24); const x96 = red.sqrnmul(x48, 48, x48); const x192 = red.sqrnmul(x96, 96, x96); const x240 = red.sqrnmul(x192, 48, x48); const x246 = red.sqrnmul(x240, 6, x6); const x247 = red.sqrnmul(x246, 1, x1); return x247; } pm3d4(x1) { // Exponent: (p - 3) / 4 // Bits: 247x1 1x0 1x1 const {red} = x1; const r0 = this.core(x1); const r1 = red.sqrn(r0, 1); const r2 = red.sqrnmul(r1, 1, x1); return r2; } pm2(x1) { // Exponent: p - 2 // Bits: 247x1 1x0 1x1 1x0 1x1 const {red} = x1; const r0 = this.core(x1); const r1 = red.sqrn(r0, 1); const r2 = red.sqrnmul(r1, 1, x1); const r3 = red.sqrn(r2, 1); const r4 = red.sqrnmul(r3, 1, x1); return r4; } pp1d4(x1) { // Exponent: (p + 1) / 4 // Bits: 248x1 1x0 const {red} = x1; const r0 = this.core(x1); const r1 = red.sqrnmul(r0, 1, x1); const r2 = red.sqrn(r1, 1); return r2; } } /** * P25519 */ class P25519 extends Prime58 { constructor() { // 2^255 - 19 (= 5 mod 8) super('p25519', '7fffffff ffffffff ffffffff ffffffff' + 'ffffffff ffffffff ffffffff ffffffed', '2b832480 4fc1df0b 2b4d0099 3dfbd7a7' + '2f431806 ad2fe478 c4ee1b27 4a0ea0b0'); } imulK(num) { // K = 0x13 let carry = 0; for (let i = 0; i < num.length; i++) { const w = num.words[i] * 0x13 + carry; carry = w >>> 26; num.words[i] = w & 0x3ffffff; } if (carry !== 0) { num._alloc(num.length + 1); num.words[num.length++] = carry; } // Note: we shouldn't need to strip here. return num; } core(x1, x2) { // Exponent: 2^250 - 1 // Bits: 250x1 const {red} = x1; const x4 = red.sqrnmul(x2, 2, x2); const x5 = red.sqrnmul(x4, 1, x1); const x10 = red.sqrnmul(x5, 5, x5); const x20 = red.sqrnmul(x10, 10, x10); const x40 = red.sqrnmul(x20, 20, x20); const x50 = red.sqrnmul(x40, 10, x10); const x100 = red.sqrnmul(x50, 50, x50); const x200 = red.sqrnmul(x100, 100, x100); const x250 = red.sqrnmul(x200, 50, x50); return x250; } pm5d8(x1) { // Exponent: (p - 5) / 8 // Bits: 250x1 1x0 1x1 const {red} = x1; const x2 = red.sqrnmul(x1, 1, x1); const r0 = this.core(x1, x2); const r1 = red.sqrn(r0, 1); const r2 = red.sqrnmul(r1, 1, x1); return r2; } pm2(x1) { // Exponent: p - 2 // Bits: 250x1 1x0 1x1 1x0 2x1 const {red} = x1; const x2 = red.sqrnmul(x1, 1, x1); const r0 = this.core(x1, x2); const r1 = red.sqrn(r0, 1); const r2 = red.sqrnmul(r1, 1, x1); const r3 = red.sqrn(r2, 1); const r4 = red.sqrnmul(r3, 2, x2); return r4; } pp3d8(x1) { // Exponent: (p + 3) / 8 // Bits: 251x1 1x0 const {red} = x1; const x2 = red.sqrnmul(x1, 1, x1); const r0 = this.core(x1, x2); const r1 = red.sqrnmul(r0, 1, x1); const r2 = red.sqrn(r1, 1); return r2; } } /** * P448 */ class P448 extends Prime34 { constructor() { // 2^448 - 2^224 - 1 (= 3 mod 4) super('p448', 'ffffffff ffffffff ffffffff ffffffff' + 'ffffffff ffffffff fffffffe ffffffff' + 'ffffffff ffffffff ffffffff ffffffff' + 'ffffffff ffffffff'); } imulK(num) { // K = 0x100000000000000000000000000000000000000000000000000000001 // K = 2^224 + 1 const one = this.one.inject(num); return num.iushln(224)._iadd(num, one); } core(x1, x2) { // Exponent: 2^222 - 1 // Bits: 222x1 const {red} = x1; const x3 = red.sqrnmul(x2, 1, x1); const x6 = red.sqrnmul(x3, 3, x3); const x9 = red.sqrnmul(x6, 3, x3); const x11 = red.sqrnmul(x9, 2, x2); const x22 = red.sqrnmul(x11, 11, x11); const x44 = red.sqrnmul(x22, 22, x22); const x88 = red.sqrnmul(x44, 44, x44); const x176 = red.sqrnmul(x88, 88, x88); const x220 = red.sqrnmul(x176, 44, x44); const x222 = red.sqrnmul(x220, 2, x2); return x222; } pm3d4(x1) { // Exponent: (p - 3) / 4 // Bits: 223x1 1x0 222x1 const {red} = x1; const x2 = red.sqrnmul(x1, 1, x1); const x222 = this.core(x1, x2); const r0 = red.sqrnmul(x222, 1, x1); const r1 = red.sqrn(r0, 1); const r2 = red.sqrnmul(r1, 222, x222); return r2; } pm2(x1) { // Exponent: p - 2 // Bits: 223x1 1x0 222x1 1x0 1x1 const {red} = x1; const r0 = this.pm3d4(x1); const r1 = red.sqrn(r0, 1); const r2 = red.sqrnmul(r1, 1, x1); return r2; } pp1d4(x1) { // Exponent: (p + 1) / 4 // Bits: 224x1 222x0 const {red} = x1; const x2 = red.sqrnmul(x1, 1, x1); const r0 = this.core(x1, x2); const r1 = red.sqrnmul(r0, 2, x2); const r2 = red.sqrn(r1, 222); return r2; } } /** * Reduction Engine */ class Red { constructor(m) { let prime = null; if (typeof m === 'string') { prime = BN._prime(m); m = prime.p; } enforce(BN.isBN(m), 'm', 'bignum'); nonred(!m.red, 'reduction'); range(m.sign() > 0, 'reduction'); this.m = m; this.prime = prime; this.mb = null; this.sm1 = null; } _verify1(a) { range(a.negative === 0, 'red'); red(a.red != null, 'red'); } _verify2(a, b) { range((a.negative | b.negative) === 0, 'red'); red(a.red != null && a.red === b.red, 'red'); } get mont() { return false; } precompute() { // Precompute `sqrt(-1)` for primes congruent to 5 mod 8. if (this.sm1 === null && this.m.andln(7) === 5) { if (this.prime) { this.sm1 = this.prime.sm1.clone()._forceRed(this); } else { const x = new BN(2).toRed(this); const e = this.m.subn(1).iushrn(2); // sqrt(-1) = 2^((p - 1) / 4) mod p this.sm1 = this.pow(x, e); } } return this; } convertTo(num) { const res = num.mod(this.m); res.red = this; return res; } convertFrom(num) { const res = num.clone(); res.red = null; return res; } intTo(a) { return a; } intFrom(a) { return a; } imod(a) { if (this.prime) return this.prime.ireduce(a)._forceRed(this); return a.imod(this.m)._forceRed(this); } iadd(a, b) { this._verify2(a, b); a._iadd(a, b); if (a.ucmp(this.m) >= 0) a._isub(a, this.m); return a; } add(a, b) { if (a.length < b.length) return this.iadd(b.clone(), a); return this.iadd(a.clone(), b); } iaddn(a, num) { this._verify1(a); if (num < 0) return this.isubn(a, -num); if (this.m.length === 1) num %= this.m.words[0]; a._iaddn(num); if (a.ucmp(this.m) >= 0) a._isub(a, this.m); return a; } addn(a, num) { return this.iaddn(a.clone(), num); } isub(a, b) { this._verify2(a, b); // 0: a - a mod m == 0 // -1: a - b mod m == m - (b - a) // +1: a - b mod m == a - b const cmp = a.ucmp(b); if (cmp === 0) { a.words[0] = 0; a.length = 1; return a; } if (cmp < 0) { a._isub(b, a); a._isub(this.m, a); } else { a._isub(a, b); } return a; } sub(a, b) { return this.isub(a.clone(), b); } isubn(a, num) { this._verify1(a); if (num < 0) return this.iaddn(a, -num); if (this.m.length === 1) num %= this.m.words[0]; // <: a - b mod m == m - (b - a) // >=: a - b mod m == a - b if (a.length === 1 && a.words[0] < num) { a.words[0] = num - a.words[0]; a._isub(this.m, a); } else { a._isubn(num); } return a; } subn(a, num) { return this.isubn(a.clone(), num); } imul(a, b) { this._verify2(a, b); return this.imod(a.imul(b)); } mul(a, b) { this._verify2(a, b); return this.imod(a.mul(b)); } imuln(a, num) { this._verify1(a); if (a.isZero()) return a; if (num === 0) { a.words[0] = 0; a.length = 1; return a; } const neg = num < 0; if (neg) num = -num; if (this.m.length === 1) num %= this.m.words[0]; a.imuln(num); if (num <= 16) { // Quick reduction. while (a.ucmp(this.m) >= 0) a._isub(a, this.m); } else { this.imod(a); } if (neg) this.ineg(a); return a; } muln(a, num) { return this.imuln(a.clone(), num); } idiv(a, b) { return this.div(a, b)._move(a); } div(a, b) { return this.mul(a, this.invert(b)); } idivn(a, num) { return this.divn(a, num)._move(a); } divn(a, num) { return this.div(a, this.convertTo(new BN(num))); } ipow(a, num) { return this.pow(a, num)._move(a); } pow(a, num) { this._verify1(a); if (num.isNeg()) a = this.invert(a); // Small exponent. if (num.length === 1) return this.pown(a, num.words[0]); // Call out to BigInt. if (HAS_BIGINT && !this.prime) return this.powInt(a, num); // Otherwise, a BN implementation. return this.powNum(a, num); } powNum(a, num) { // Sliding window (odd multiples only). const one = new BN(1).toRed(this); const wnd = new Array(WND_SIZE); const a2 = this.sqr(a); wnd[0] = a; for (let i = 1; i < WND_SIZE; i++) wnd[i] = this.mul(wnd[i - 1], a2); let i = num.bitLength(); let r = one; while (i >= WND_WIDTH) { let width = WND_WIDTH; let bits = num.bits(i - width, width); if (bits < WND_SIZE) { r = this.sqr(r); i -= 1; continue; } while ((bits & 1) === 0) { width -= 1; bits >>= 1; } if (r === one) { r = wnd[bits >> 1].clone(); } else { r = this.sqrn(r, width); r = this.mul(r, wnd[bits >> 1]); } i -= width; } if (i > 0) { const bits = num.bits(0, i); while (i--) { r = this.sqr(r); if ((bits >> i) & 1) r = this.mul(r, a); } } return r; } powInt(a, num) { if (this.mb === null) this.mb = this.m.toBigInt(); const x = this.intFrom(a.toBigInt()); const y = powInt(x, num, this.mb); const z = this.intTo(y); return BN.fromBigInt(z)._forceRed(this); } sqrn(a, n) { while (n--) a = this.sqr(a); return a; } sqrnmul(a, n, b) { return this.mul(this.sqrn(a, n), b); } ipown(a, num) { return this.pown(a, num)._move(a); } pown(a, num) { this._verify1(a); if (num < 0) { a = this.invert(a); num = -num; } if (num === 0) return new BN(1).toRed(this); if (num === 1) return a.clone(); const bits = countBits(num); let r = a; for (let i = bits - 2; i >= 0; i--) { r = this.sqr(r); if ((num >> i) & 1) r = this.mul(r, a); } return r; } isqr(a) { return this.imul(a, a); } sqr(a) { return this.mul(a, a); } isqrt(x) { return this.sqrt(x)._move(x); } sqrt(x) { this._verify1(x); // Optimized square root chain. if (this.prime) return this.prime.sqrt(x); // Fast case (p = 3 mod 4). if (this.m.andln(3) === 3) return this.sqrt3mod4(x); // Fast case (p = 5 mod 8). if (this.m.andln(7) === 5) { if (this.sm1 != null) return this.sqrt5mod8sm1(x); return this.sqrt5mod8(x); } // Slow case (Tonelli-Shanks). return this.sqrt0(x); } sqrt3mod4(x) { const e = this.m.addn(1).iushrn(2); // (p + 1) / 4 const b = this.pow(x, e); if (!this.sqr(b).eq(x)) throw new SquareRootError(b); return b; } sqrt5mod8(x) { // Atkin's Algorithm. const one = new BN(1).toRed(this); const e = this.m.ushrn(3); // (p - 5) / 8 const x2 = this.add(x, x); const alpha = this.pow(x2, e); const beta = this.mul(x2, this.sqr(alpha)); const b = this.mul(this.mul(alpha, x), this.isub(beta, one)); if (!this.sqr(b).eq(x)) throw new SquareRootError(b); return b; } sqrt5mod8sm1(x) { const e = this.m.addn(3).iushrn(3); // (p + 3) / 8 const b = this.pow(x, e); if (this.sqr(b).eq(x)) return b; const c = this.mul(b, this.sm1); if (this.sqr(c).eq(x)) return c; throw new SquareRootError(b); } sqrt0(x) { if (this.m.cmpn(1) === 0 || !this.m.isOdd()) throw new Error('Invalid prime.'); switch (this.jacobi(x)) { case -1: throw new SquareRootError(x); case 0: return x.clone(); case 1: break; } const one = new BN(1).toRed(this); const s = this.m.subn(1); const e = s._makeOdd(); const n = new BN(2).toRed(this); while (this.jacobi(n) !== -1) this.iadd(n, one); let g = this.pow(n, s); let b = this.pow(x, s); let y = this.pow(x, s.iaddn(1).iushrn(1)); let k = e; for (;;) { let t = b; let m = 0; while (!t.eq(one) && m < k) { t = this.sqr(t); m += 1; } if (m === 0) break; assert(m < k); t = this.sqrn(g, k - m - 1); g = this.sqr(t); y = this.mul(y, t); b = this.mul(b, g); k = m; } return y; } idivsqrt(u, v) { return this.divsqrt(u, v)._move(u); } divsqrt(u, v) { this._verify2(u, v); // u = 0, v = 0 if (u.isZero() && v.isZero()) throw new SquareRootError(v); // Optimized inverse square root chain. if (this.prime) return this.prime.divsqrt(u, v); // p = 3 mod 4 if (this.m.andln(3) === 3) return this.divsqrt3mod4(u, v); // p = 5 mod 8 if (this.sm1 != null && this.m.andln(7) === 5) return this.divsqrt5mod8(u, v); // v = 0 if (v.isZero()) throw new SquareRootError(v); return this.sqrt(this.div(u, v)); } divsqrt3mod4(u, v) { // x = u^3 * v * (u^5 * v^3)^((p - 3) / 4) mod p const e = this.m.subn(3).iushrn(2); const u2 = this.sqr(u); const u3 = this.mul(u2, u); const u5 = this.mul(u3, u2); const v3 = this.mul(this.sqr(v), v); const p = this.pow(this.mul(u5, v3), e); const x = this.mul(this.mul(u3, v), p); const c = this.mul(v, this.sqr(x)); if (c.eq(u)) return x; throw new SquareRootError(x); } divsqrt5mod8(u, v) { // x = u * v^3 * (u * v^7)^((p - 5) / 8) mod p const e = this.m.subn(5).iushrn(3); const v3 = this.mul(this.sqr(v), v); const v7 = this.mul(this.sqr(v3), v); const p = this.pow(this.mul(u, v7), e); const x = this.mul(this.mul(u, v3), p); const c = this.mul(v, this.sqr(x)); if (c.eq(u)) return x; const mc = this.ineg(c); if (mc.eq(u)) return this.mul(x, this.sm1); if (mc.eq(this.mul(u, this.sm1))) throw new SquareRootError(this.mul(x, this.sm1)); throw new SquareRootError(x); } isSquare(a) { if (this.m.isOdd()) return this.jacobi(a) >= 0; return this.kronecker(a) >= 0; } ishl(a, num) { this._verify1(a); return this.imod(a.iushl(num)); } shl(a, num) { return this.ishl(a.clone(), num); } ishln(a, num) { this._verify1(a); a.iushln(num); if (num <= 4) { // Quick reduction. while (a.ucmp(this.m) >= 0) a._isub(a, this.m); } else { this.imod(a); } return a; } shln(a, num) { return this.ishln(a.clone(), num); } ineg(a) { this._verify1(a); if (!a.isZero()) a._isub(this.m, a); return a; } neg(a) { return this.ineg(a.clone()); } eq(a, b) { this._verify2(a, b); return a.ucmp(b) === 0; } eqn(a, num) { this._verify1(a); if (this.m.length === 1) { num %= this.m.words[0]; if (num < 0) num += this.m.words[0]; return a.ucmpn(num) === 0; } if (num < 0) { this.m._isubn(-num); const cmp = a.ucmp(this.m); this.m._iaddn(-num); return cmp === 0; } return a.ucmpn(num) === 0; } isHigh(a) { return !this.isLow(a); } isLow(a) { this._verify1(a); return a.ucmp(this.m.ushrn(1)) <= 0; } isOdd(a) { this._verify1(a); return a.isOdd(); } isEven(a) { this._verify1(a); return a.isEven(); } legendre(num) { this._verify1(num); if (this.m.isEven()) throw new Error('legendre: `num` must be odd.'); // Euler's criterion. const e = this.m.subn(1).iushrn(1); // (p - 1) / 2 const symbol = this.pow(num, e); if (symbol.isZero()) return 0; const one = new BN(1).toRed(this); if (symbol.eq(one)) return 1; if (symbol.eq(this.ineg(one))) return -1; throw new Error('Invalid prime.'); } jacobi(a) { this._verify1(a); return a.jacobi(this.m); } kronecker(a) { this._verify1(a); return a.kronecker(this.m); } iinvert(a) { return this.invert(a)._move(a); } invert(a) { this._verify1(a); return a.invert(this.m)._forceRed(this); } ifermat(a) { return this.fermat(a)._move(a); } fermat(a) { this._verify1(a); if (a.isZero() || this.m.cmpn(1) === 0) throw new RangeError('Not invertible.'); // Optimized inversion chain. if (this.prime) return this.prime.fermat(a); // Invert using fermat's little theorem. return this.pow(a, this.m.subn(2)); } invertAll(elems) { // Montgomery's trick. enforce(Array.isArray(elems), 'elems', 'array'); for (const elem of elems) { enforce(BN.isBN(elem), 'elem', 'bignum'); this._verify1(elem); } if (this.m.cmpn(1) === 0 || this.m.isEven()) throw new RangeError('Not invertible.'); const len = elems.length; const invs = new Array(len); if (len === 0) return invs; let acc = new BN(1).toRed(this); for (let i = 0; i < len; i++) { if (elems[i].isZero()) { invs[i] = elems[i].clone(); continue; } invs[i] = acc; acc = this.mul(acc, elems[i]); } acc = this.invert(acc); for (let i = len - 1; i >= 0; i--) { if (elems[i].isZero()) continue; invs[i] = this.mul(acc, invs[i]); acc = this.mul(acc, elems[i]); } return invs; } [custom]() { if (this.prime) return ``; return ``; } } /** * Barrett Engine */ class Barrett extends Red { constructor(m) { super(m); this.prime = null; this.n = this.m.bitLength(); if ((this.n % 26) !== 0) this.n += 26 - (this.n % 26); this.k = this.n * 2; this.w = this.k / 26; this.b = BN.shift(1, this.k).div(this.m); } convertTo(num) { if (num.length > this.w) return super.convertTo(num); return this.imod(num.clone()); } _shift(q) { let i = 0; let j = this.w; while (j < q.length) q.words[i++] = q.words[j++]; if (i === 0) q.words[i++] = 0; q.length = i; } imod(a) { const neg = a.negative; assert(a.length <= this.w); a.negative = 0; const q = a.mul(this.b); // Shift right by `k` bits. this._shift(q); a._isub(a, q.mul(this.m)); if (a.ucmp(this.m) >= 0) a._isub(a, this.m); if (neg && !a.isZero()) a._isub(this.m, a); a.red = this; return a; } } /** * Montgomery Engine */ class Mont extends Red { constructor(m) { super(m); // Note that: // // mi = (-m^-1 mod (2^(n * 2))) mod r // // and: // // mi = (((2^n)^-1 mod m) * r^-1 - 1) / m // // are equivalent. this.prime = null; this.n = this.m.length * 26; this.r = BN.shift(1, this.n); this.r2 = BN.shift(1, this.n * 2).imod(this.m); this.ri = this.r.invert(this.m); this.mi = this.r.mul(this.ri).isubn(1).div(this.m); this.rib = null; } get mont() { return true; } convertTo(num) { if (num.isNeg() || num.ucmp(this.m) >= 0) return this.imod(num.ushln(this.n)); // Equivalent to: (num * 2^n) mod m return this.mul(num, this.r2); } convertFrom(num) { // Equivalent to: num * r^-1 mod m const r = this.mul(num, new BN(1)); r.red = null; return r; } intTo(a) { return (a << BigInt(this.n)) % this.mb; } intFrom(a) { if (this.rib === null) this.rib = this.ri.toBigInt(); return (a * this.rib) % this.mb; } iaddn(a, num) { return this.iadd(a, this.convertTo(new BN(num))); } isubn(a, num) { return this.isub(a, this.convertTo(new BN(num))); } imul(a, b) { return this.mul(a, b)._move(a); } mul(a, b) { if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); const t = a.mul(b); const c = t.umaskn(this.n).mul(this.mi).iumaskn(this.n); const u = t.iadd(c.mul(this.m)).iushrn(this.n); if (u.ucmp(this.m) >= 0) u._isub(u, this.m); return u._forceRed(this); } imuln(a, num) { this._verify1(a); if (a.isZero()) return a; if (num === 0) { a.words[0] = 0; a.length = 1; return a; } const neg = num < 0; if (neg) num = -num; if (this.m.length === 1) num %= this.m.words[0]; const bits = countBits(num); // Potentially compute with additions. // This avoids an expensive division. if (bits > 5) { // Slow case (num > 31). this.imul(a, this.convertTo(new BN(num))); } else if ((num & (num - 1)) === 0) { // Optimize for powers of two. for (let i = 0; i < bits - 1; i++) this.iadd(a, a); } else { // Multiply left to right. const c = a.clone(); for (let i = bits - 2; i >= 0; i--) { this.iadd(a, a); if ((num >> i) & 1) this.iadd(a, c); } } if (neg) this.ineg(a); return a; } eqn(a, num) { this._verify1(a); if (num === 0) return a.isZero(); return a.ucmp(this.convertTo(new BN(num))) === 0; } isLow(a) { this._verify1(a); return this.convertFrom(a).ucmp(this.m.ushrn(1)) <= 0; } isOdd(a) { this._verify1(a); return this.convertFrom(a).isOdd(); } isEven(a) { this._verify1(a); return this.convertFrom(a).isEven(); } invert(a) { this._verify1(a); // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R return this.imod(a.invert(this.m).mul(this.r2)); } } /* * Helpers */ function makeError(Error, msg, start) { const err = new Error(msg); if (Error.captureStackTrace) Error.captureStackTrace(err, start); return err; } function assert(value, message) { if (!value) { const msg = message || 'Assertion failed.'; throw makeError(Error, msg, assert); } } function enforce(value, name, type) { if (!value) { const msg = `"${name}" must be a(n) ${type}.`; throw makeError(TypeError, msg, enforce); } } function range(value, name) { if (!value) { const msg = `"${name}" only works with positive numbers.`; throw makeError(RangeError, msg, range); } } function red(value, name) { if (!value) { const msg = `"${name}" only works with red numbers.`; throw makeError(TypeError, msg, red); } } function nonred(value, name) { if (!value) { const msg = `"${name}" only works with normal numbers.`; throw makeError(TypeError, msg, nonred); } } function nonzero(value) { if (!value) { const msg = 'Cannot divide by zero.'; throw makeError(RangeError, msg, nonzero); } } class SquareRootError extends Error { constructor(result) { super(); this.name = 'SquareRootError'; this.message = 'X is not a square mod P.'; this.result = result.fromRed(); if (Error.captureStackTrace) Error.captureStackTrace(this, SquareRootError); } } function isInteger(num) { return Number.isSafeInteger(num); } function isSMI(num) { return isInteger(num) && num >= -0x3ffffff && num <= 0x3ffffff; } function allocate(ArrayType, size) { if (ArrayType.allocUnsafeSlow) return ArrayType.allocUnsafeSlow(size); return new ArrayType(size); } function getBase(base) { if (base == null) return 10; if (typeof base === 'number') return base; switch (base) { case 'bin': return 2; case 'oct': return 8; case 'dec': return 10; case 'hex': return 16; } return 0; } /* * Internal */ function countBits(w) { if (Math.clz32) return 32 - Math.clz32(w); let t = w; let r = 0; if (t >= 0x1000) { r += 13; t >>>= 13; } if (t >= 0x40) { r += 7; t >>>= 7; } if (t >= 0x8) { r += 4; t >>>= 4; } if (t >= 0x02) { r += 2; t >>>= 2; } return r + t; } function zeroBits(w) { // Shortcut. if (w === 0) return 26; let t = w; let r = 0; if ((t & 0x1fff) === 0) { r += 13; t >>>= 13; } if ((t & 0x7f) === 0) { r += 7; t >>>= 7; } if ((t & 0xf) === 0) { r += 4; t >>>= 4; } if ((t & 0x3) === 0) { r += 2; t >>>= 2; } if ((t & 0x1) === 0) r += 1; return r; } function parseHex(str, start, end) { const len = Math.min(str.length, end); let r = 0; let z = 0; for (let i = start; i < len; i++) { const c = str.charCodeAt(i) - 48; r <<= 4; let b; if (c >= 49 && c <= 54) { // 'a' - 'f' b = c - 49 + 0xa; } else if (c >= 17 && c <= 22) { // 'A' - 'F' b = c - 17 + 0xa; } else { // '0' - '9' b = c; } r |= b; z |= b; } if (z & ~15) throw new Error('Invalid string.'); return r; } function parseBase(str, start, end, mul) { const len = Math.min(str.length, end); let r = 0; for (let i = start; i < len; i++) { const c = str.charCodeAt(i) - 48; r *= mul; let b; if (c >= 49) { // 'a' b = c - 49 + 0xa; } else if (c >= 17) { // 'A' b = c - 17 + 0xa; } else { // '0' - '9' b = c; } if (c < 0 || c > 207 || b >= mul) throw new Error('Invalid string.'); r += b; } return r; } /* * Exponentiation (bigint) */ function powInt(x, e, m) { // Sliding window (odd multiples only). const one = BigInt(1); const wnd = new Array(WND_SIZE); const x2 = (x * x) % m; wnd[0] = x; for (let i = 1; i < WND_SIZE; i++) wnd[i] = (wnd[i - 1] * x2) % m; let i = e.bitLength(); let r = one; while (i >= WND_WIDTH) { let width = WND_WIDTH; let bits = e.bits(i - width, width); if (bits < WND_SIZE) { r = (r * r) % m; i -= 1; continue; } while ((bits & 1) === 0) { width -= 1; bits >>= 1; } if (r === one) { r = wnd[bits >> 1]; } else { r = sqrn(r, width, m); r = (r * wnd[bits >> 1]) % m; } i -= width; } if (i > 0) { const bits = e.bits(0, i); while (i--) { r = (r * r) % m; if ((bits >> i) & 1) r = (r * x) % m; } } return r; } function sqrn(x, n, m) { for (let i = 0; i < n; i++) x = (x * x) % m; return x; } /* * Multiplication */ function smallMulTo(self, num, out) { const len = self.length + num.length; out.negative = self.negative ^ num.negative; out._alloc(len); out.length = len; // Peel one iteration (compiler can't // do it, because of code complexity). const a = self.words[0]; const b = num.words[0]; const r = a * b; const lo = r & 0x3ffffff; let carry = (r / 0x4000000) | 0; let k = 1; out.words[0] = lo; for (; k < out.length - 1; k++) { // Sum all words with the same // `i + j = k` and accumulate // `ncarry`, note that ncarry // could be >= 0x3ffffff. let ncarry = carry >>> 26; let rword = carry & 0x3ffffff; const min = Math.max(0, k - self.length + 1); const max = Math.min(k, num.length - 1); for (let j = min; j <= max; j++) { const i = k - j; const a = self.words[i]; const b = num.words[j]; const r = a * b + rword; ncarry += (r / 0x4000000) | 0; rword = r & 0x3ffffff; } out.words[k] = rword | 0; carry = ncarry | 0; } if (carry !== 0) out.words[k] = carry | 0; else out.length -= 1; return out._strip(); } function bigMulTo(self, num, out) { const len = self.length + num.length; out.negative = self.negative ^ num.negative; out._alloc(len); out.length = len; let carry = 0; let hncarry = 0; let k = 0; for (; k < out.length - 1; k++) { // Sum all words with the same // `i + j = k` and accumulate // `ncarry`, note that ncarry // could be >= 0x3ffffff. let ncarry = hncarry; hncarry = 0; let rword = carry & 0x3ffffff; const min = Math.max(0, k - self.length + 1); const max = Math.min(k, num.length - 1); for (let j = min; j <= max; j++) { const i = k - j; const a = self.words[i]; const b = num.words[j]; const r = a * b; let lo = r & 0x3ffffff; ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; lo = (lo + rword) | 0; rword = lo & 0x3ffffff; ncarry = (ncarry + (lo >>> 26)) | 0; hncarry += ncarry >>> 26; ncarry &= 0x3ffffff; } out.words[k] = rword; carry = ncarry; ncarry = hncarry; } if (carry !== 0) out.words[k] = carry; else out.length -= 1; return out._strip(); } function jumboMulTo(x, y, out) { // v8 has a 2147483519 bit max (~256mb). if (!HAS_BIGINT || x.length + y.length > 82595519) return bigMulTo(x, y, out); const zero = BigInt(0); const mask = BigInt(0x3ffffff); const shift = BigInt(26); let z = x.toBigInt() * y.toBigInt(); const neg = (z < zero) | 0; if (neg) z = -z; let i = 0; while (z > zero) { out.words[i++] = Number(z & mask); z >>= shift; } if (i === 0) out.words[i++] = 0; out.length = i; out.negative = neg; return out; } function comb10MulTo(self, num, out) { const a = self.words; const b = num.words; const o = out.words; const a0 = a[0] | 0; const al0 = a0 & 0x1fff; const ah0 = a0 >>> 13; const a1 = a[1] | 0; const al1 = a1 & 0x1fff; const ah1 = a1 >>> 13; const a2 = a[2] | 0; const al2 = a2 & 0x1fff; const ah2 = a2 >>> 13; const a3 = a[3] | 0; const al3 = a3 & 0x1fff; const ah3 = a3 >>> 13; const a4 = a[4] | 0; const al4 = a4 & 0x1fff; const ah4 = a4 >>> 13; const a5 = a[5] | 0; const al5 = a5 & 0x1fff; const ah5 = a5 >>> 13; const a6 = a[6] | 0; const al6 = a6 & 0x1fff; const ah6 = a6 >>> 13; const a7 = a[7] | 0; const al7 = a7 & 0x1fff; const ah7 = a7 >>> 13; const a8 = a[8] | 0; const al8 = a8 & 0x1fff; const ah8 = a8 >>> 13; const a9 = a[9] | 0; const al9 = a9 & 0x1fff; const ah9 = a9 >>> 13; const b0 = b[0] | 0; const bl0 = b0 & 0x1fff; const bh0 = b0 >>> 13; const b1 = b[1] | 0; const bl1 = b1 & 0x1fff; const bh1 = b1 >>> 13; const b2 = b[2] | 0; const bl2 = b2 & 0x1fff; const bh2 = b2 >>> 13; const b3 = b[3] | 0; const bl3 = b3 & 0x1fff; const bh3 = b3 >>> 13; const b4 = b[4] | 0; const bl4 = b4 & 0x1fff; const bh4 = b4 >>> 13; const b5 = b[5] | 0; const bl5 = b5 & 0x1fff; const bh5 = b5 >>> 13; const b6 = b[6] | 0; const bl6 = b6 & 0x1fff; const bh6 = b6 >>> 13; const b7 = b[7] | 0; const bl7 = b7 & 0x1fff; const bh7 = b7 >>> 13; const b8 = b[8] | 0; const bl8 = b8 & 0x1fff; const bh8 = b8 >>> 13; const b9 = b[9] | 0; const bl9 = b9 & 0x1fff; const bh9 = b9 >>> 13; let c = 0; let lo, mid, hi; out.negative = self.negative ^ num.negative; out._alloc(20); out.length = 19; /* k = 0 */ lo = Math.imul(al0, bl0); mid = Math.imul(al0, bh0); mid = (mid + Math.imul(ah0, bl0)) | 0; hi = Math.imul(ah0, bh0); let w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; w0 &= 0x3ffffff; /* k = 1 */ lo = Math.imul(al1, bl0); mid = Math.imul(al1, bh0); mid = (mid + Math.imul(ah1, bl0)) | 0; hi = Math.imul(ah1, bh0); lo = (lo + Math.imul(al0, bl1)) | 0; mid = (mid + Math.imul(al0, bh1)) | 0; mid = (mid + Math.imul(ah0, bl1)) | 0; hi = (hi + Math.imul(ah0, bh1)) | 0; let w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; w1 &= 0x3ffffff; /* k = 2 */ lo = Math.imul(al2, bl0); mid = Math.imul(al2, bh0); mid = (mid + Math.imul(ah2, bl0)) | 0; hi = Math.imul(ah2, bh0); lo = (lo + Math.imul(al1, bl1)) | 0; mid = (mid + Math.imul(al1, bh1)) | 0; mid = (mid + Math.imul(ah1, bl1)) | 0; hi = (hi + Math.imul(ah1, bh1)) | 0; lo = (lo + Math.imul(al0, bl2)) | 0; mid = (mid + Math.imul(al0, bh2)) | 0; mid = (mid + Math.imul(ah0, bl2)) | 0; hi = (hi + Math.imul(ah0, bh2)) | 0; let w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; w2 &= 0x3ffffff; /* k = 3 */ lo = Math.imul(al3, bl0); mid = Math.imul(al3, bh0); mid = (mid + Math.imul(ah3, bl0)) | 0; hi = Math.imul(ah3, bh0); lo = (lo + Math.imul(al2, bl1)) | 0; mid = (mid + Math.imul(al2, bh1)) | 0; mid = (mid + Math.imul(ah2, bl1)) | 0; hi = (hi + Math.imul(ah2, bh1)) | 0; lo = (lo + Math.imul(al1, bl2)) | 0; mid = (mid + Math.imul(al1, bh2)) | 0; mid = (mid + Math.imul(ah1, bl2)) | 0; hi = (hi + Math.imul(ah1, bh2)) | 0; lo = (lo + Math.imul(al0, bl3)) | 0; mid = (mid + Math.imul(al0, bh3)) | 0; mid = (mid + Math.imul(ah0, bl3)) | 0; hi = (hi + Math.imul(ah0, bh3)) | 0; let w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; w3 &= 0x3ffffff; /* k = 4 */ lo = Math.imul(al4, bl0); mid = Math.imul(al4, bh0); mid = (mid + Math.imul(ah4, bl0)) | 0; hi = Math.imul(ah4, bh0); lo = (lo + Math.imul(al3, bl1)) | 0; mid = (mid + Math.imul(al3, bh1)) | 0; mid = (mid + Math.imul(ah3, bl1)) | 0; hi = (hi + Math.imul(ah3, bh1)) | 0; lo = (lo + Math.imul(al2, bl2)) | 0; mid = (mid + Math.imul(al2, bh2)) | 0; mid = (mid + Math.imul(ah2, bl2)) | 0; hi = (hi + Math.imul(ah2, bh2)) | 0; lo = (lo + Math.imul(al1, bl3)) | 0; mid = (mid + Math.imul(al1, bh3)) | 0; mid = (mid + Math.imul(ah1, bl3)) | 0; hi = (hi + Math.imul(ah1, bh3)) | 0; lo = (lo + Math.imul(al0, bl4)) | 0; mid = (mid + Math.imul(al0, bh4)) | 0; mid = (mid + Math.imul(ah0, bl4)) | 0; hi = (hi + Math.imul(ah0, bh4)) | 0; let w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; w4 &= 0x3ffffff; /* k = 5 */ lo = Math.imul(al5, bl0); mid = Math.imul(al5, bh0); mid = (mid + Math.imul(ah5, bl0)) | 0; hi = Math.imul(ah5, bh0); lo = (lo + Math.imul(al4, bl1)) | 0; mid = (mid + Math.imul(al4, bh1)) | 0; mid = (mid + Math.imul(ah4, bl1)) | 0; hi = (hi + Math.imul(ah4, bh1)) | 0; lo = (lo + Math.imul(al3, bl2)) | 0; mid = (mid + Math.imul(al3, bh2)) | 0; mid = (mid + Math.imul(ah3, bl2)) | 0; hi = (hi + Math.imul(ah3, bh2)) | 0; lo = (lo + Math.imul(al2, bl3)) | 0; mid = (mid + Math.imul(al2, bh3)) | 0; mid = (mid + Math.imul(ah2, bl3)) | 0; hi = (hi + Math.imul(ah2, bh3)) | 0; lo = (lo + Math.imul(al1, bl4)) | 0; mid = (mid + Math.imul(al1, bh4)) | 0; mid = (mid + Math.imul(ah1, bl4)) | 0; hi = (hi + Math.imul(ah1, bh4)) | 0; lo = (lo + Math.imul(al0, bl5)) | 0; mid = (mid + Math.imul(al0, bh5)) | 0; mid = (mid + Math.imul(ah0, bl5)) | 0; hi = (hi + Math.imul(ah0, bh5)) | 0; let w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; w5 &= 0x3ffffff; /* k = 6 */ lo = Math.imul(al6, bl0); mid = Math.imul(al6, bh0); mid = (mid + Math.imul(ah6, bl0)) | 0; hi = Math.imul(ah6, bh0); lo = (lo + Math.imul(al5, bl1)) | 0; mid = (mid + Math.imul(al5, bh1)) | 0; mid = (mid + Math.imul(ah5, bl1)) | 0; hi = (hi + Math.imul(ah5, bh1)) | 0; lo = (lo + Math.imul(al4, bl2)) | 0; mid = (mid + Math.imul(al4, bh2)) | 0; mid = (mid + Math.imul(ah4, bl2)) | 0; hi = (hi + Math.imul(ah4, bh2)) | 0; lo = (lo + Math.imul(al3, bl3)) | 0; mid = (mid + Math.imul(al3, bh3)) | 0; mid = (mid + Math.imul(ah3, bl3)) | 0; hi = (hi + Math.imul(ah3, bh3)) | 0; lo = (lo + Math.imul(al2, bl4)) | 0; mid = (mid + Math.imul(al2, bh4)) | 0; mid = (mid + Math.imul(ah2, bl4)) | 0; hi = (hi + Math.imul(ah2, bh4)) | 0; lo = (lo + Math.imul(al1, bl5)) | 0; mid = (mid + Math.imul(al1, bh5)) | 0; mid = (mid + Math.imul(ah1, bl5)) | 0; hi = (hi + Math.imul(ah1, bh5)) | 0; lo = (lo + Math.imul(al0, bl6)) | 0; mid = (mid + Math.imul(al0, bh6)) | 0; mid = (mid + Math.imul(ah0, bl6)) | 0; hi = (hi + Math.imul(ah0, bh6)) | 0; let w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; w6 &= 0x3ffffff; /* k = 7 */ lo = Math.imul(al7, bl0); mid = Math.imul(al7, bh0); mid = (mid + Math.imul(ah7, bl0)) | 0; hi = Math.imul(ah7, bh0); lo = (lo + Math.imul(al6, bl1)) | 0; mid = (mid + Math.imul(al6, bh1)) | 0; mid = (mid + Math.imul(ah6, bl1)) | 0; hi = (hi + Math.imul(ah6, bh1)) | 0; lo = (lo + Math.imul(al5, bl2)) | 0; mid = (mid + Math.imul(al5, bh2)) | 0; mid = (mid + Math.imul(ah5, bl2)) | 0; hi = (hi + Math.imul(ah5, bh2)) | 0; lo = (lo + Math.imul(al4, bl3)) | 0; mid = (mid + Math.imul(al4, bh3)) | 0; mid = (mid + Math.imul(ah4, bl3)) | 0; hi = (hi + Math.imul(ah4, bh3)) | 0; lo = (lo + Math.imul(al3, bl4)) | 0; mid = (mid + Math.imul(al3, bh4)) | 0; mid = (mid + Math.imul(ah3, bl4)) | 0; hi = (hi + Math.imul(ah3, bh4)) | 0; lo = (lo + Math.imul(al2, bl5)) | 0; mid = (mid + Math.imul(al2, bh5)) | 0; mid = (mid + Math.imul(ah2, bl5)) | 0; hi = (hi + Math.imul(ah2, bh5)) | 0; lo = (lo + Math.imul(al1, bl6)) | 0; mid = (mid + Math.imul(al1, bh6)) | 0; mid = (mid + Math.imul(ah1, bl6)) | 0; hi = (hi + Math.imul(ah1, bh6)) | 0; lo = (lo + Math.imul(al0, bl7)) | 0; mid = (mid + Math.imul(al0, bh7)) | 0; mid = (mid + Math.imul(ah0, bl7)) | 0; hi = (hi + Math.imul(ah0, bh7)) | 0; let w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; w7 &= 0x3ffffff; /* k = 8 */ lo = Math.imul(al8, bl0); mid = Math.imul(al8, bh0); mid = (mid + Math.imul(ah8, bl0)) | 0; hi = Math.imul(ah8, bh0); lo = (lo + Math.imul(al7, bl1)) | 0; mid = (mid + Math.imul(al7, bh1)) | 0; mid = (mid + Math.imul(ah7, bl1)) | 0; hi = (hi + Math.imul(ah7, bh1)) | 0; lo = (lo + Math.imul(al6, bl2)) | 0; mid = (mid + Math.imul(al6, bh2)) | 0; mid = (mid + Math.imul(ah6, bl2)) | 0; hi = (hi + Math.imul(ah6, bh2)) | 0; lo = (lo + Math.imul(al5, bl3)) | 0; mid = (mid + Math.imul(al5, bh3)) | 0; mid = (mid + Math.imul(ah5, bl3)) | 0; hi = (hi + Math.imul(ah5, bh3)) | 0; lo = (lo + Math.imul(al4, bl4)) | 0; mid = (mid + Math.imul(al4, bh4)) | 0; mid = (mid + Math.imul(ah4, bl4)) | 0; hi = (hi + Math.imul(ah4, bh4)) | 0; lo = (lo + Math.imul(al3, bl5)) | 0; mid = (mid + Math.imul(al3, bh5)) | 0; mid = (mid + Math.imul(ah3, bl5)) | 0; hi = (hi + Math.imul(ah3, bh5)) | 0; lo = (lo + Math.imul(al2, bl6)) | 0; mid = (mid + Math.imul(al2, bh6)) | 0; mid = (mid + Math.imul(ah2, bl6)) | 0; hi = (hi + Math.imul(ah2, bh6)) | 0; lo = (lo + Math.imul(al1, bl7)) | 0; mid = (mid + Math.imul(al1, bh7)) | 0; mid = (mid + Math.imul(ah1, bl7)) | 0; hi = (hi + Math.imul(ah1, bh7)) | 0; lo = (lo + Math.imul(al0, bl8)) | 0; mid = (mid + Math.imul(al0, bh8)) | 0; mid = (mid + Math.imul(ah0, bl8)) | 0; hi = (hi + Math.imul(ah0, bh8)) | 0; let w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; w8 &= 0x3ffffff; /* k = 9 */ lo = Math.imul(al9, bl0); mid = Math.imul(al9, bh0); mid = (mid + Math.imul(ah9, bl0)) | 0; hi = Math.imul(ah9, bh0); lo = (lo + Math.imul(al8, bl1)) | 0; mid = (mid + Math.imul(al8, bh1)) | 0; mid = (mid + Math.imul(ah8, bl1)) | 0; hi = (hi + Math.imul(ah8, bh1)) | 0; lo = (lo + Math.imul(al7, bl2)) | 0; mid = (mid + Math.imul(al7, bh2)) | 0; mid = (mid + Math.imul(ah7, bl2)) | 0; hi = (hi + Math.imul(ah7, bh2)) | 0; lo = (lo + Math.imul(al6, bl3)) | 0; mid = (mid + Math.imul(al6, bh3)) | 0; mid = (mid + Math.imul(ah6, bl3)) | 0; hi = (hi + Math.imul(ah6, bh3)) | 0; lo = (lo + Math.imul(al5, bl4)) | 0; mid = (mid + Math.imul(al5, bh4)) | 0; mid = (mid + Math.imul(ah5, bl4)) | 0; hi = (hi + Math.imul(ah5, bh4)) | 0; lo = (lo + Math.imul(al4, bl5)) | 0; mid = (mid + Math.imul(al4, bh5)) | 0; mid = (mid + Math.imul(ah4, bl5)) | 0; hi = (hi + Math.imul(ah4, bh5)) | 0; lo = (lo + Math.imul(al3, bl6)) | 0; mid = (mid + Math.imul(al3, bh6)) | 0; mid = (mid + Math.imul(ah3, bl6)) | 0; hi = (hi + Math.imul(ah3, bh6)) | 0; lo = (lo + Math.imul(al2, bl7)) | 0; mid = (mid + Math.imul(al2, bh7)) | 0; mid = (mid + Math.imul(ah2, bl7)) | 0; hi = (hi + Math.imul(ah2, bh7)) | 0; lo = (lo + Math.imul(al1, bl8)) | 0; mid = (mid + Math.imul(al1, bh8)) | 0; mid = (mid + Math.imul(ah1, bl8)) | 0; hi = (hi + Math.imul(ah1, bh8)) | 0; lo = (lo + Math.imul(al0, bl9)) | 0; mid = (mid + Math.imul(al0, bh9)) | 0; mid = (mid + Math.imul(ah0, bl9)) | 0; hi = (hi + Math.imul(ah0, bh9)) | 0; let w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; w9 &= 0x3ffffff; /* k = 10 */ lo = Math.imul(al9, bl1); mid = Math.imul(al9, bh1); mid = (mid + Math.imul(ah9, bl1)) | 0; hi = Math.imul(ah9, bh1); lo = (lo + Math.imul(al8, bl2)) | 0; mid = (mid + Math.imul(al8, bh2)) | 0; mid = (mid + Math.imul(ah8, bl2)) | 0; hi = (hi + Math.imul(ah8, bh2)) | 0; lo = (lo + Math.imul(al7, bl3)) | 0; mid = (mid + Math.imul(al7, bh3)) | 0; mid = (mid + Math.imul(ah7, bl3)) | 0; hi = (hi + Math.imul(ah7, bh3)) | 0; lo = (lo + Math.imul(al6, bl4)) | 0; mid = (mid + Math.imul(al6, bh4)) | 0; mid = (mid + Math.imul(ah6, bl4)) | 0; hi = (hi + Math.imul(ah6, bh4)) | 0; lo = (lo + Math.imul(al5, bl5)) | 0; mid = (mid + Math.imul(al5, bh5)) | 0; mid = (mid + Math.imul(ah5, bl5)) | 0; hi = (hi + Math.imul(ah5, bh5)) | 0; lo = (lo + Math.imul(al4, bl6)) | 0; mid = (mid + Math.imul(al4, bh6)) | 0; mid = (mid + Math.imul(ah4, bl6)) | 0; hi = (hi + Math.imul(ah4, bh6)) | 0; lo = (lo + Math.imul(al3, bl7)) | 0; mid = (mid + Math.imul(al3, bh7)) | 0; mid = (mid + Math.imul(ah3, bl7)) | 0; hi = (hi + Math.imul(ah3, bh7)) | 0; lo = (lo + Math.imul(al2, bl8)) | 0; mid = (mid + Math.imul(al2, bh8)) | 0; mid = (mid + Math.imul(ah2, bl8)) | 0; hi = (hi + Math.imul(ah2, bh8)) | 0; lo = (lo + Math.imul(al1, bl9)) | 0; mid = (mid + Math.imul(al1, bh9)) | 0; mid = (mid + Math.imul(ah1, bl9)) | 0; hi = (hi + Math.imul(ah1, bh9)) | 0; let w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; w10 &= 0x3ffffff; /* k = 11 */ lo = Math.imul(al9, bl2); mid = Math.imul(al9, bh2); mid = (mid + Math.imul(ah9, bl2)) | 0; hi = Math.imul(ah9, bh2); lo = (lo + Math.imul(al8, bl3)) | 0; mid = (mid + Math.imul(al8, bh3)) | 0; mid = (mid + Math.imul(ah8, bl3)) | 0; hi = (hi + Math.imul(ah8, bh3)) | 0; lo = (lo + Math.imul(al7, bl4)) | 0; mid = (mid + Math.imul(al7, bh4)) | 0; mid = (mid + Math.imul(ah7, bl4)) | 0; hi = (hi + Math.imul(ah7, bh4)) | 0; lo = (lo + Math.imul(al6, bl5)) | 0; mid = (mid + Math.imul(al6, bh5)) | 0; mid = (mid + Math.imul(ah6, bl5)) | 0; hi = (hi + Math.imul(ah6, bh5)) | 0; lo = (lo + Math.imul(al5, bl6)) | 0; mid = (mid + Math.imul(al5, bh6)) | 0; mid = (mid + Math.imul(ah5, bl6)) | 0; hi = (hi + Math.imul(ah5, bh6)) | 0; lo = (lo + Math.imul(al4, bl7)) | 0; mid = (mid + Math.imul(al4, bh7)) | 0; mid = (mid + Math.imul(ah4, bl7)) | 0; hi = (hi + Math.imul(ah4, bh7)) | 0; lo = (lo + Math.imul(al3, bl8)) | 0; mid = (mid + Math.imul(al3, bh8)) | 0; mid = (mid + Math.imul(ah3, bl8)) | 0; hi = (hi + Math.imul(ah3, bh8)) | 0; lo = (lo + Math.imul(al2, bl9)) | 0; mid = (mid + Math.imul(al2, bh9)) | 0; mid = (mid + Math.imul(ah2, bl9)) | 0; hi = (hi + Math.imul(ah2, bh9)) | 0; let w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; w11 &= 0x3ffffff; /* k = 12 */ lo = Math.imul(al9, bl3); mid = Math.imul(al9, bh3); mid = (mid + Math.imul(ah9, bl3)) | 0; hi = Math.imul(ah9, bh3); lo = (lo + Math.imul(al8, bl4)) | 0; mid = (mid + Math.imul(al8, bh4)) | 0; mid = (mid + Math.imul(ah8, bl4)) | 0; hi = (hi + Math.imul(ah8, bh4)) | 0; lo = (lo + Math.imul(al7, bl5)) | 0; mid = (mid + Math.imul(al7, bh5)) | 0; mid = (mid + Math.imul(ah7, bl5)) | 0; hi = (hi + Math.imul(ah7, bh5)) | 0; lo = (lo + Math.imul(al6, bl6)) | 0; mid = (mid + Math.imul(al6, bh6)) | 0; mid = (mid + Math.imul(ah6, bl6)) | 0; hi = (hi + Math.imul(ah6, bh6)) | 0; lo = (lo + Math.imul(al5, bl7)) | 0; mid = (mid + Math.imul(al5, bh7)) | 0; mid = (mid + Math.imul(ah5, bl7)) | 0; hi = (hi + Math.imul(ah5, bh7)) | 0; lo = (lo + Math.imul(al4, bl8)) | 0; mid = (mid + Math.imul(al4, bh8)) | 0; mid = (mid + Math.imul(ah4, bl8)) | 0; hi = (hi + Math.imul(ah4, bh8)) | 0; lo = (lo + Math.imul(al3, bl9)) | 0; mid = (mid + Math.imul(al3, bh9)) | 0; mid = (mid + Math.imul(ah3, bl9)) | 0; hi = (hi + Math.imul(ah3, bh9)) | 0; let w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; w12 &= 0x3ffffff; /* k = 13 */ lo = Math.imul(al9, bl4); mid = Math.imul(al9, bh4); mid = (mid + Math.imul(ah9, bl4)) | 0; hi = Math.imul(ah9, bh4); lo = (lo + Math.imul(al8, bl5)) | 0; mid = (mid + Math.imul(al8, bh5)) | 0; mid = (mid + Math.imul(ah8, bl5)) | 0; hi = (hi + Math.imul(ah8, bh5)) | 0; lo = (lo + Math.imul(al7, bl6)) | 0; mid = (mid + Math.imul(al7, bh6)) | 0; mid = (mid + Math.imul(ah7, bl6)) | 0; hi = (hi + Math.imul(ah7, bh6)) | 0; lo = (lo + Math.imul(al6, bl7)) | 0; mid = (mid + Math.imul(al6, bh7)) | 0; mid = (mid + Math.imul(ah6, bl7)) | 0; hi = (hi + Math.imul(ah6, bh7)) | 0; lo = (lo + Math.imul(al5, bl8)) | 0; mid = (mid + Math.imul(al5, bh8)) | 0; mid = (mid + Math.imul(ah5, bl8)) | 0; hi = (hi + Math.imul(ah5, bh8)) | 0; lo = (lo + Math.imul(al4, bl9)) | 0; mid = (mid + Math.imul(al4, bh9)) | 0; mid = (mid + Math.imul(ah4, bl9)) | 0; hi = (hi + Math.imul(ah4, bh9)) | 0; let w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; w13 &= 0x3ffffff; /* k = 14 */ lo = Math.imul(al9, bl5); mid = Math.imul(al9, bh5); mid = (mid + Math.imul(ah9, bl5)) | 0; hi = Math.imul(ah9, bh5); lo = (lo + Math.imul(al8, bl6)) | 0; mid = (mid + Math.imul(al8, bh6)) | 0; mid = (mid + Math.imul(ah8, bl6)) | 0; hi = (hi + Math.imul(ah8, bh6)) | 0; lo = (lo + Math.imul(al7, bl7)) | 0; mid = (mid + Math.imul(al7, bh7)) | 0; mid = (mid + Math.imul(ah7, bl7)) | 0; hi = (hi + Math.imul(ah7, bh7)) | 0; lo = (lo + Math.imul(al6, bl8)) | 0; mid = (mid + Math.imul(al6, bh8)) | 0; mid = (mid + Math.imul(ah6, bl8)) | 0; hi = (hi + Math.imul(ah6, bh8)) | 0; lo = (lo + Math.imul(al5, bl9)) | 0; mid = (mid + Math.imul(al5, bh9)) | 0; mid = (mid + Math.imul(ah5, bl9)) | 0; hi = (hi + Math.imul(ah5, bh9)) | 0; let w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; w14 &= 0x3ffffff; /* k = 15 */ lo = Math.imul(al9, bl6); mid = Math.imul(al9, bh6); mid = (mid + Math.imul(ah9, bl6)) | 0; hi = Math.imul(ah9, bh6); lo = (lo + Math.imul(al8, bl7)) | 0; mid = (mid + Math.imul(al8, bh7)) | 0; mid = (mid + Math.imul(ah8, bl7)) | 0; hi = (hi + Math.imul(ah8, bh7)) | 0; lo = (lo + Math.imul(al7, bl8)) | 0; mid = (mid + Math.imul(al7, bh8)) | 0; mid = (mid + Math.imul(ah7, bl8)) | 0; hi = (hi + Math.imul(ah7, bh8)) | 0; lo = (lo + Math.imul(al6, bl9)) | 0; mid = (mid + Math.imul(al6, bh9)) | 0; mid = (mid + Math.imul(ah6, bl9)) | 0; hi = (hi + Math.imul(ah6, bh9)) | 0; let w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; w15 &= 0x3ffffff; /* k = 16 */ lo = Math.imul(al9, bl7); mid = Math.imul(al9, bh7); mid = (mid + Math.imul(ah9, bl7)) | 0; hi = Math.imul(ah9, bh7); lo = (lo + Math.imul(al8, bl8)) | 0; mid = (mid + Math.imul(al8, bh8)) | 0; mid = (mid + Math.imul(ah8, bl8)) | 0; hi = (hi + Math.imul(ah8, bh8)) | 0; lo = (lo + Math.imul(al7, bl9)) | 0; mid = (mid + Math.imul(al7, bh9)) | 0; mid = (mid + Math.imul(ah7, bl9)) | 0; hi = (hi + Math.imul(ah7, bh9)) | 0; let w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; w16 &= 0x3ffffff; /* k = 17 */ lo = Math.imul(al9, bl8); mid = Math.imul(al9, bh8); mid = (mid + Math.imul(ah9, bl8)) | 0; hi = Math.imul(ah9, bh8); lo = (lo + Math.imul(al8, bl9)) | 0; mid = (mid + Math.imul(al8, bh9)) | 0; mid = (mid + Math.imul(ah8, bl9)) | 0; hi = (hi + Math.imul(ah8, bh9)) | 0; let w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; w17 &= 0x3ffffff; /* k = 18 */ lo = Math.imul(al9, bl9); mid = Math.imul(al9, bh9); mid = (mid + Math.imul(ah9, bl9)) | 0; hi = Math.imul(ah9, bh9); let w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; w18 &= 0x3ffffff; o[0] = w0; o[1] = w1; o[2] = w2; o[3] = w3; o[4] = w4; o[5] = w5; o[6] = w6; o[7] = w7; o[8] = w8; o[9] = w9; o[10] = w10; o[11] = w11; o[12] = w12; o[13] = w13; o[14] = w14; o[15] = w15; o[16] = w16; o[17] = w17; o[18] = w18; if (c !== 0) { o[19] = c; out.length += 1; } // Note: we shouldn't need to strip here. return out; } // Polyfill comb. if (!Math.imul) comb10MulTo = smallMulTo; /* * Expose */ BN.Red = Red; module.exports = BN; }], [/* 33 */ 'bcrypto', '/lib/internal/custom-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * custom.js - custom inspect symbol for bcrypto * Copyright (c) 2018-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; exports.custom = 'inspect'; }], [/* 34 */ 'bcrypto', '/lib/internal/asn1.js', function(exports, module, __filename, __dirname, __meta) { /*! * asn1.js - asn1 parsing for bcrypto * Copyright (c) 2020, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; const assert = require('assert'); const BN = __node_require__(31 /* '../bn' */); /* * ASN1 */ function readSize(data, pos, strict) { assert(Buffer.isBuffer(data)); assert((pos >>> 0) === pos); assert(typeof strict === 'boolean'); if (pos >= data.length) throw new Error('Invalid size.'); const field = data[pos]; const bytes = field & 0x7f; pos += 1; // Definite form. if ((field & 0x80) === 0) { // Short form. return [bytes, pos]; } // Indefinite form. if (strict && bytes === 0) throw new Error('Indefinite length.'); // Long form. let size = 0; for (let i = 0; i < bytes; i++) { assert(pos < data.length); const ch = data[pos]; pos += 1; if (size >= (1 << 24)) throw new Error('Length too large.'); size *= 0x100; size += ch; if (strict && size === 0) throw new Error('Unexpected leading zeroes.'); } if (strict && size < 0x80) throw new Error('Non-minimal length.'); return [size, pos]; } function readSeq(data, pos, strict = true) { assert(Buffer.isBuffer(data)); assert((pos >>> 0) === pos); assert(typeof strict === 'boolean'); if (pos >= data.length || data[pos] !== 0x30) throw new Error('Invalid sequence tag.'); pos += 1; let size; [size, pos] = readSize(data, pos, strict); if (strict && pos + size !== data.length) throw new Error('Trailing bytes.'); return pos; } function readInt(data, pos, strict = true) { assert(Buffer.isBuffer(data)); assert((pos >>> 0) === pos); assert(typeof strict === 'boolean'); if (pos >= data.length || data[pos] !== 0x02) throw new Error('Invalid integer tag.'); pos += 1; let size; [size, pos] = readSize(data, pos, strict); if (pos + size > data.length) throw new Error('Integer body out of bounds.'); if (strict) { // Zero length integer. if (size === 0) throw new Error('Zero length integer.'); // No negatives. if (data[pos] & 0x80) throw new Error('Integers must be positive.'); // Allow zero only if it prefixes a high bit. if (size > 1) { if (data[pos] === 0x00 && (data[pos + 1] & 0x80) === 0x00) throw new Error('Unexpected leading zeroes.'); } } // Eat leading zeroes. while (size > 0 && data[pos] === 0x00) { pos += 1; size -= 1; } // No reason to have an integer larger than this. if (size > 2048) throw new Error('Invalid integer size.'); const num = BN.decode(data.slice(pos, pos + size)); pos += size; return [num, pos]; } function readVersion(data, pos, version, strict = true) { assert(Buffer.isBuffer(data)); assert((pos >>> 0) === pos); assert((version & 0xff) === version); assert(typeof strict === 'boolean'); let num; [num, pos] = readInt(data, pos, strict); if (num.cmpn(version) !== 0) throw new Error('Invalid version.'); return pos; } function sizeSize(size) { assert((size >>> 0) === size); if (size <= 0x7f) // [size] return 1; if (size <= 0xff) // 0x81 [size] return 2; assert(size <= 0xffff); return 3; // 0x82 [size-hi] [size-lo] } function sizeSeq(size) { return 1 + sizeSize(size) + size; } function sizeInt(num) { assert(num instanceof BN); // 0x02 [size] [0x00?] [int] const bits = num.bitLength(); let size = (bits + 7) >>> 3; if (bits > 0 && (bits & 7) === 0) size += num.testn(bits - 1); if (bits === 0) size = 1; return 1 + sizeSize(size) + size; } function sizeVersion(version) { assert((version & 0xff) === version); return 3; } function writeSize(data, pos, size) { assert(Buffer.isBuffer(data)); assert((pos >>> 0) === pos); assert((size >>> 0) === size); if (size <= 0x7f) { // [size] data[pos++] = size; } else if (size <= 0xff) { // 0x81 [size] data[pos++] = 0x81; data[pos++] = size; } else { // 0x82 [size-hi] [size-lo] assert(size <= 0xffff); data[pos++] = 0x82; data[pos++] = size >> 8; data[pos++] = size & 0xff; } assert(pos <= data.length); return pos; } function writeSeq(data, pos, size) { assert(Buffer.isBuffer(data)); assert((pos >>> 0) === pos); data[pos++] = 0x30; return writeSize(data, pos, size); } function writeInt(data, pos, num) { assert(Buffer.isBuffer(data)); assert((pos >>> 0) === pos); assert(num instanceof BN); // 0x02 [size] [0x00?] [int] const bits = num.bitLength(); let size = (bits + 7) >>> 3; let pad = 0; if (bits > 0 && (bits & 7) === 0) pad = num.testn(bits - 1); if (bits === 0) size = 1; data[pos++] = 0x02; pos = writeSize(data, pos, pad + size); if (pad) data[pos++] = 0x00; if (bits !== 0) num.encode().copy(data, pos); else data[pos] = 0x00; pos += size; assert(pos <= data.length); return pos; } function writeVersion(data, pos, version) { assert(Buffer.isBuffer(data)); assert((pos >>> 0) === pos); assert((version & 0xff) === version); assert(pos + 3 <= data.length); data[pos++] = 0x02; data[pos++] = 0x01; data[pos++] = version; return pos; } /* * Expose */ exports.readSize = readSize; exports.readSeq = readSeq; exports.readInt = readInt; exports.readVersion = readVersion; exports.sizeSize = sizeSize; exports.sizeSeq = sizeSeq; exports.sizeInt = sizeInt; exports.sizeVersion = sizeVersion; exports.writeSize = writeSize; exports.writeSeq = writeSeq; exports.writeInt = writeInt; exports.writeVersion = writeVersion; }], [/* 35 */ 'bcrypto', '/lib/js/schnorr-legacy.js', function(exports, module, __filename, __dirname, __meta) { /*! * schnorr-legacy.js - bip-schnorr for bcrypto * Copyright (c) 2019-2020, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Parts of this software are based on sipa/bip-schnorr: * Copyright (c) 2018-2019, Pieter Wuille (2-clause BSD License). * https://github.com/sipa/bips/blob/d194620/bip-schnorr/reference.py * * Parts of this software are based on ElementsProject/secp256k1-zkp: * Copyright (c) 2013, Pieter Wuille. * https://github.com/ElementsProject/secp256k1-zkp * * Resources: * https://github.com/sipa/bips/blob/d194620/bip-schnorr.mediawiki * https://github.com/sipa/bips/blob/d194620/bip-schnorr/reference.py * https://github.com/sipa/bips/blob/d194620/bip-schnorr/test-vectors.csv * https://github.com/ElementsProject/secp256k1-zkp/tree/11af701/src/modules/schnorrsig * https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/2019-05-15-schnorr.md * * References: * * [SCHNORR] Schnorr Signatures for secp256k1 * Pieter Wuille * https://github.com/sipa/bips/blob/d194620/bip-schnorr.mediawiki * * [CASH] Schnorr Signature specification * Mark B. Lundeberg * https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/2019-05-15-schnorr.md */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); const BatchRNG = __node_require__(36 /* './batch-rng' */); const BN = __node_require__(31 /* '../bn' */); /** * Schnorr */ class Schnorr { constructor(curve, hash) { this.curve = curve; this.hash = hash; this.rng = new BatchRNG(this.curve, this.encode.bind(this)); } check() { // [SCHNORR] "Footnotes". // Must be congruent to 3 mod 4. if (this.curve.p.andln(3) !== 3) throw new Error(`Schnorr is not supported for ${this.curve.id}.`); } encode(key) { // Extra speedy key reserialization. assert(Buffer.isBuffer(key)); const {fieldSize} = this.curve; if (key.length === 1 + fieldSize) return key; if (key.length !== 1 + fieldSize * 2) throw new Error('Invalid point.'); const out = Buffer.alloc(1 + fieldSize); out[0] = 0x02 | (key[key.length - 1] & 1); key.copy(out, 1, 1, 1 + fieldSize); return out; } hashInt(...items) { // [SCHNORR] "Specification". // eslint-disable-next-line const h = new this.hash(); h.init(); for (const item of items) h.update(item); let hash = h.final(this.curve.scalarSize); if (hash.length > this.curve.scalarSize) hash = hash.slice(0, this.curve.scalarSize); const num = BN.decode(hash, this.curve.endian); num.iumaskn(this.curve.scalarBits); return num.imod(this.curve.n); } hashNonce(a, m) { return this.hashInt(a, m); } hashChallenge(R, A, m) { return this.hashInt(R, this.encode(A), m); } sign(msg, key) { assert(Buffer.isBuffer(msg)); this.check(); return this._sign(msg, key); } _sign(msg, key) { // Schnorr Signing. // // [SCHNORR] "Signing". // [CASH] "Recommended practices for secure signature generation". // // Assumptions: // // - Let `H` be a cryptographic hash function. // - Let `m` be a 32-byte array. // - Let `a` be a secret non-zero scalar. // - k != 0. // // Computation: // // A = G * a // k = H(a, m) mod n // R = G * k // k = -k mod n, if y(R) is not square // r = x(R) // e = H(r, A, m) mod n // s = (k + e * a) mod n // S = (r, s) // // Note that `k` must remain secret, // otherwise an attacker can compute: // // a = (s - k) / e mod n const {n} = this.curve; const G = this.curve.g; const a = this.curve.decodeScalar(key); if (a.isZero() || a.cmp(n) >= 0) throw new Error('Invalid private key.'); const A = G.mulBlind(a); const k = this.hashNonce(key, msg); if (k.isZero()) throw new Error('Signing failed (k\' = 0).'); const R = G.mulBlind(k); if (!R.isSquare()) k.ineg().imod(n); const Rraw = R.encodeX(); const Araw = A.encode(); const e = this.hashChallenge(Rraw, Araw, msg); const s = k.add(e.mul(a)).imod(n); return Buffer.concat([Rraw, this.curve.encodeScalar(s)]); } verify(msg, sig, key) { assert(Buffer.isBuffer(msg)); assert(Buffer.isBuffer(sig)); assert(Buffer.isBuffer(key)); this.check(); if (sig.length !== this.curve.fieldSize + this.curve.scalarSize) return false; try { return this._verify(msg, sig, key); } catch (e) { return false; } } _verify(msg, sig, key) { // Schnorr Verification. // // [SCHNORR] "Verification". // [CASH] "Signature verification algorithm". // // Assumptions: // // - Let `H` be a cryptographic hash function. // - Let `m` be a 32-byte array. // - Let `r` and `s` be signature elements. // - Let `A` be a valid group element. // - r^3 + a * r + b is square in F(p). // - sqrt(r^3 + a * r + b) is square in F(p). // - r < p, s < n. // - R != O. // // Computation: // // R = (r, sqrt(r^3 + a * r + b)) // e = H(r, A, m) mod n // R == G * s - A * e // // We can skip a square root with: // // e = H(r, A, m) mod n // R = G * s - A * e // y(R) is square // x(R) == r // // We can also avoid affinization by // replacing the two assertions with: // // (y(R) * z(R) mod p) is square // x(R) == r * z(R)^2 mod p // // Furthermore, squareness can be calculated // with a variable time Jacobi symbol algorithm. const {p, n} = this.curve; const G = this.curve.g; const Rraw = sig.slice(0, this.curve.fieldSize); const sraw = sig.slice(this.curve.fieldSize); const r = this.curve.decodeField(Rraw); const s = this.curve.decodeScalar(sraw); const A = this.curve.decodePoint(key); if (r.cmp(p) >= 0 || s.cmp(n) >= 0) return false; const e = this.hashChallenge(Rraw, key, msg); const R = G.jmulAdd(s, A, e.ineg().imod(n)); if (!R.isSquare()) return false; if (!R.eqX(r)) return false; return true; } verifyBatch(batch) { assert(Array.isArray(batch)); this.check(); for (const item of batch) { assert(Array.isArray(item) && item.length === 3); const [msg, sig, key] = item; assert(Buffer.isBuffer(msg)); assert(Buffer.isBuffer(sig)); assert(Buffer.isBuffer(key)); if (sig.length !== this.curve.fieldSize + this.curve.scalarSize) return false; } try { return this._verifyBatch(batch); } catch (e) { return false; } } _verifyBatch(batch) { // Schnorr Batch Verification. // // [SCHNORR] "Batch Verification". // // Assumptions: // // - Let `H` be a cryptographic hash function. // - Let `m` be a 32-byte array. // - Let `r` and `s` be signature elements. // - Let `A` be a valid group element. // - Let `i` be the batch item index. // - r^3 + a * r + b is square in F(p). // - sqrt(r^3 + a * r + b) is square in F(p). // - r < p, s < n. // - a1 = 1 mod n. // // Computation: // // Ri = (ri, sqrt(ri^3 + a * ri + b)) // ei = H(ri, Ai, mi) mod n // ai = random integer in [1,n-1] // lhs = si * ai + ... mod n // rhs = Ri * ai + Ai * (ei * ai mod n) + ... // G * -lhs + rhs == O const {n} = this.curve; const G = this.curve.g; const points = new Array(1 + batch.length * 2); const coeffs = new Array(1 + batch.length * 2); const sum = new BN(0); this.rng.init(batch); points[0] = G; coeffs[0] = sum; for (let i = 0; i < batch.length; i++) { const [msg, sig, key] = batch[i]; const Rraw = sig.slice(0, this.curve.fieldSize); const sraw = sig.slice(this.curve.fieldSize); const R = this.curve.decodeSquare(Rraw); const s = this.curve.decodeScalar(sraw); const A = this.curve.decodePoint(key); if (s.cmp(n) >= 0) return false; const e = this.hashChallenge(Rraw, key, msg); const a = this.rng.generate(i); const ea = e.mul(a).imod(n); sum.iadd(s.mul(a)).imod(n); points[1 + i * 2 + 0] = R; coeffs[1 + i * 2 + 0] = a; points[1 + i * 2 + 1] = A; coeffs[1 + i * 2 + 1] = ea; } sum.ineg().imod(n); return this.curve.jmulAll(points, coeffs).isInfinity(); } } /* * Expose */ module.exports = Schnorr; }], [/* 36 */ 'bcrypto', '/lib/js/batch-rng.js', function(exports, module, __filename, __dirname, __meta) { /*! * batch-rng.js - batch rng for bcrypto * Copyright (c) 2019-2020, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Parts of this software are based on ElementsProject/secp256k1-zkp: * Copyright (c) 2013, Pieter Wuille. * https://github.com/ElementsProject/secp256k1-zkp * * Resources: * https://github.com/ElementsProject/secp256k1-zkp/blob/11af701/src/modules/schnorrsig/main_impl.h#L166 * https://github.com/ElementsProject/secp256k1-zkp/blob/11af701/src/scalar_4x64_impl.h#L972 * https://github.com/ElementsProject/secp256k1-zkp/blob/11af701/src/scalar_8x32_impl.h#L747 */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); const BN = __node_require__(31 /* '../bn' */); const ChaCha20 = __node_require__(37 /* '../chacha20' */); const SHA256 = __node_require__(39 /* '../sha256' */); /** * BatchRNG */ class BatchRNG { constructor(curve, encode = key => key) { this.curve = curve; this.encode = encode; this.hash = new SHA256(); this.chacha = new ChaCha20(); this.key = Buffer.alloc(32, 0x00); this.iv = Buffer.alloc(8, 0x00); this.cache = [new BN(1), new BN(1)]; } init(batch) { assert(Array.isArray(batch)); this.hash.init(); for (const [msg, sig, key] of batch) { this.hash.update(SHA256.digest(msg)); this.hash.update(sig); this.hash.update(this.encode(key)); } this.key = this.hash.final(); this.cache[0] = new BN(1); this.cache[1] = new BN(1); return this; } encrypt(counter) { const size = this.curve.scalarSize * 2; const data = Buffer.alloc(size, 0x00); const left = data.slice(0, this.curve.scalarSize); const right = data.slice(this.curve.scalarSize); this.chacha.init(this.key, this.iv, counter); this.chacha.encrypt(data); return [ this.curve.decodeScalar(left), this.curve.decodeScalar(right) ]; } refresh(counter) { let overflow = 0; for (;;) { // First word is always zero. this.iv[4] = overflow; this.iv[5] = overflow >>> 8; this.iv[6] = overflow >>> 16; this.iv[7] = overflow >>> 24; overflow += 1; const [s1, s2] = this.encrypt(counter); if (s1.isZero() || s1.cmp(this.curve.n) >= 0) continue; if (s2.isZero() || s2.cmp(this.curve.n) >= 0) continue; this.cache[0] = s1; this.cache[1] = s2; break; } } generate(index) { assert((index >>> 0) === index); if (index & 1) this.refresh(index >>> 1); return this.cache[index & 1]; } } /* * Expose */ module.exports = BatchRNG; }], [/* 37 */ 'bcrypto', '/lib/chacha20-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * chacha20.js - chacha20 for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; module.exports = __node_require__(38 /* './js/chacha20' */); }], [/* 38 */ 'bcrypto', '/lib/js/chacha20.js', function(exports, module, __filename, __dirname, __meta) { /*! * chacha20.js - chacha20 for bcrypto * Copyright (c) 2016-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Resources * https://en.wikipedia.org/wiki/Chacha20 * https://tools.ietf.org/html/rfc7539#section-2 * https://cr.yp.to/chacha.html */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); /* * Constants */ const BIG_ENDIAN = new Int8Array(new Int16Array([1]).buffer)[0] === 0; /** * ChaCha20 */ class ChaCha20 { /** * Create a ChaCha20 context. * @constructor */ constructor() { this.state = new Uint32Array(16); this.stream = new Uint32Array(16); this.bytes = new Uint8Array(this.stream.buffer); this.pos = -1; if (BIG_ENDIAN) this.bytes = Buffer.alloc(64); } /** * Initialize chacha20 with a key, nonce, and counter. * @param {Buffer} key * @param {Buffer} nonce * @param {Number} counter */ init(key, nonce, counter) { if (counter == null) counter = 0; assert(Buffer.isBuffer(key)); assert(Buffer.isBuffer(nonce)); assert(Number.isSafeInteger(counter)); if (key.length !== 16 && key.length !== 32) throw new RangeError('Invalid key size.'); if (nonce.length >= 24) { key = ChaCha20.derive(key, nonce.slice(0, 16)); nonce = nonce.slice(16); } this.state[0] = 0x61707865; this.state[1] = key.length < 32 ? 0x3120646e : 0x3320646e; this.state[2] = key.length < 32 ? 0x79622d36 : 0x79622d32; this.state[3] = 0x6b206574; this.state[4] = readU32(key, 0); this.state[5] = readU32(key, 4); this.state[6] = readU32(key, 8); this.state[7] = readU32(key, 12); this.state[8] = readU32(key, 16 % key.length); this.state[9] = readU32(key, 20 % key.length); this.state[10] = readU32(key, 24 % key.length); this.state[11] = readU32(key, 28 % key.length); this.state[12] = counter >>> 0; if (nonce.length === 8) { this.state[13] = (counter / 0x100000000) >>> 0; this.state[14] = readU32(nonce, 0); this.state[15] = readU32(nonce, 4); } else if (nonce.length === 12) { this.state[13] = readU32(nonce, 0); this.state[14] = readU32(nonce, 4); this.state[15] = readU32(nonce, 8); } else if (nonce.length === 16) { this.state[12] = readU32(nonce, 0); this.state[13] = readU32(nonce, 4); this.state[14] = readU32(nonce, 8); this.state[15] = readU32(nonce, 12); } else { throw new RangeError('Invalid nonce size.'); } this.pos = 0; return this; } /** * Encrypt/decrypt data. * @param {Buffer} data - Will be mutated. * @returns {Buffer} */ encrypt(data) { assert(Buffer.isBuffer(data)); if (this.pos === -1) throw new Error('Context is not initialized.'); for (let i = 0; i < data.length; i++) { if ((this.pos & 63) === 0) { this._block(); this.pos = 0; } data[i] ^= this.bytes[this.pos++]; } return data; } /** * Stir the stream. */ _block() { for (let i = 0; i < 16; i++) this.stream[i] = this.state[i]; for (let i = 0; i < 10; i++) { 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 i = 0; i < 16; i++) this.stream[i] += this.state[i]; if (BIG_ENDIAN) { for (let i = 0; i < 16; i++) writeU32(this.bytes, this.stream[i], i * 4); } this.state[12] += 1; if (this.state[12] === 0) this.state[13] += 1; } /** * Destroy context. */ destroy() { for (let i = 0; i < 16; i++) { this.state[i] = 0; this.stream[i] = 0; } if (BIG_ENDIAN) { for (let i = 0; i < 64; i++) this.bytes[i] = 0; } this.pos = -1; return this; } /** * Derive key with XChaCha20. * @param {Buffer} key * @param {Buffer} nonce * @returns {Buffer} */ static derive(key, nonce) { assert(Buffer.isBuffer(key)); assert(Buffer.isBuffer(nonce)); if (key.length !== 16 && key.length !== 32) throw new RangeError('Invalid key size.'); if (nonce.length !== 16) throw new RangeError('Invalid nonce size.'); const state = new Uint32Array(16); state[0] = 0x61707865; state[1] = key.length < 32 ? 0x3120646e : 0x3320646e; state[2] = key.length < 32 ? 0x79622d36 : 0x79622d32; state[3] = 0x6b206574; state[4] = readU32(key, 0); state[5] = readU32(key, 4); state[6] = readU32(key, 8); state[7] = readU32(key, 12); state[8] = readU32(key, 16 % key.length); state[9] = readU32(key, 20 % key.length); state[10] = readU32(key, 24 % key.length); state[11] = readU32(key, 28 % key.length); state[12] = readU32(nonce, 0); state[13] = readU32(nonce, 4); state[14] = readU32(nonce, 8); state[15] = readU32(nonce, 12); for (let i = 0; i < 10; i++) { qround(state, 0, 4, 8, 12); qround(state, 1, 5, 9, 13); qround(state, 2, 6, 10, 14); qround(state, 3, 7, 11, 15); qround(state, 0, 5, 10, 15); qround(state, 1, 6, 11, 12); qround(state, 2, 7, 8, 13); qround(state, 3, 4, 9, 14); } const out = Buffer.alloc(32); writeU32(out, state[0], 0); writeU32(out, state[1], 4); writeU32(out, state[2], 8); writeU32(out, state[3], 12); writeU32(out, state[12], 16); writeU32(out, state[13], 20); writeU32(out, state[14], 24); writeU32(out, state[15], 28); return out; } } /* * Static */ ChaCha20.native = 0; /* * 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)); } function readU32(data, off) { return (data[off++] + data[off++] * 0x100 + data[off++] * 0x10000 + data[off] * 0x1000000); } function writeU32(dst, num, off) { dst[off++] = num; num >>>= 8; dst[off++] = num; num >>>= 8; dst[off++] = num; num >>>= 8; dst[off++] = num; return off; } /* * Expose */ module.exports = ChaCha20; }], [/* 39 */ 'bcrypto', '/lib/sha256-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * sha256.js - sha256 for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; module.exports = __node_require__(20 /* './js/sha256' */); }], [/* 40 */ 'bcrypto', '/lib/hmac-drbg-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * hmac-drbg.js - hmac-drbg for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; module.exports = __node_require__(41 /* './js/hmac-drbg' */); }], [/* 41 */ 'bcrypto', '/lib/js/hmac-drbg.js', function(exports, module, __filename, __dirname, __meta) { /*! * hmac-drbg.js - hmac-drbg implementation for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Parts of this software are based on indutny/hmac-drbg: * Copyright Fedor Indutny, 2017. * https://github.com/indutny/hmac-drbg * * Resources: * https://tools.ietf.org/html/rfc6979 * https://csrc.nist.gov/publications/detail/sp/800-90a/archive/2012-01-23 * https://github.com/indutny/hmac-drbg/blob/master/lib/hmac-drbg.js */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); /* * Constants */ const RESEED_INTERVAL = 0x1000000000000; const ZERO = Buffer.from([0x00]); const ONE = Buffer.from([0x01]); /** * HmacDRBG */ class HmacDRBG { constructor(hash, entropy, nonce, pers) { assert(hash && typeof hash.id === 'string'); this.hash = hash; this.minEntropy = hash.id === 'SHA1' ? 10 : 24; this.K = Buffer.alloc(hash.size); this.V = Buffer.alloc(hash.size); this.rounds = 0; if (entropy) this.init(entropy, nonce, pers); } init(entropy, nonce, pers) { if (nonce == null) nonce = Buffer.alloc(0); if (pers == null) pers = Buffer.alloc(0); assert(Buffer.isBuffer(entropy)); assert(Buffer.isBuffer(nonce)); assert(Buffer.isBuffer(pers)); for (let i = 0; i < this.V.length; i++) { this.K[i] = 0x00; this.V[i] = 0x01; } const seed = Buffer.concat([entropy, nonce, pers]); if (seed.length < this.minEntropy) throw new Error('Not enough entropy.'); this.update(seed); this.rounds = 1; return this; } reseed(entropy, add) { if (add == null) add = Buffer.alloc(0); assert(Buffer.isBuffer(entropy)); assert(Buffer.isBuffer(add)); if (this.rounds === 0) throw new Error('DRBG not initialized.'); const seed = Buffer.concat([entropy, add]); if (seed.length < this.minEntropy) throw new Error('Not enough entropy.'); this.update(seed); this.rounds = 1; return this; } generate(len, add) { assert((len >>> 0) === len); assert(add == null || Buffer.isBuffer(add)); if (this.rounds === 0) throw new Error('DRBG not initialized.'); if (this.rounds > RESEED_INTERVAL) throw new Error('Reseed is required.'); if (add && add.length > 0) this.update(add); const blocks = Math.ceil(len / this.hash.size); const out = Buffer.alloc(blocks * this.hash.size); for (let i = 0; i < blocks; i++) { this.V = this.mac(this.V); this.V.copy(out, i * this.hash.size); } this.update(add); this.rounds += 1; return out.slice(0, len); } randomBytes(size) { return this.generate(size); } /* * Helpers */ mac(data) { return this.hash.mac(data, this.K); } hmac() { return this.hash.hmac().init(this.K); } update(seed) { assert(seed == null || Buffer.isBuffer(seed)); const kmac = this.hmac(); kmac.update(this.V); kmac.update(ZERO); if (seed) kmac.update(seed); this.K = kmac.final(); this.V = this.mac(this.V); if (seed && seed.length > 0) { const kmac = this.hmac(); kmac.update(this.V); kmac.update(ONE); kmac.update(seed); this.K = kmac.final(); this.V = this.mac(this.V); } return this; } } /* * Static */ HmacDRBG.native = 0; /* * Expose */ module.exports = HmacDRBG; }], [/* 42 */ 'bcrypto', '/lib/js/elliptic.js', function(exports, module, __filename, __dirname, __meta) { /*! * elliptic.js - elliptic curves for bcrypto * Copyright (c) 2018-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Parts of this software are based on indutny/elliptic: * Copyright (c) 2014, Fedor Indutny (MIT License). * https://github.com/indutny/elliptic * * Formulas from DJB and Tanja Lange [EFD]. * * References: * * [GECC] Guide to Elliptic Curve Cryptography * D. Hankerson, A. Menezes, and S. Vanstone * https://tinyurl.com/guide-to-ecc * * [GLV] Faster Point Multiplication on Elliptic Curves * R. Gallant, R. Lambert, and S. Vanstone * https://link.springer.com/content/pdf/10.1007/3-540-44647-8_11.pdf * * [MONT1] Montgomery curves and the Montgomery ladder * Daniel J. Bernstein, Tanja Lange * https://eprint.iacr.org/2017/293.pdf * * [SQUARED] Elligator Squared * Mehdi Tibouchi * https://eprint.iacr.org/2014/043.pdf * * [SEC1] SEC 1 - Standards for Efficient Cryptography Group * Certicom Research * https://www.secg.org/sec1-v2.pdf * * [SEC2] SEC 2: Recommended Elliptic Curve Domain Parameters * Certicom Research * https://www.secg.org/sec2-v2.pdf * * [SIDE1] Elliptic Curves and Side-Channel Attacks * Marc Joye * https://pdfs.semanticscholar.org/8d69/9645033e25d74fcfd4cbf07a770d2e943e14.pdf * * [BLIND] Side-Channel Analysis on Blinding Regular Scalar Multiplications * B. Feix, M. Roussellet, A. Venelli * https://eprint.iacr.org/2014/191.pdf * * [ALT] Alternative Elliptic Curve Representations * R. Struik * https://tools.ietf.org/id/draft-ietf-lwig-curve-representations-02.html * * [ARITH1] Arithmetic of Elliptic Curves * Christophe Doche, Tanja Lange * Handbook of Elliptic and Hyperelliptic Curve Cryptography * Page 267, Section 13 (978-1-58488-518-4) * https://hyperelliptic.org/HEHCC/index.html * * [ARITH2] The Arithmetic of Elliptic Curves, 2nd Edition * Joseph H. Silverman * http://www.pdmi.ras.ru/~lowdimma/BSD/Silverman-Arithmetic_of_EC.pdf * * [EFD] Explicit-Formulas Database * Daniel J. Bernstein, Tanja Lange * https://hyperelliptic.org/EFD/index.html * * [SAFE] SafeCurves: choosing safe curves for elliptic-curve cryptography * Daniel J. Bernstein * https://safecurves.cr.yp.to/ * * [4GLV] Refinement of the Four-Dimensional GLV Method on Elliptic Curves * Hairong Yi, Yuqing Zhu, and Dongdai Lin * http://www.site.uottawa.ca/~cadams/papers/prepro/paper_19_slides.pdf * * [SSWU1] Efficient Indifferentiable Hashing into Ordinary Elliptic Curves * E. Brier, J. Coron, T. Icart, D. Madore, H. Randriam, M. Tibouchi * https://eprint.iacr.org/2009/340.pdf * * [SSWU2] Rational points on certain hyperelliptic curves over finite fields * Maciej Ulas * https://arxiv.org/abs/0706.1448 * * [H2EC] Hashing to Elliptic Curves * A. Faz-Hernandez, S. Scott, N. Sullivan, R. S. Wahby, C. A. Wood * https://git.io/JeWz6 * https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve * * [SVDW1] Construction of Rational Points on Elliptic Curves * A. Shallue, C. E. van de Woestijne * https://works.bepress.com/andrew_shallue/1/download/ * * [SVDW2] Indifferentiable Hashing to Barreto-Naehrig Curves * Pierre-Alain Fouque, Mehdi Tibouchi * https://www.di.ens.fr/~fouque/pub/latincrypt12.pdf * * [SVDW3] Covert ECDH over secp256k1 * Pieter Wuille * https://gist.github.com/sipa/29118d3fcfac69f9930d57433316c039 * * [MONT2] Montgomery Curve (wikipedia) * https://en.wikipedia.org/wiki/Montgomery_curve * * [MONT3] Montgomery Curves and their arithmetic * C. Costello, B. Smith * https://eprint.iacr.org/2017/212.pdf * * [ELL2] Elliptic-curve points indistinguishable from uniform random strings * D. Bernstein, M. Hamburg, A. Krasnova, T. Lange * https://elligator.cr.yp.to/elligator-20130828.pdf * * [RFC7748] Elliptic Curves for Security * A. Langley, M. Hamburg, S. Turner * https://tools.ietf.org/html/rfc7748 * * [TWISTED] Twisted Edwards Curves * D. Bernstein, P. Birkner, M. Joye, T. Lange, C. Peters * https://eprint.iacr.org/2008/013.pdf * * [ELL1] Injective Encodings to Elliptic Curves * P. Fouque, A. Joux, M. Tibouchi * https://eprint.iacr.org/2013/373.pdf * * [ISOGENY] Twisting Edwards curves with isogenies * Mike Hamburg * https://www.shiftleft.org/papers/isogeny/isogeny.pdf * * [RFC8032] Edwards-Curve Digital Signature Algorithm (EdDSA) * S. Josefsson, SJD AB, I. Liusvaara * https://tools.ietf.org/html/rfc8032 * * [SCHNORR] Schnorr Signatures for secp256k1 * Pieter Wuille * https://github.com/sipa/bips/blob/d194620/bip-schnorr.mediawiki * * [BIP340] Schnorr Signatures for secp256k1 * Pieter Wuille, Jonas Nick, Tim Ruffing * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki * * [JCEN12] Efficient Software Implementation of Public-Key Cryptography * on Sensor Networks Using the MSP430X Microcontroller * C. P. L. Gouvea, L. B. Oliveira, J. Lopez * http://conradoplg.cryptoland.net/files/2010/12/jcen12.pdf * * [FIPS186] Federal Information Processing Standards Publication * National Institute of Standards and Technology * https://tinyurl.com/fips-186-3 * * [RFC5639] Elliptic Curve Cryptography (ECC) Brainpool * Standard Curves and Curve Generation * M. Lochter, BSI, J. Merkle * https://tools.ietf.org/html/rfc5639 * * [TWISTEQ] Twisted Edwards & Short Weierstrass Equivalence * Christopher Jeffrey * https://gist.github.com/chjj/16ba7fa08d64e8dda269a9fe5b2a8bbc * * [ECPM] Elliptic Curve Point Multiplication (wikipedia) * https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication */ 'use strict'; const {custom} = __node_require__(33 /* '../internal/custom' */); const BN = __node_require__(31 /* '../bn' */); /* * Constants */ const types = { AFFINE: 0, JACOBIAN: 1, PROJECTIVE: 2, EXTENDED: 3 }; const jsfIndex = [ -3, // -1 -1 -1, // -1 0 -5, // -1 1 -7, // 0 -1 0, // 0 0 7, // 0 1 5, // 1 -1 1, // 1 0 3 // 1 1 ]; const USE_FIXED = false; let uid = 0; /** * Curve */ class Curve { constructor(Point, type, conf) { this.Point = null; this.id = null; this.uid = uid++; this.ossl = null; this.type = 'base'; this.endian = 'be'; this.hash = null; this.prefix = null; this.context = false; this.prime = null; this.p = null; this.red = null; this.fieldSize = 0; this.fieldBits = 0; this.adjustedSize = 0; this.signBit = 0; this.mask = 0; this.n = null; this.h = null; this.q = null; this.z = null; this.g = null; this.nh = null; this.scalarSize = 0; this.scalarBits = 0; this.zero = null; this.one = null; this.two = null; this.three = null; this.four = null; this.i2 = null; this.i3 = null; this.i4 = null; this.i6 = null; this.torsion = null; this.endo = null; this.hi = null; this._init(Point, type, conf); } _init(Point, type, conf) { assert(typeof Point === 'function'); assert(typeof type === 'string'); assert(conf && typeof conf === 'object'); assert(conf.red == null || (conf.red instanceof BN.Red)); assert(conf.p != null, 'Must pass a prime.'); assert(conf.id == null || typeof conf.id === 'string'); assert(conf.ossl == null || typeof conf.ossl === 'string'); assert(conf.endian == null || typeof conf.endian === 'string'); assert(conf.hash == null || typeof conf.hash === 'string'); assert(conf.prefix == null || typeof conf.prefix === 'string'); assert(conf.context == null || typeof conf.context === 'boolean'); assert(conf.prime == null || typeof conf.prime === 'string'); assert(conf.torsion == null || Array.isArray(conf.torsion)); // Point class. this.Point = Point; // Meta. this.id = conf.id || null; this.ossl = conf.ossl || null; this.type = type; this.endian = conf.endian || (type === 'short' ? 'be' : 'le'); this.hash = conf.hash || null; this.prefix = conf.prefix ? Buffer.from(conf.prefix, 'binary') : null; this.context = conf.context || false; this.prime = conf.prime || null; // Prime. this.p = BN.fromJSON(conf.p); // Reduction. if (conf.red) { this.red = conf.red; } else { // Use Montgomery when there is no fast reduction for the prime. this.red = conf.prime ? BN.red(conf.prime) : BN.mont(this.p); this.red.precompute(); } // Precalculate encoding length. this.fieldSize = this.p.byteLength(); this.fieldBits = this.p.bitLength(); this.adjustedSize = this.fieldSize + ((this.fieldBits & 7) === 0); this.signBit = this.adjustedSize * 8 - 1; this.mask = 0xff; if ((this.fieldBits & 7) !== 0) this.mask = (1 << (this.fieldBits & 7)) - 1; // Curve configuration, optional. this.n = BN.fromJSON(conf.n || '0'); this.h = BN.fromJSON(conf.h || '1'); this.q = this.n.mul(this.h); this.z = BN.fromJSON(conf.z || '0').toRed(this.red); this.g = null; this.nh = this.n.ushrn(1); this.scalarSize = this.n.byteLength(); this.scalarBits = this.n.bitLength(); // Useful for many curves. this.zero = new BN(0).toRed(this.red); this.one = new BN(1).toRed(this.red); this.two = new BN(2).toRed(this.red); this.three = new BN(3).toRed(this.red); this.four = new BN(4).toRed(this.red); // Inverses. this.i2 = this.two.redInvert(); this.i3 = this.three.redInvert(); this.i4 = this.i2.redSqr(); this.i6 = this.i2.redMul(this.i3); // Torsion. this.torsion = new Array(this.h.word(0)); for (let i = 0; i < this.torsion.length; i++) this.torsion[i] = this.point(); // Endomorphism. this.endo = null; // Cache. this.hi = null; // Memoize. this._scale = memoize(this._scale, this); this.isIsomorphic = memoize(this.isIsomorphic, this); this.isIsogenous = memoize(this.isIsogenous, this); // Sanity checks. assert(this.p.sign() > 0 && this.p.isOdd()); assert(this.n.sign() >= 0); assert(this.h.sign() > 0 && this.h.cmpn(255) <= 0); assert(this.endian === 'be' || this.endian === 'le'); return this; } _finalize(conf) { assert(conf && typeof conf === 'object'); // Create base point. this.g = conf.g ? this.pointFromJSON(conf.g) : this.point(); // Parse small order points. if (conf.torsion) { assert(conf.torsion.length === this.torsion.length); for (let i = 0; i < this.torsion.length; i++) this.torsion[i] = this.pointFromJSON(conf.torsion[i]); } return this; } _findTorsion() { // Find all torsion points by grinding. assert(!this.n.isZero()); const h = this.h.word(0); const x = this.one.redNeg(); const out = [this.point()]; const set = new Set(); let len = h; while (out.length < len) { let p; x.redIAdd(this.one); try { p = this.pointFromX(x.clone()); } catch (e) { continue; } try { p = p.mul(this.n); } catch (e) { len = 2; continue; } if (p.isInfinity()) continue; p.normalize(); for (const point of [p, p.neg()]) { const key = point.key(); if (!set.has(key)) { out.push(point); set.add(key); } } } out.sort((a, b) => a.cmp(b)); while (out.length < h) out.push(this.point()); return out; } _fixedMul(p, k) { // Fixed-base method for point multiplication. // // [ECPM] "Windowed method". // [GECC] Page 95, Section 3.3. // // Windows are appropriately shifted to avoid any // doublings. This reduces a 256 bit multiplication // down to 64 additions with a window size of 4. assert(p instanceof Point); assert(k instanceof BN); assert(p.pre && p.pre.windows); // Get precomputed windows. const {width, points} = p._getWindows(0, 0); // Recompute window size. const size = 1 << width; // Recompute steps. const bits = k.bitLength(); const steps = ((bits + width - 1) / width) >>> 0; // Multiply. let acc = this.jpoint(); for (let i = 0; i < steps; i++) { const bits = k.bits(i * width, width); acc = acc.add(points[i * size + bits]); } // Adjust sign. if (k.isNeg()) acc = acc.neg(); return acc; } _fixedNafMul(p, k) { // Fixed-base NAF windowing method for point multiplication. // // [GECC] Algorithm 3.42, Page 105, Section 3.3. assert(p instanceof Point); assert(k instanceof BN); assert(p.pre && p.pre.doubles); // Get precomputed doubles. const {step, points} = p._getDoubles(0, 0); // Get fixed NAF (in a more windowed form). const naf = getFixedNAF(k, 2, k.bitLength() + 1, step); // Compute steps. const I = ((1 << (step + 1)) - (step % 2 === 0 ? 2 : 1)) / 3; // Multiply. let a = this.jpoint(); let b = this.jpoint(); for (let i = I; i > 0; i--) { for (let j = 0; j < naf.length; j++) { const nafW = naf[j]; if (nafW === i) b = b.add(points[j]); else if (nafW === -i) b = b.sub(points[j]); } a = a.add(b); } return a; } _wnafMul(w, p, k) { // Window NAF method for point multiplication. // // [GECC] Algorithm 3.36, Page 100, Section 3.3. assert(p instanceof Point); assert(k instanceof BN); // Precompute window. const {width, points} = p._safeNAF(w); // Get NAF form. const naf = getNAF(k, width, k.bitLength() + 1); // Add `this`*(N+1) for every w-NAF index. let acc = this.jpoint(); for (let i = naf.length - 1; i >= 0; i--) { const z = naf[i]; if (i !== naf.length - 1) acc = acc.dbl(); if (z > 0) acc = acc.add(points[(z - 1) >> 1]); else if (z < 0) acc = acc.sub(points[(-z - 1) >> 1]); } return acc; } _wnafMulAdd(w, points, coeffs) { // Multiple point multiplication, also known // as "Shamir's trick" (with interleaved NAFs). // // [GECC] Algorithm 3.48, Page 109, Section 3.3.3. // Algorithm 3.51, Page 112, Section 3.3. // // This is particularly useful for signature // verifications and mutiplications after an // endomorphism split. assert((w >>> 0) === w); assert(Array.isArray(points)); assert(Array.isArray(coeffs)); assert(points.length === coeffs.length); const length = points.length; const wnd = new Array(length); const naf = new Array(length); // Check arrays and calculate size. let max = 0; for (let i = 0; i < length; i++) { const point = points[i]; const coeff = coeffs[i]; assert(point instanceof Point); assert(coeff instanceof BN); if (i > 0 && point.type !== points[i - 1].type) throw new Error('Cannot mix points.'); // Avoid sparse arrays. wnd[i] = null; naf[i] = null; // Compute max scalar size. max = Math.max(max, coeff.bitLength() + 1); } // Compute NAFs. let ppoint = null; let pcoeff = null; let len = 0; for (let i = 0; i < length; i++) { const point = points[i]; const coeff = coeffs[i]; const pre = point._getNAF(0); // Use precomputation if available. if (pre) { wnd[len] = pre.points; naf[len] = getNAF(coeff, pre.width, max); len += 1; continue; } // Save last non-precomputed point. if (!ppoint) { ppoint = point; pcoeff = coeff; continue; } // Compute JSF in NAF form. wnd[len] = ppoint._getJNAF(point); naf[len] = getJNAF(pcoeff, coeff, max); ppoint = null; pcoeff = null; len += 1; } // Regular NAF for odd points. if (ppoint) { const nafw = ppoint._safeNAF(w); wnd[len] = nafw.points; naf[len] = getNAF(pcoeff, nafw.width, max); len += 1; } // Multiply and add. let acc = this.jpoint(); for (let i = max - 1; i >= 0; i--) { if (i !== max - 1) acc = acc.dbl(); for (let j = 0; j < len; j++) { const z = naf[j][i]; if (z > 0) acc = acc.add(wnd[j][(z - 1) >> 1]); else if (z < 0) acc = acc.sub(wnd[j][(-z - 1) >> 1]); } } return acc; } _endoWnafMulAdd(points, coeffs) { throw new Error('Not implemented.'); } _scale(curve, invert) { assert(curve instanceof Curve); assert(curve.p.eq(this.p)); switch (curve.type) { case 'short': return this._scaleShort(curve, invert); case 'mont': return this._scaleMont(curve, invert); case 'edwards': return this._scaleEdwards(curve, invert); default: throw new Error('Not implemented.'); } } _scaleShort(curve, invert) { throw new Error('Not implemented.'); } _scaleMont(curve, invert) { throw new Error('Not implemented.'); } _scaleEdwards(curve, invert) { throw new Error('Not implemented.'); } isElliptic() { throw new Error('Not implemented.'); } jinv() { throw new Error('Not implemented.'); } isComplete() { return false; } precompute(rng) { assert(!this.g.isInfinity(), 'Must have base point.'); assert(!this.n.isZero(), 'Must have order.'); this.g.precompute(this.n.bitLength(), rng); return this; } scalar(num, base, endian) { const k = new BN(num, base, endian); assert(!k.red); if (this.n.isZero()) return k; return k.imod(this.n); } field(num, base, endian) { const x = BN.cast(num, base, endian); if (x.red) return x.forceRed(this.red); return x.toRed(this.red); } point(x, y) { throw new Error('Not implemented.'); } jpoint(x, y, z) { throw new Error('Not implemented.'); } xpoint(x, z) { throw new Error('Not implemented.'); } cpoint(xx, xz, yy, yz) { assert(xx instanceof BN); assert(xz instanceof BN); assert(yy instanceof BN); assert(yz instanceof BN); if (xz.isZero() || yz.isZero()) return this.point(); const z = xz.redMul(yz).redInvert(); const x = xx.redMul(yz).redMul(z); const y = yy.redMul(xz).redMul(z); return this.point(x, y); } solveX2(y) { throw new Error('Not implemented.'); } solveX(y) { return this.solveX2(y).redSqrt(); } solveY2(x) { throw new Error('Not implemented.'); } solveY(x) { return this.solveY2(x).redSqrt(); } validate(point) { throw new Error('Not implemented.'); } pointFromX(x, sign) { throw new Error('Not implemented.'); } pointFromY(y, sign) { throw new Error('Not implemented.'); } isIsomorphic(curve) { throw new Error('Not implemented.'); } isIsogenous(curve) { throw new Error('Not implemented.'); } pointFromShort(point) { throw new Error('Not implemented.'); } pointFromMont(point, sign) { throw new Error('Not implemented.'); } pointFromEdwards(point) { throw new Error('Not implemented.'); } pointFromUniform(u) { throw new Error('Not implemented.'); } pointToUniform(p) { throw new Error('Not implemented.'); } pointFromHash(bytes, pake = false) { // [H2EC] "Roadmap". assert(Buffer.isBuffer(bytes)); assert(typeof pake === 'boolean'); if (bytes.length !== this.fieldSize * 2) throw new Error('Invalid hash size.'); // Random oracle encoding. // Ensure a proper distribution. const s1 = bytes.slice(0, this.fieldSize); const s2 = bytes.slice(this.fieldSize); const u1 = this.decodeUniform(s1); const u2 = this.decodeUniform(s2); const p1 = this.pointFromUniform(u1); const p2 = this.pointFromUniform(u2); const p3 = p1.add(p2); return pake ? p3.mulH() : p3; } pointToHash(p, subgroup, rng) { // [SQUARED] Algorithm 1, Page 8, Section 3.3. assert(p instanceof this.Point); assert((subgroup >>> 0) === subgroup); // Add a random torsion component. const i = subgroup % this.torsion.length; const p0 = p.add(this.torsion[i]); // Average Cost (R = sqrt): // // SSWU (~4 iterations) => 8I + 16R // SVDW (~4 iterations) => 12I + 28R // Elligator 1 (~2 iterations) => 6I + 10R // Elligator 2 (~2 iterations) => 4I + 6R // Ristretto (~1 iteration) => 1I + 2R + h*1R for (;;) { const u1 = this.randomField(rng); const p1 = this.pointFromUniform(u1); // Avoid 2-torsion points: // Short Weierstrass: ((A / 3) / B, 0) // Montgomery: (0, 0) // Twisted Edwards: (0, -1) if (p1.neg().eq(p1)) continue; const p2 = p0.sub(p1); const hint = randomInt(rng); let u2; try { u2 = this.pointToUniform(p2, hint & 15); } catch (e) { if (e.message === 'Invalid point.') continue; throw e; } const s1 = this.encodeUniform(u1, hint >>> 8); const s2 = this.encodeUniform(u2, hint >>> 16); return Buffer.concat([s1, s2]); } } randomScalar(rng) { const max = this.n.isZero() ? this.p : this.n; return BN.random(rng, 1, max); } randomField(rng) { return BN.random(rng, 1, this.p).toRed(this.red); } randomPoint(rng) { let p; for (;;) { const x = this.randomField(rng); const sign = (randomInt(rng) & 1) !== 0; try { p = this.pointFromX(x, sign); } catch (e) { continue; } assert(p.validate()); return p.mulH(); } } mulAll(points, coeffs) { return this.jmulAll(points, coeffs); } jmulAll(points, coeffs) { assert(Array.isArray(points)); assert(points.length === 0 || (points[0] instanceof Point)); // Multiply with endomorphism if we're using affine points. if (this.endo && points.length > 0 && points[0].type === types.AFFINE) return this._endoWnafMulAdd(points, coeffs); // Otherwise, a regular Shamir's trick. return this._wnafMulAdd(5, points, coeffs); } mulH(k) { assert(k instanceof BN); return this.imulH(k.clone()); } imulH(k) { assert(k instanceof BN); assert(!k.red); const word = this.h.word(0); // Optimize for powers of two. if ((word & (word - 1)) === 0) { const bits = this.h.bitLength(); return k.iushln(bits - 1).imod(this.n); } return k.imuln(word).imod(this.n); } normalizeAll(points) { assert(Array.isArray(points)); const len = points.length; const z = new Array(len); for (let i = 0; i < len; i++) { const p = points[i]; assert(p instanceof Point); assert(p.curve === this); if (p.type === types.AFFINE) { z[i] = this.one; continue; } z[i] = p.z; } const zi = this.red.invertAll(z); const out = new Array(len); for (let i = 0; i < len; i++) out[i] = points[i].scale(zi[i]); return out; } affinizeAll(points) { return this.normalizeAll(points); } clamp(scalar) { // [RFC7748] Page 8, Section 5. // [RFC8032] Section 5.1.5 & 5.2.5. assert(Buffer.isBuffer(scalar)); assert(scalar.length === this.scalarSize); assert(this.scalarSize <= this.fieldSize); let top = (this.fieldBits & 7) || 8; let lsb = 0; let msb = this.scalarSize - 1; // Swap endianness. if (this.endian === 'be') [lsb, msb] = [msb, lsb]; // Adjust for low order. if (this.scalarSize < this.fieldSize) top = 8; // Ensure a multiple of the cofactor. scalar[lsb] &= -this.h.word(0) & 0xff; // Clamp to the prime. scalar[msb] &= (1 << top) - 1; // Set the high bit. scalar[msb] |= 1 << (top - 1); return scalar; } splitHash(bytes) { // [RFC8032] Section 5.1.6 & 5.2.6. assert(Buffer.isBuffer(bytes)); assert(bytes.length === this.adjustedSize * 2); assert(this.scalarSize <= this.adjustedSize); let off = 0; if (this.endian === 'be') off = this.adjustedSize - this.scalarSize; const scalar = bytes.slice(off, off + this.scalarSize); const prefix = bytes.slice(this.adjustedSize); this.clamp(scalar); return [scalar, prefix]; } encodeField(x) { // [SEC1] Page 12, Section 2.3.5. assert(x instanceof BN); assert(!x.red); return x.encode(this.endian, this.fieldSize); } decodeField(bytes) { // [SEC1] Page 13, Section 2.3.6. assert(Buffer.isBuffer(bytes)); if (bytes.length !== this.fieldSize) throw new Error('Invalid field element size.'); return BN.decode(bytes, this.endian); } encodeAdjusted(x) { assert(x instanceof BN); assert(!x.red); return x.encode(this.endian, this.adjustedSize); } decodeAdjusted(bytes) { assert(Buffer.isBuffer(bytes)); if (bytes.length !== this.adjustedSize) throw new Error('Invalid field element size.'); return BN.decode(bytes, this.endian); } encodeScalar(k) { // [SEC1] Page 13, Section 2.3.7. assert(k instanceof BN); assert(!k.red); return k.encode(this.endian, this.scalarSize); } decodeScalar(bytes) { // [SEC1] Page 14, Section 2.3.8. assert(Buffer.isBuffer(bytes)); if (bytes.length !== this.scalarSize) throw new Error('Invalid scalar size.'); return BN.decode(bytes, this.endian); } encodeClamped(k) { // [RFC7748] Page 8, Section 5. // [RFC8032] Section 5.1.5 & 5.2.5. return this.clamp(this.encodeScalar(k)); } decodeClamped(bytes) { // [RFC7748] Page 8, Section 5. // [RFC8032] Section 5.1.5 & 5.2.5. assert(Buffer.isBuffer(bytes)); if (bytes.length !== this.scalarSize) throw new Error('Invalid scalar size.'); const clamped = this.clamp(Buffer.from(bytes)); return BN.decode(clamped, this.endian); } encodeUniform(x, bits) { assert(x instanceof BN); assert((bits >>> 0) === bits); const msb = this.endian === 'le' ? this.fieldSize - 1 : 0; const bytes = x.fromRed().encode(this.endian, this.fieldSize); bytes[msb] |= (bits & ~this.mask) & 0xff; return bytes; } decodeUniform(bytes) { assert(Buffer.isBuffer(bytes)); if (bytes.length !== this.fieldSize) throw new Error('Invalid field size.'); const x = BN.decode(bytes, this.endian); x.iumaskn(this.fieldBits); return x.toRed(this.red); } encodePoint(point, compact) { assert(point instanceof Point); return point.encode(compact); } decodePoint(bytes) { throw new Error('Not implemented.'); } encodeX(point) { throw new Error('Not implemented.'); } decodeX(bytes) { throw new Error('Not implemented.'); } decodeEven(bytes) { throw new Error('Not implemented.'); } decodeSquare(bytes) { throw new Error('Not implemented.'); } toShort() { throw new Error('Not implemented.'); } toMont(b0) { throw new Error('Not implemented.'); } toEdwards(a0) { throw new Error('Not implemented.'); } pointToJSON(point, pre) { assert(point instanceof Point); return point.toJSON(pre); } pointFromJSON(json) { throw new Error('Not implemented.'); } toJSON(pre) { let prefix, context; let n, z, endo; if (this.type === 'edwards') { prefix = this.prefix ? this.prefix.toString() : null; context = this.context; } if (!this.n.isZero()) n = this.n.toJSON(); if (!this.z.isZero()) { z = this.z.fromRed(); if (this.z.redIsHigh()) z.isub(this.p); z = z.toString(16); } if (this.endo) endo = this.endo.toJSON(); return { id: this.id, ossl: this.ossl, type: this.type, endian: this.endian, hash: this.hash, prefix, context, prime: this.prime, p: this.p.toJSON(), a: undefined, b: undefined, d: undefined, n, h: this.h.toString(16), s: undefined, z, c: undefined, g: this.g.toJSON(pre), endo }; } static fromJSON(json) { return new this(json); } } /** * Point */ class Point { constructor(curve, type) { assert(curve instanceof Curve); assert((type >>> 0) === type); this.curve = curve; this.type = type; this.pre = null; } _init() { throw new Error('Not implemented.'); } _safeNAF(width) { assert((width >>> 0) === width); if (this.pre && this.pre.naf) return this.pre.naf; if (width === 0) return null; const size = 1 << (width - 2); const points = new Array(size); const p = this.toJ(); const dbl = size === 1 ? null : p.dbl(); points[0] = p; for (let i = 1; i < size; i++) points[i] = points[i - 1].add(dbl); return new NAF(width, points); } _getNAF(width) { assert((width >>> 0) === width); if (this.pre && this.pre.naf) return this.pre.naf; if (width === 0) return null; const odds = this._safeNAF(width).points; const points = this.curve.affinizeAll(odds); return new NAF(width, points); } _getWindows(width, bits) { assert((width >>> 0) === width); assert((bits >>> 0) === bits); if (this.pre && this.pre.windows) return this.pre.windows; if (width === 0) return null; const size = 1 << width; const steps = ((bits + width - 1) / width) >>> 0; const wnds = new Array(steps * size); let g = this.toJ(); for (let i = 0; i < steps; i++) { wnds[i * size] = this.curve.jpoint(); for (let j = 1; j < size; j++) wnds[i * size + j] = wnds[i * size + j - 1].add(g); g = g.dblp(width); } const points = this.curve.affinizeAll(wnds); return new Windows(width, bits, points); } _getDoubles(step, power) { assert((step >>> 0) === step); assert((power >>> 0) === power); if (this.pre && this.pre.doubles) return this.pre.doubles; if (step === 0) return null; const len = Math.ceil(power / step) + 1; const dbls = new Array(len); let acc = this.toJ(); let k = 0; dbls[k++] = acc; for (let i = 0; i < power; i += step) { for (let j = 0; j < step; j++) acc = acc.dbl(); dbls[k++] = acc; } assert(k === len); const points = this.curve.affinizeAll(dbls); return new Doubles(step, points); } _getBeta() { return null; } _getBlinding(rng) { if (this.pre && this.pre.blinding) return this.pre.blinding; if (!rng) return null; if (this.curve.n.isZero()) return null; // Pregenerate a random blinding value: // // blind = random integer in [1,n-1] // unblind = G * blind // // We intend to subtract the blinding value // from scalars before multiplication. We // can add the unblinding point once the // multiplication is complete. const blind = this.curve.randomScalar(rng); const unblind = this.mul(blind); return new Blinding(blind, unblind); } _hasWindows(k) { assert(k instanceof BN); if (!this.pre || !this.pre.windows) return false; const {width, bits} = this.pre.windows; const steps = ((bits + width - 1) / width) >>> 0; return k.bitLength() <= steps * width; } _hasDoubles(k) { assert(k instanceof BN); if (!this.pre || !this.pre.doubles) return false; const {step, points} = this.pre.doubles; const power = k.bitLength() + 1; return points.length >= Math.ceil(power / step) + 1; } _getJNAF(point) { assert(point instanceof Point); assert(point.type === this.type); // Create comb for JSF. return [ this, // 1 this.add(point), // 3 this.sub(point), // 5 point // 7 ]; } _blind(k, rng) { // [SIDE1] Page 5, Section 4. // [BLIND] Page 20, Section 7. assert(k instanceof BN); assert(!k.red); // Scalar splitting (requires precomputation). // // Blind a multiplication by first subtracting // a blinding value from the scalar. Example: // // b = random integer in [1,n-1] // B = P * b (precomputed) // Q = P * (k - b) + B // // Note that Joye describes a different method // (multiplier randomization) which computes: // // B = random point in E // Q = (P + B) * k - B * k // // Our method is more similar to the "scalar // splitting" technique described in the // second source above. // // The blinding value and its corresponding // point are randomly generated and computed // on boot. As long as an attacker is not // able to observe the boot, this should give // a decent bit of protection against various // channel attacks. if (this.pre && this.pre.blinding) { const {blind, unblind} = this.pre.blinding; const t = k.sub(blind); return [this, t, unblind]; } // Randomization is not possible without // an RNG. Do a normal multiplication. if (!rng) return [this, k, null]; // If we have no precomputed blinding // factor, there are two possibilities // for randomization: // // 1. Randomize the multiplier by adding // a random multiple of `n`. // // 2. Re-scale the point itself by a // random factor. // // The first option can be accomplished // with some like: // // a = random integer in [1,n-1] // r = a * n // Q = P * (k + r) // // The second is accomplished with: // // a = random element in F(p) // R = (x * a^2, y * a^3, z * a) // Q = R * k // // If we have precomputed doubles / naf // points, we opt for the first method // to avoid randomizing everything. if (this.pre) { if (this.curve.n.isZero()) return [this, k, null]; const a = this.curve.randomScalar(rng); const r = a.mul(this.curve.n); const t = r.iadd(k); return [this, t, null]; } // If there is no precomputation _at all_, // we opt for the second method. const p = this.randomize(rng); return [p, k, null]; } clone() { throw new Error('Not implemented.'); } precompute(bits, rng) { assert((bits >>> 0) === bits); if (!this.pre) this.pre = new Precomp(); if (!this.pre.naf) this.pre.naf = this._getNAF(9); if (USE_FIXED && !this.pre.windows) this.pre.windows = this._getWindows(4, bits); if (!this.pre.doubles) this.pre.doubles = this._getDoubles(4, bits + 1); if (!this.pre.beta) this.pre.beta = this._getBeta(); if (!this.pre.blinding) this.pre.blinding = this._getBlinding(rng); return this; } validate() { return this.curve.validate(this); } normalize() { return this; } scale(a) { throw new Error('Not implemented.'); } randomize(rng) { const z = this.curve.randomField(rng); return this.scale(z); } neg() { throw new Error('Not implemented.'); } add(point) { throw new Error('Not implemented.'); } sub(point) { assert(point instanceof Point); return this.add(point.neg()); } dbl() { throw new Error('Not implemented.'); } dblp(pow) { // Repeated doubling. This can // be optimized by child classes. assert((pow >>> 0) === pow); let r = this; for (let i = 0; i < pow; i++) r = r.dbl(); return r; } diffAddDbl(p, q) { throw new Error('Not implemented.'); } getX() { throw new Error('Not implemented.'); } getY() { throw new Error('Not implemented.'); } eq(point) { throw new Error('Not implemented.'); } cmp(point) { throw new Error('Not implemented.'); } isInfinity() { throw new Error('Not implemented.'); } isOrder2() { throw new Error('Not implemented.'); } isOdd() { throw new Error('Not implemented.'); } isEven() { throw new Error('Not implemented.'); } isSquare() { throw new Error('Not implemented.'); } eqX(x) { throw new Error('Not implemented.'); } eqR(x) { throw new Error('Not implemented.'); } isSmall() { // Test whether the point is of small order. if (this.isInfinity()) return false; // P * h = O return this.jmulH().isInfinity(); } hasTorsion() { // Test whether the point is in another subgroup. if (this.isInfinity()) return false; // P * n != O return !this.jmul(this.curve.n).isInfinity(); } order() { // Calculate point order. const {h, n} = this.curve; let p = this.toJ(); let q = new BN(1); while (!p.isInfinity()) { q.iaddn(1); if (q.cmp(h) > 0) { q = n.clone(); break; } p = p.add(this); } return q; } mul(k) { return this.jmul(k); } muln(k) { return this.jmuln(k); } mulBlind(k, rng) { return this.jmulBlind(k, rng); } mulAdd(k1, p2, k2) { return this.jmulAdd(k1, p2, k2); } mulH() { return this.jmulH(); } div(k) { return this.jdiv(k); } divn(k) { return this.jdivn(k); } divH() { return this.jdivH(); } jmul(k) { if (USE_FIXED && this._hasWindows(k)) return this.curve._fixedMul(this, k); if (this._hasDoubles(k)) return this.curve._fixedNafMul(this, k); if (this.curve.endo && this.type === types.AFFINE) return this.curve._endoWnafMulAdd([this], [k]); return this.curve._wnafMul(5, this, k); } jmuln(k) { assert((k | 0) === k); return this.jmul(new BN(k)); } jmulBlind(k, rng = null) { const [p, t, unblind] = this._blind(k, rng); const q = p.jmul(t); if (unblind) return q.add(unblind); return q; } jmulAdd(k1, p2, k2) { if (this.curve.endo && this.type === types.AFFINE) return this.curve._endoWnafMulAdd([this, p2], [k1, k2]); return this.curve._wnafMulAdd(5, [this, p2], [k1, k2]); } jmulH() { const word = this.curve.h.word(0); // Optimize for powers of two. if ((word & (word - 1)) === 0) { const bits = this.curve.h.bitLength(); return this.toJ().dblp(bits - 1); } return this.jmul(this.curve.h); } jdiv(k) { assert(k instanceof BN); assert(!k.red); return this.jmul(k.invert(this.curve.n)); } jdivn(k) { assert(!this.curve.n.isZero()); if (this.curve.h.cmpn(k) === 0) return this.jdivH(); return this.jdiv(new BN(k)); } jdivH() { if (this.curve.n.isZero()) return this.toJ(); if (this.curve.h.cmpn(1) === 0) return this.toJ(); if (this.curve.hi === null) this.curve.hi = this.curve.h.invert(this.curve.n); return this.jmul(this.curve.hi); } toP() { return this.normalize(); } toJ() { return this; } toX() { return this; } key() { if (this.isInfinity()) return `${this.curve.uid}:oo`; this.normalize(); const x = this.getX().toString(16); const y = this.getY().toString(16); return `${this.curve.uid}:${x},${y}`; } encode(compact) { throw new Error('Not implemented.'); } static decode(curve, bytes) { throw new Error('Not implemented.'); } encodeX() { throw new Error('Not implemented.'); } static decodeX(curve, bytes) { throw new Error('Not implemented.'); } static decodeEven(curve, bytes) { throw new Error('Not implemented.'); } static decodeSquare(curve, bytes) { throw new Error('Not implemented.'); } toJSON(pre) { throw new Error('Not implemented.'); } static fromJSON(curve, json) { throw new Error('Not implemented.'); } [custom]() { return ''; } } /** * ShortCurve */ class ShortCurve extends Curve { constructor(conf) { super(ShortPoint, 'short', conf); this.a = BN.fromJSON(conf.a).toRed(this.red); this.b = BN.fromJSON(conf.b).toRed(this.red); this.c = BN.fromJSON(conf.c || '0').toRed(this.red); this.ai = this.a.isZero() ? this.zero : this.a.redInvert(); this.zi = this.z.isZero() ? this.zero : this.z.redInvert(); this.zeroA = this.a.isZero(); this.threeA = this.a.eq(this.three.redNeg()); this.redN = this.n.toRed(this.red); this.pmodn = this.p.clone(); this.highOrder = this.n.cmp(this.p) >= 0; this.smallGap = false; this._finalize(conf); } _finalize(conf) { super._finalize(conf); // Precalculate endomorphism. if (conf.endo != null) this.endo = Endo.fromJSON(this, conf.endo); else this.endo = this._getEndomorphism(); if (!this.n.isZero()) { this.pmodn = this.p.mod(this.n); // Check for Maxwell's trick (see eqR). this.smallGap = this.p.div(this.n).cmpn(1) <= 0; } return this; } static _isomorphism(curveA, curveB, custom, odd) { // Short Weierstrass Isomorphism. // // [GECC] Page 84, Section 3.1.5. // [ARITH1] Page 274, Section 13.1.5. // [ALT] Appendix F.3 (Isomorphic Mapping between Weierstrass Curves). // // Find `u` such that `a * u^4 = a'` and `b * u^6 = b'`. // // Transformation: // // u4 = a' / a // u2 = +-sqrt(u4) // u6 = u4 * u2 // a' = a * u4 // b' = b * u6 // // Where `u2` is any root that is square. // // If a = 0, we can do: // // a' = 0 // b' = b' // // Where (b' / b)^(1 / 3) is square. // // If b = 0, we can do: // // a' = a' // b' = 0 // // Where sqrt(a' / a) is square. assert(curveA instanceof BN); assert(curveB instanceof BN); assert(custom instanceof BN); assert(odd == null || typeof odd === 'boolean'); assert(!curveA.isZero() || !curveB.isZero()); if (custom.isZero()) throw new Error('Invalid coefficient.'); if (curveA.isZero()) { const customB = custom; const u6 = customB.redDiv(curveB); // Todo: allow index flag. const u2 = uncube(u6); // Already checked in uncube(). assert(u2.redJacobi() === 1); return [curveA.clone(), customB.clone()]; } if (curveB.isZero()) { const customA = custom; const u4 = customA.redDiv(curveA); const u2 = u4.redSqrt(); // Todo: allow odd flag. if (u2.redJacobi() !== 1) u2.redINeg(); if (u2.redJacobi() !== 1) throw new Error('Invalid `a` coefficient.'); return [customA.clone(), curveB.clone()]; } const customA = custom; const u4 = customA.redDiv(curveA); const u2 = u4.redSqrt(); if (odd != null) { if (u2.redIsOdd() !== odd) u2.redINeg(); } else { if (u2.redJacobi() !== 1) u2.redINeg(); } if (u2.redJacobi() !== 1) throw new Error('Invalid `a` coefficient.'); const u6 = u4.redMul(u2); const a = curveA.redMul(u4); const b = curveB.redMul(u6); assert(a.eq(customA)); return [a, b]; } _short(a0, odd) { return ShortCurve._isomorphism(this.a, this.b, a0, odd); } _mont(b0, odd) { // Short Weierstrass->Montgomery Equivalence. // // [ARITH1] Page 286, Section 13.2.3.c. // [SAFE] "Ladders". // // Transformation: // // r = A / (3 * B) // s = +-sqrt(3 * r^2 + a) // A = 3 * r / s // B = 1 / s const [r, s] = this._findRS(odd); const b = s.redInvert(); const a = r.redMuln(3).redMul(b); if (b0 != null) return MontCurve._isomorphism(a, b, b0); return [a, b]; } _edwards(a0, odd) { // Short Weierstrass->Twisted Edwards Equivalence. // // [TWISTEQ] Section 1. // // Transformation: // // r = (a' + d') / 6 // s = +-sqrt(3 * r^2 + a) // a' = 3 * r + 2 * s // d' = 3 * r - 2 * s const [r, s] = this._findRS(odd); const r3 = r.redMuln(3); const s2 = s.redMuln(2); const a = r3.redAdd(s2); const d = r3.redSub(s2); if (a0 != null) return EdwardsCurve._isomorphism(a, d, a0); return [a, d]; } _findRS(sign) { // Find `r` and `s` for equivalence. // // [ARITH1] Page 286, Section 13.2.3.c. // [SAFE] "Ladders". // // Computation: // // r = solve(r^3 + a * r + b == 0, r) // s = +-sqrt(3 * r^2 + a) // // Computing `r` is non-trivial. We need // to solve `r^3 + a * r + b = 0`, but we // don't have a polynomial solver, so we // loop over random points until we find // one with 2-torsion. Multiplying by the // subgroup order should yield a point of // ((A / 3) / B, 0) which is a solution. assert(sign == null || typeof sign === 'boolean'); assert(this.h.word(0) >= 4); assert(!this.n.isZero()); const x = this.one.redNeg(); let p; for (;;) { x.redIAdd(this.one); try { p = this.pointFromX(x.clone()); } catch (e) { continue; } p = p.mul(this.n); if (p.isInfinity()) continue; if (!p.y.isZero()) continue; break; } const r = p.x; const r2 = r.redSqr(); const s = r2.redMuln(3).redIAdd(this.a).redSqrt(); if (sign != null) { if (s.redIsOdd() !== sign) s.redINeg(); } return [r, s]; } _scale0(a, b) { // We can extract the isomorphism factors with: // // u4 = a' / a // u6 = b' / b // u2 = +-sqrt(u4) // u = +-sqrt(u2) // u3 = u2 * u // // `u2` should be picked such that `u4 * u2 = u6`. // // If a = 0, we can do: // // u6 = b' / b // u2 = u6^(1 / 3) // u = +-sqrt(u2) // u3 = u2 * u // // Where `u2` is any root that is square. // // If b = 0, we can do: // // u4 = a' / a // u2 = +-sqrt(u4) // u = +-sqrt(u2) // u3 = u2 * u // // Where `u2` is any root that is square. assert(this.a.isZero() === a.isZero()); assert(this.b.isZero() === b.isZero()); if (this.a.isZero()) { const u6 = this.b.redDiv(this.field(b)); // Todo: figure out how to check index. const u2 = uncube(u6); const u = u2.redSqrt(); const u3 = u2.redMul(u); assert(u3.redSqr().eq(u6)); assert(!u.isZero()); return [u2, u3]; } if (this.b.isZero()) { const u4 = this.a.redDiv(this.field(a)); const u2 = u4.redSqrt(); // Todo: figure out how to check oddness. if (u2.redJacobi() !== 1) u2.redINeg(); const u = u2.redSqrt(); const u3 = u2.redMul(u); assert(u3.redMul(u).eq(u4)); assert(!u.isZero()); return [u2, u3]; } const u4 = this.a.redDiv(this.field(a)); const u6 = this.b.redDiv(this.field(b)); const u2 = u4.redSqrt(); if (!u4.redMul(u2).eq(u6)) u2.redINeg(); assert(u4.redMul(u2).eq(u6)); const u = u2.redSqrt(); const u3 = u2.redMul(u); assert(!u.isZero()); return [u2, u3]; } _scale1(x, y) { // If base points are available, it is much // easier, with: // // u2 = x' / x // u3 = y' / y // u = +-sqrt(u2) // // `u` should be picked such that `u2 * u = u3`. const u2 = this.g.x.redDiv(this.field(x)); const u3 = this.g.y.redDiv(this.field(y)); const u = u2.redSqrt(); if (!u2.redMul(u).eq(u3)) u.redINeg(); assert(u2.redMul(u).eq(u3)); assert(!u.isZero()); return [u2, u3]; } _scaleShort(curve) { assert(curve instanceof ShortCurve); if (this.g.isInfinity() || curve.g.isInfinity()) return this._scale0(curve.a, curve.b); return this._scale1(curve.g.x, curve.g.y); } _scaleMont(curve) { assert(curve instanceof MontCurve); if (this.g.isInfinity() || curve.g.isInfinity()) { const [a, b] = curve._short(); return this._scale0(a, b); } const {x, y} = curve.g; const nx = x.redAdd(curve.a3).redMul(curve.bi); const ny = y.redMul(curve.bi); return this._scale1(nx, ny); } _scaleEdwards(curve) { assert(curve instanceof EdwardsCurve); if (this.g.isInfinity() || curve.g.isInfinity()) { const [a, b] = curve._short(); return this._scale0(a, b); } const {x, y, z} = curve.g; const a5 = curve.a.redMuln(5); const d5 = curve.d.redMuln(5); const dma = curve.d.redSub(curve.a); const d5a = d5.redSub(curve.a); const da5 = curve.d.redSub(a5); const ypz = y.redAdd(z); const ymz = y.redSub(z); const xx = d5a.redMul(y).redIAdd(da5.redMul(z)); const xz = ymz.redMuln(12); const yy = dma.redMul(ypz).redMul(z); const yz = ymz.redMul(x).redIMuln(4); const zi = xz.redMul(yz).redInvert(); const nx = xx.redMul(yz).redMul(zi); const ny = yy.redMul(xz).redMul(zi); return this._scale1(nx, ny); } _getEndomorphism(index = 0) { // Compute endomorphism. // // [GECC] Example 3.76, Page 128, Section 3.5. // No curve params. if (this.n.isZero() || this.g.isInfinity()) return null; // No efficient endomorphism. if (!this.zeroA || this.p.modrn(3) !== 1 || this.n.modrn(3) !== 1) return null; // Solve beta^3 mod p = 1. const [b1, b2] = this._getEndoRoots(this.p); // Choose the smallest beta by default. const beta = [b1, b2][index & 1].toRed(this.red); // Solve lambda^3 mod n = 1. const [l1, l2] = this._getEndoRoots(this.n); // Choose the lambda matching selected beta. // Note that P * lambda = (x * beta, y). const p = this.point(this.g.x.redMul(beta), this.g.y); let lambda; if (this.g.mul(l1).eq(p)) { lambda = l1; } else { assert(this.g.mul(l2).eq(p)); lambda = l2; } // Get basis vectors. const basis = this._getEndoBasis(lambda); // Precompute `g1` and `g2`. const pre = this._getEndoPrecomp(basis); return new Endo(beta, lambda, basis, pre); } _getEndoRoots(num) { // Find roots for x^2 + x + 1 in F. // // [GECC] Example 3.76, Page 128, Section 3.5. // [GLV] Page 192, Section 2 (Endomorphisms). // // The above document doesn't fully explain how // to derive these and only "hints" at it, as // mentioned by Hal Finney[1], but we're basically // computing two possible cube roots of 1 here. // // Note that we could also compute[2]: // // beta = 2^((p - 1) / 3) mod p // lambda = 3^((n - 1) / 3) mod n // // As an extension of Fermat's little theorem: // // g^(p - 1) mod p == 1 // // It is suspected[3] this is how Hal Finney[4] // computed his original endomorphism roots. // // @indutny's method for computing cube roots // of unity[5] appears to be the method described // on wikipedia[6][7]. // // Sage produces the same solution: // // sage: solve(x^2 + x + 1 == 0, x) // [x == -1/2*I*sqrt(3) - 1/2, x == 1/2*I*sqrt(3) - 1/2] // // This can be reduced to: // // x = (+-sqrt(-3) - 1) / 2 // // [1] https://bitcointalk.org/index.php?topic=3238.msg45565#msg45565 // [2] https://crypto.stackexchange.com/a/22739 // [3] https://bitcoin.stackexchange.com/a/35872 // [4] https://github.com/halfinney/bitcoin/commit/dc411b5 // [5] https://en.wikipedia.org/wiki/Cube_root_of_unity // [6] https://en.wikipedia.org/wiki/Splitting_field#Cubic_example // [7] http://mathworld.wolfram.com/SplittingField.html const red = num === this.p ? this.red : BN.mont(num); const two = new BN(2).toRed(red); const three = new BN(3).toRed(red); const i2 = two.redInvert(); // S1 = sqrt(-3) / 2 const s1 = three.redNeg().redSqrt().redMul(i2); // S2 = -S1 const s2 = s1.redNeg(); // R1 = S1 - 1 / 2 const r1 = s1.redSub(i2).fromRed(); // R2 = S2 - 1 / 2 const r2 = s2.redSub(i2).fromRed(); return [r1, r2].sort(BN.cmp); } _getEndoBasis(lambda) { // Compute endomorphic basis. // // This essentially computes Cornacchia's algorithm // for solving x^2 + d * y^2 = m (d = lambda, m = order). // // https://en.wikipedia.org/wiki/Cornacchia%27s_algorithm // // [GECC] Algorithm 3.74, Page 127, Section 3.5. // [GLV] Page 196, Section 4 (Decomposing K). // // Balanced length-two representation of a multiplier. // // 1. Run the extended euclidean algorithm with inputs n // and lambda. The algorithm produces a sequence of // equations si*n + ti*lam = ri where s0=1, t0=0, // r0=n, s1=0, t1=1, r1=lam, and the remainders ri // and are non-negative and strictly decreasing. Let // l be the greatest index for which rl >= sqrt(n). const [rl, tl, rl1, tl1, rl2, tl2] = this._egcdSqrt(lambda); // 2. Set (a1, b1) <- (rl+1, -tl+1). const a1 = rl1; const b1 = tl1.neg(); // 3. If (rl^2 + tl^2) <= (rl+2^2 + tl+2^2) // then set (a2, b2) <- (rl, -tl). // else set (a2, b2) <- (rl+2, -tl+2). const lhs = rl.sqr().iadd(tl.sqr()); const rhs = rl2.sqr().iadd(tl2.sqr()); let a2, b2; if (lhs.cmp(rhs) <= 0) { a2 = rl; b2 = tl.neg(); } else { a2 = rl2; b2 = tl2.neg(); } return [ new Vector(a1, b1), new Vector(a2, b2) ]; } _egcdSqrt(lambda) { // Extended Euclidean algorithm for integers. // // [GECC] Algorithm 2.19, Page 40, Section 2.2. // [GLV] Page 196, Section 4 (Decomposing K). assert(lambda instanceof BN); assert(!lambda.red); assert(lambda.sign() > 0); assert(this.n.sign() > 0); // Note that we insert the approximate square // root checks as described in algorithm 3.74. // // Algorithm 2.19 is defined as: // // 1. u <- a // v <- b // // 2. x1 <- 1 // y1 <- 0 // x2 <- 0 // y2 <- 1 // // 3. while u != 0 do // // 3.1. q <- floor(v / u) // r <- v - q * u // x <- x2 - q * x1 // y <- y2 - q * y1 // // 3.2. v <- u // u <- r // x2 <- x1 // x1 <- x // y2 <- y1 // y1 <- y // // 4. d <- v // x <- x2 // y <- y2 // // 5. Return (d, x, y). // Start with an approximate square root of n. const sqrtn = this.n.ushrn(this.n.bitLength() >>> 1); let u = lambda; // r1 let v = this.n.clone(); // r0 let x1 = new BN(1); // t1 let y1 = new BN(0); // t0 let x2 = new BN(0); // s1 let y2 = new BN(1); // s0 // All vectors are roots of: a + b * lambda = 0 (mod n). let rl, tl; // First vector. let rl1, tl1; // Inner. let i = 0; let j = 0; let p; // Compute EGCD. while (!u.isZero() && i < 2) { const q = v.quo(u); const r = v.sub(q.mul(u)); const x = x2.sub(q.mul(x1)); const y = y2.sub(q.mul(y1)); // Check for r < sqrt(n). if (j === 0 && r.cmp(sqrtn) < 0) { rl = p; tl = x1; rl1 = r; tl1 = x; j = 1; // 1 more round. } p = r; v = u; u = r; x2 = x1; x1 = x; y2 = y1; y1 = y; i += j; } // Should never happen. assert(j !== 0, 'Could not find r < sqrt(n).'); // Second vector. const rl2 = x2; const tl2 = x1; return [ rl, tl, rl1, tl1, rl2, tl2 ]; } _getEndoPrecomp(basis) { // Precompute `g1` and `g2` to avoid round division. // // [JCEN12] Page 5, Section 4.3. // // Computation: // // d = a1 * b2 - b1 * a2 // t = ceil(log2(d+1)) + p // g1 = round((2^t * b2) / d) // g2 = round((2^t * b1) / d) // // Where: // // `p` is the number of precision bits. // `d` is equal to `n` (the curve order). // // The paper above uses 2 as the value of `p`, // whereas libsecp256k1 uses 128 (total=384). // // We pick precision for `g1` and `g2` such that: // // abs(g1) < n // abs(g2) < n // // This ensures maximum precision for the constants // while also ensuring they fit into a fixed number // of scalar limbs in more optimized implementations. // // Furthermore, we attempt to align to a limb width // of 64 bits. This allows us to optimize the shift, // a la libsecp256k1[1]. // // [1] https://github.com/bitcoin-core/secp256k1/pull/822 assert(Array.isArray(basis)); assert(basis.length === 2); assert(basis[0] instanceof Vector); assert(basis[1] instanceof Vector); const [v1, v2] = basis; const d = v1.a.mul(v2.b).isub(v1.b.mul(v2.a)); const bits = d.bitLength(); const align = bits >= 160; assert(d.eq(this.n)); // Start with a rough estimate. let shift = bits + Math.ceil(bits / 2) + 1; let g1, g2; if (align) shift -= shift & 63; while (shift > bits) { g1 = v2.b.ushln(shift).divRound(d); g2 = v1.b.ushln(shift).divRound(d); if (g1.ucmp(d) < 0 && g2.ucmp(d) < 0) break; if (align) shift -= 64; else shift -= 1; } if (shift <= bits) throw new Error('Could not calculate g1 and g2.'); return [shift, g1, g2]; } _endoSplit(k) { // Balanced length-two representation of a multiplier. // // [GECC] Algorithm 3.74, Page 127, Section 3.5. // // Also note that it is possible to precompute[1] // values in order to avoid the division[2][3][4]. // // This involves precomputing `g1` and `g2 (see // above). `c1` and `c2` can then be computed as // follows: // // t = ceil(log2(n+1)) + p // c1 = (k * g1) >> t // c2 = -((k * g2) >> t) // // Where `>>` is an _unsigned_ right shift. Also // note that the last bit discarded in the shift // must be stored. If it is 1, then add 1 to the // scalar (absolute addition). // // It's worth noting that libsecp256k1 uses a // different calculation along the lines of: // // t = ceil(log2(n+1)) + p // c1 = ((k * g1) >> t) * -b1 // c2 = ((k * -g2) >> t) * -b2 // k2 = c1 + c2 // k1 = k2 * -lambda + k // // So, in the future, we can consider changing // step 4 to: // // 4. Compute c1 = (k * g1) >> t // and c2 = -((k * g2) >> t). // // const [shift, g1, g2] = this.endo.pre; // const c1 = k.mulShift(g1, shift); // const c2 = k.mulShift(g2, shift).ineg(); // // Once we're brave enough, that is. // // [1] [JCEN12] Page 5, Section 4.3. // [2] https://github.com/bitcoin-core/secp256k1/blob/0b70241/src/scalar_impl.h#L259 // [3] https://github.com/bitcoin-core/secp256k1/pull/21 // [4] https://github.com/bitcoin-core/secp256k1/pull/127 assert(k instanceof BN); assert(!k.red); assert(!this.n.isZero()); const [v1, v2] = this.endo.basis; // 4. Compute c1 = round(b2 * k / n) // and c2 = round(-b1 * k / n). const c1 = v2.b.mul(k).divRound(this.n); const c2 = v1.b.neg().mul(k).divRound(this.n); // 5. Compute k1 = k - c1 * a1 - c2 * a2 // and k2 = -c1 * b1 - c2 * b2. const p1 = c1.mul(v1.a); const p2 = c2.mul(v2.a); const q1 = c1.ineg().mul(v1.b); const q2 = c2.mul(v2.b); // Calculate answer. const k1 = k.sub(p1).isub(p2); const k2 = q1.isub(q2); // 6. Return (k1, k2). return [k1, k2]; } _endoBeta(point) { assert(point instanceof ShortPoint); return [point, point._getBeta()]; } _endoWnafMulAdd(points, coeffs) { // Point multiplication with efficiently computable endomorphisms. // // [GECC] Algorithm 3.77, Page 129, Section 3.5. // [GLV] Page 193, Section 3 (Using Efficient Endomorphisms). // // Note it may be possible to do this 4-dimensionally [4GLV]. assert(Array.isArray(points)); assert(Array.isArray(coeffs)); assert(points.length === coeffs.length); assert(this.endo != null); const len = points.length; const npoints = new Array(len * 2); const ncoeffs = new Array(len * 2); for (let i = 0; i < len; i++) { const [p1, p2] = this._endoBeta(points[i]); const [k1, k2] = this._endoSplit(coeffs[i]); npoints[i * 2 + 0] = p1; ncoeffs[i * 2 + 0] = k1; npoints[i * 2 + 1] = p2; ncoeffs[i * 2 + 1] = k2; } return this._wnafMulAdd(5, npoints, ncoeffs); } _sswu(u) { // Simplified Shallue-Woestijne-Ulas Method. // // Distribution: 3/8. // // [SSWU1] Page 15-16, Section 7. Appendix G. // [SSWU2] Page 5, Theorem 2.3. // [H2EC] "Simplified Shallue-van de Woestijne-Ulas Method". // // Assumptions: // // - a != 0, b != 0. // - Let z be a non-square in F(p). // - z != -1. // - The polynomial g(x) - z is irreducible over F(p). // - g(b / (z * a)) is square in F(p). // - u != 0, u != +-sqrt(-1 / z). // // Map: // // g(x) = x^3 + a * x + b // t1 = 1 / (z^2 * u^4 + z * u^2) // x1 = (-b / a) * (1 + t1) // x1 = b / (z * a), if t1 = 0 // x2 = z * u^2 * x1 // x = x1, if g(x1) is square // = x2, otherwise // y = sign(u) * abs(sqrt(g(x))) const {b, z, ai, zi, one} = this; const z2 = z.redSqr(); const ba = b.redNeg().redMul(ai); const bza = b.redMul(zi).redMul(ai); const u2 = u.redSqr(); const u4 = u2.redSqr(); const t0 = z2.redMul(u4).redIAdd(z.redMul(u2)); const t1 = t0.isZero() ? t0 : t0.redInvert(); const x1 = t1.isZero() ? bza : ba.redMul(one.redAdd(t1)); const x2 = z.redMul(u2).redMul(x1); const y1 = this.solveY2(x1); const y2 = this.solveY2(x2); const alpha = y1.redIsSquare() | 0; const x = [x1, x2][alpha ^ 1]; const y = [y1, y2][alpha ^ 1].redSqrt(); if (y.redIsOdd() !== u.redIsOdd()) y.redINeg(); return this.point(x, y); } _sswui(p, hint) { // Inverting the Map (Simplified Shallue-Woestijne-Ulas). // // Assumptions: // // - a^2 * x^2 - 2 * a * b * x - 3 * b^2 is square in F(p). // - If r < 3 then x != -b / a. // // Unlike SVDW, the preimages here are evenly // distributed (more or less). SSWU covers ~3/8 // of the curve points. Each preimage has a 1/2 // chance of mapping to either x1 or x2. // // Assuming the point is within that set, each // point has a 1/4 chance of inverting to any // of the preimages. This means we can simply // randomly select a preimage if one exists. // // However, the [SVDW2] sampling method seems // slighly faster in practice for [SQUARED]. // // Map: // // c = sqrt(a^2 * x^2 - 2 * a * b * x - 3 * b^2) // u1 = -(a * x + b - c) / (2 * (a * x + b) * z) // u2 = -(a * x + b + c) / (2 * (a * x + b) * z) // u3 = -(a * x + b - c) / (2 * b * z) // u4 = -(a * x + b + c) / (2 * b * z) // r = random integer in [1,4] // u = sign(y) * abs(sqrt(ur)) const {a, b, z} = this; const {x, y} = p; const r = hint & 3; const a2x2 = a.redSqr().redMul(x.redSqr()); const abx2 = a.redMul(b).redMul(x).redIMuln(2); const b23 = b.redSqr().redMuln(3); const axb = a.redMul(x).redIAdd(b); const c = a2x2.redISub(abx2).redISub(b23).redSqrt(); const n0 = axb.redSub(c).redINeg(); const n1 = axb.redAdd(c).redINeg(); const d0 = axb.redMul(z).redIMuln(2); const d1 = b.redMul(z).redIMuln(2); const n = [n0, n1][r & 1]; // r = 1 or 3 const d = [d0, d1][r >>> 1]; // r = 2 or 3 const u = n.redDivSqrt(d); if (u.redIsOdd() !== y.redIsOdd()) u.redINeg(); return u; } _svdwf(u) { // Shallue-van de Woestijne Method. // // Distribution: 9/16. // // [SVDW1] Section 5. // [SVDW2] Page 8, Section 3. // Page 15, Section 6, Algorithm 1. // [H2EC] "Shallue-van de Woestijne Method". // // Assumptions: // // - p = 1 (mod 3). // - a = 0, b != 0. // - Let z be a unique element in F(p). // - g((sqrt(-3 * z^2) - z) / 2) is square in F(p). // - u != 0, u != +-sqrt(-g(z)). // // Map: // // g(x) = x^3 + b // c = sqrt(-3 * z^2) // t1 = u^2 + g(z) // t2 = 1 / (u^2 * t1) // t3 = u^4 * t2 * c // x1 = (c - z) / 2 - t3 // x2 = t3 - (c + z) / 2 // x3 = z - t1^3 * t2 / (3 * z^2) // x = x1, if g(x1) is square // = x2, if g(x2) is square // = x3, otherwise // y = sign(u) * abs(sqrt(g(x))) const {c, z, zi, i2, i3} = this; const gz = this.solveY2(z); const z3 = i3.redMul(zi.redSqr()); const u2 = u.redSqr(); const u4 = u2.redSqr(); const t1 = u2.redAdd(gz); const u2t1 = u2.redMul(t1); const t2 = u2t1.isZero() ? u2t1 : u2t1.redInvert(); const t3 = u4.redMul(t2).redMul(c); const t4 = t1.redSqr().redMul(t1); const x1 = c.redSub(z).redMul(i2).redISub(t3); const x2 = t3.redSub(c.redAdd(z).redMul(i2)); const x3 = z.redSub(t4.redMul(t2).redMul(z3)); const y1 = this.solveY2(x1); const y2 = this.solveY2(x2); const y3 = this.solveY2(x3); const alpha = y1.redJacobi() | 1; const beta = y2.redJacobi() | 1; const i = mod((alpha - 1) * beta, 3); const x = [x1, x2, x3][i]; const y = [y1, y2, y3][i]; return [x, y]; } _svdw(u) { const [x, yy] = this._svdwf(u); const y = yy.redSqrt(); if (y.redIsOdd() !== u.redIsOdd()) y.redINeg(); return this.point(x, y); } _svdwi(p, hint) { // Inverting the Map (Shallue-van de Woestijne). // // [SQUARED] Algorithm 1, Page 8, Section 3.3. // [SVDW2] Page 12, Section 5. // [SVDW3] "Inverting the map". // // Assumptions: // // - If r = 1 then x != -(c + z) / 2. // - If r = 2 then x != (c - z) / 2. // - If r > 2 then (t0 - t1 + t2) is square in F(p). // - f(f^-1(x)) = x where f is the map function. // // We use the sampling method from [SVDW2], // _not_ [SQUARED]. This seems to have a // better distribution in practice. // // Note that [SVDW3] also appears to be // incorrect in terms of distribution. // // The distribution of f(u), assuming u is // random, is (1/2, 1/4, 1/4). // // To mirror this, f^-1(x) should simply // pick (1/2, 1/4, 1/8, 1/8). // // To anyone running the forward map, our // strings will appear to be random. // // Map: // // g(x) = x^3 + b // c = sqrt(-3 * z^2) // t0 = 9 * (x^2 * z^2 + z^4) // t1 = 18 * x * z^3 // t2 = 12 * g(z) * (x - z) // t3 = sqrt(t0 - t1 + t2) // t4 = t3 * z // u1 = g(z) * (c - 2 * x - z) / (c + 2 * x + z) // u2 = g(z) * (c + 2 * x + z) / (c - 2 * x - z) // u3 = (3 * (z^3 - x * z^2) - 2 * g(z) + t4) / 2 // u4 = (3 * (z^3 - x * z^2) - 2 * g(z) - t4) / 2 // r = random integer in [1,4] // u = sign(y) * abs(sqrt(ur)) const {b, c, z, zero, two} = this; const {x, y} = p; const r = hint & 3; const z2 = z.redSqr(); const z3 = z2.redMul(z); const z4 = z2.redSqr(); const gz = z3.redAdd(b); const gz2 = gz.redMuln(2); const xx = x.redSqr(); const x2z = x.redMuln(2).redIAdd(z); const xz2 = x.redMul(z2); const c0 = c.redSub(x2z); const c1 = c.redAdd(x2z); const t0 = xx.redMul(z2).redIAdd(z4).redIMuln(9); const t1 = x.redMul(z3).redIMuln(18); const t2 = gz.redMul(x.redSub(z)).redIMuln(12); const t3 = r >= 2 ? t0.redISub(t1).redIAdd(t2).redSqrt() : zero; const t4 = t3.redMul(z); const t5 = z3.redISub(xz2).redIMuln(3).redISub(gz2); const n0 = gz.redMul(c0); const n1 = gz.redMul(c1); const n2 = t5.redAdd(t4); const n3 = t5.redSub(t4); const d2 = two; const n = [n0, n1, n2, n3][r]; const d = [c1, c0, d2, d2][r]; const u = n.redDivSqrt(d); const [x0] = this._svdwf(u); if (!x0.eq(x)) throw new Error('Invalid point.'); if (u.redIsOdd() !== y.redIsOdd()) u.redINeg(); return u; } isElliptic() { const {a, b} = this; const a2 = a.redSqr(); const a3 = a2.redMul(a); const b2 = b.redSqr(); const d = b2.redMuln(27).redIAdd(a3.redMuln(4)); // 4 * a^3 + 27 * b^2 != 0 return !d.isZero(); } jinv() { // [ARITH1] Page 71, Section 4.4. // http://mathworld.wolfram.com/j-Invariant.html const {a, b} = this; const a2 = a.redSqr(); const a3 = a2.redMul(a); const b2 = b.redSqr(); const t0 = a3.redMuln(4); const lhs = t0.redMuln(1728); const rhs = b2.redMuln(27).redIAdd(t0); if (rhs.isZero()) throw new Error('Curve is not elliptic.'); // (1728 * 4 * a^3) / (4 * a^3 + 27 * b^2) return lhs.redDiv(rhs).fromRed(); } point(x, y) { return new ShortPoint(this, x, y); } jpoint(x, y, z) { return new JPoint(this, x, y, z); } solveX(y) { assert(y instanceof BN); if (!this.a.isZero()) throw new Error('Not implemented.'); // x^3 = y^2 - b const y2 = y.redSqr(); const x3 = y2.redSub(this.b); return cubeRoots(x3); } solveY2(x) { // [GECC] Page 89, Section 3.2.2. // https://hyperelliptic.org/EFD/g1p/auto-shortw.html assert(x instanceof BN); // y^2 = x^3 + a * x + b const x3 = x.redSqr().redMul(x); const y2 = x3.redIAdd(this.b); if (!this.zeroA) { // Save some cycles for a = -3. if (this.threeA) y2.redIAdd(x.redMuln(-3)); else y2.redIAdd(this.a.redMul(x)); } return y2; } validate(point) { assert(point instanceof ShortPoint); if (point.inf) return true; const {x, y} = point; const y2 = this.solveY2(x); return y.redSqr().eq(y2); } pointFromX(x, sign = null) { assert(x instanceof BN); assert(sign == null || typeof sign === 'boolean'); if (!x.red) x = x.toRed(this.red); const y = this.solveY(x); if (sign != null) { if (this.h.cmpn(1) > 0) { if (y.isZero() && sign) throw new Error('Invalid point.'); } if (y.redIsOdd() !== sign) y.redINeg(); } return this.point(x, y); } pointFromY(y, index = 0) { assert(y instanceof BN); assert((index >>> 0) === index); if (!y.red) y = y.toRed(this.red); const coords = this.solveX(y); if (index >= coords.length) throw new Error('Invalid X coordinate index.'); const x = coords[index]; return this.point(x, y); } isIsomorphic(curve) { // [GECC] Page 84, Section 3.1.5. // [ARITH1] Page 286, Section 13.2.3.c. assert(curve instanceof Curve); if (!curve.p.eq(this.p)) return false; let u2, u3; try { [u2, u3] = this._scale(curve); } catch (e) { return false; } // E(a,b) <-> E(au^4,bu^6) if (curve.type === 'short') { // a' = a * u^4, b' = b * u^6 const a = this.field(curve.a).redMul(u2.redSqr()); const b = this.field(curve.b).redMul(u3.redSqr()); return this.a.eq(a) && this.b.eq(b); } // E(a,b) <-> M(A,B) if (curve.type === 'mont') { // (A / (3 * B))^3 + a * (A / (3 * B)) + b = 0 const {a3, bi} = curve; const x = this.field(a3.redMul(bi)).redMul(u2); const y2 = this.solveY2(x); return y2.isZero(); } // E(a,b) <-> E(a,d) if (curve.type === 'edwards') { // ((a' + d') / 6)^3 + a * ((a' + d') / 6) + b = 0 const x = this.field(curve.ad6).redMul(u2); const y2 = this.solveY2(x); return y2.isZero(); } return false; } isIsogenous(curve) { assert(curve instanceof Curve); return false; } pointFromShort(point) { // [GECC] Page 84, Section 3.1.5. // [ALT] Appendix F.3 (Isomorphic Mapping between Weierstrass Curves). assert(point instanceof ShortPoint); if (this.isIsomorphic(point.curve)) { // Isomorphic maps for E(a,b)<->E(au^4,bu^6): // // x' = x * u^2 // y' = y * u^3 // // Where a * u^4 = a' and b * u^6 = b'. if (point.isInfinity()) return this.point(); const [u2, u3] = this._scale(point.curve); const x = this.field(point.x); const y = this.field(point.y); const nx = x.redMul(u2); const ny = y.redMul(u3); return this.point(nx, ny); } throw new Error('Not implemented.'); } pointFromMont(point) { // [ALT] Appendix E.2 (Switching between Alternative Representations). // [MONT2] "Equivalence with Weierstrass curves" assert(point instanceof MontPoint); if (this.isIsomorphic(point.curve)) { // Equivalence for M(A,B)->E(a,b): // // x = (u + A / 3) / B // y = v / B // // Undefined if ((u^3 + A * u^2 + u) / B) is not square. if (point.isInfinity()) return this.point(); const {a3, bi} = point.curve; const [u2, u3] = this._scale(point.curve); const nx = point.x.redAdd(a3).redMul(bi); const ny = point.y.redMul(bi); return this.point(this.field(nx).redMul(u2), this.field(ny).redMul(u3)); } throw new Error('Not implemented.'); } pointFromEdwards(point) { // [TWISTEQ] Section 2. assert(point instanceof EdwardsPoint); if (this.isIsomorphic(point.curve)) { // Equivalence for E(a,d)->E(a',b'): // // x' = ((5 * d - a) * y + d - 5 * a) / (12 * (y - 1)) // y' = (d - a) * (y + 1) / (4 * x * (y - 1)) // // Undefined for x = 0 or y = 1. // // Exceptional Cases: // - (0, 1) -> O // - (0, -1) -> ((a + d) / 6, 0) // // Unexceptional Cases: // - (sqrt(1 / a), 0) -> ((5 * a - d) / 12, (a - d) / 4 * sqrt(a)) const {a, d, ad6} = point.curve; const [u2, u3] = this._scale(point.curve); if (point.isInfinity()) return this.point(); if (point.x.isZero()) { const x = this.field(ad6).redMul(u2); return this.point(x, this.zero); } const {x, y, z} = point; const a5 = a.redMuln(5); const d5 = d.redMuln(5); const dma = d.redSub(a); const d5a = d5.redSub(a); const da5 = d.redSub(a5); const ypz = y.redAdd(z); const ymz = y.redSub(z); const xx = d5a.redMul(y).redIAdd(da5.redMul(z)); const xz = ymz.redMuln(12); const yy = dma.redMul(ypz).redMul(z); const yz = ymz.redMul(x).redIMuln(4); return this.cpoint(this.field(xx).redMul(u2), this.field(xz), this.field(yy).redMul(u3), this.field(yz)); } throw new Error('Not implemented.'); } pointFromUniform(u) { assert(u instanceof BN); // z = 0 or b = 0 if (this.z.isZero() || this.b.isZero()) throw new Error('Not implemented.'); // a != 0, b != 0 if (!this.a.isZero()) return this._sswu(u); // p = 1 mod 3, a = 0, b != 0 if (!this.c.isZero()) return this._svdw(u); throw new Error('Not implemented.'); } pointToUniform(p, hint) { // Convert a short weierstrass point to a field // element by inverting either the SSWU or SVDW // map. // // Hint Layout: // // [00000000] [0000] [0000] // | | | // | | +-- preimage index // | +--- subgroup // +-- bits to OR with uniform bytes assert(p instanceof ShortPoint); assert((hint >>> 0) === hint); // z = 0 or b = 0 if (this.z.isZero() || this.b.isZero()) throw new Error('Not implemented.'); // P = O if (p.isInfinity()) throw new Error('Invalid point.'); // Add a random torsion component. const i = ((hint >>> 4) & 15) % this.torsion.length; const q = p.add(this.torsion[i]); return wrapErrors(() => { // a != 0, b != 0 if (!this.a.isZero()) return this._sswui(q, hint); // p = 1 mod 3, a = 0, b != 0 if (!this.c.isZero()) return this._svdwi(q, hint); throw new Error('Not implemented.'); }); } mulAll(points, coeffs) { return super.mulAll(points, coeffs).toP(); } affinizeAll(points) { const out = this.normalizeAll(points); for (let i = 0; i < out.length; i++) out[i] = out[i].toP(); return out; } decodePoint(bytes) { return ShortPoint.decode(this, bytes); } encodeX(point) { assert(point instanceof Point); return point.encodeX(); } decodeEven(bytes) { return ShortPoint.decodeEven(this, bytes); } decodeSquare(bytes) { return ShortPoint.decodeSquare(this, bytes); } toShort(a0, odd, sign = null) { const [a, b] = this._short(a0, odd); const curve = new ShortCurve({ red: this.red, prime: this.prime, p: this.p, a: a, b: b, n: this.n, h: this.h }); if (sign != null) { const [, u3] = curve._scale(this); if (u3.redIsOdd() !== sign) u3.redINeg(); } if (!this.g.isInfinity()) curve.g = curve.pointFromShort(this.g); for (let i = 0; i < this.h.word(0); i++) curve.torsion[i] = curve.pointFromShort(this.torsion[i]); return curve; } toMont(b0, odd, sign = null) { const [a, b] = this._mont(b0, odd); const curve = new MontCurve({ red: this.red, prime: this.prime, p: this.p, a: a, b: b, n: this.n, h: this.h }); if (sign != null) { const [, u3] = this._scale(curve); if (u3.redIsOdd() !== sign) u3.redINeg(); } if (!this.g.isInfinity()) curve.g = curve.pointFromShort(this.g); for (let i = 0; i < this.h.word(0); i++) curve.torsion[i] = curve.pointFromShort(this.torsion[i]); return curve; } toEdwards(a0, odd, sign = null) { const [a, d] = this._edwards(a0, odd); const curve = new EdwardsCurve({ red: this.red, prime: this.prime, p: this.p, a: a, d: d, n: this.n, h: this.h }); if (sign != null) { const [, u3] = this._scale(curve); if (u3.redIsOdd() !== sign) u3.redINeg(); } if (!this.g.isInfinity()) { curve.g = curve.pointFromShort(this.g); curve.g.normalize(); } if (curve.isComplete()) { for (let i = 0; i < this.h.word(0); i++) { curve.torsion[i] = curve.pointFromShort(this.torsion[i]); curve.torsion[i].normalize(); } } return curve; } pointFromJSON(json) { return ShortPoint.fromJSON(this, json); } toJSON(pre) { const json = super.toJSON(pre); json.a = this.a.fromRed().toJSON(); json.b = this.b.fromRed().toJSON(); if (!this.c.isZero()) json.c = this.c.fromRed().toJSON(); return json; } } /** * ShortPoint */ class ShortPoint extends Point { constructor(curve, x, y) { assert(curve instanceof ShortCurve); super(curve, types.AFFINE); this.x = this.curve.zero; this.y = this.curve.zero; this.inf = true; if (x != null) this._init(x, y); } _init(x, y) { assert(x instanceof BN); assert(y instanceof BN); this.x = x; this.y = y; if (!this.x.red) this.x = this.x.toRed(this.curve.red); if (!this.y.red) this.y = this.y.toRed(this.curve.red); this.inf = false; } _getBeta() { if (!this.curve.endo) return null; if (this.pre && this.pre.beta) return this.pre.beta; // Augment the point with our beta value. // This is the counterpart to `k2` after // the endomorphism split of `k`. // // Note that if we have precomputation, // we have to clone and update all of the // precomputed points below. const xb = this.x.redMul(this.curve.endo.beta); const beta = this.curve.point(xb, this.y); if (this.pre) { beta.pre = this.pre.map((point) => { const xb = point.x.redMul(this.curve.endo.beta); return this.curve.point(xb, point.y); }); this.pre.beta = beta; } return beta; } _getJNAF(point) { assert(point instanceof ShortPoint); if (this.inf || point.inf) return super._getJNAF(point); // Create comb for JSF. const comb = [ this, // 1 null, // 3 null, // 5 point // 7 ]; // Try to avoid Jacobian points, if possible. if (this.y.eq(point.y)) { comb[1] = this.add(point); comb[2] = this.toJ().sub(point); } else if (this.y.eq(point.y.redNeg())) { comb[1] = this.toJ().add(point); comb[2] = this.sub(point); } else { comb[1] = this.toJ().add(point); comb[2] = this.toJ().sub(point); } return comb; } clone() { if (this.inf) return this.curve.point(); return this.curve.point(this.x, this.y); } scale(a) { return this.toJ().scale(a); } neg() { // P = O if (this.inf) return this; // -(X1, Y1) = (X1, -Y1) return this.curve.point(this.x, this.y.redNeg()); } add(p) { // [GECC] Page 80, Section 3.1.2. // // Addition Law: // // l = (y1 - y2) / (x1 - x2) // x3 = l^2 - x1 - x2 // y3 = l * (x1 - x3) - y1 // // 1I + 2M + 1S + 6A assert(p instanceof ShortPoint); // O + P = P if (this.inf) return p; // P + O = P if (p.inf) return this; // P + P, P + -P if (this.x.eq(p.x)) { // P + -P = O if (!this.y.eq(p.y)) return this.curve.point(); // P + P = 2P return this.dbl(); } // X1 != X2, Y1 = Y2 if (this.y.eq(p.y)) { // X3 = -X1 - X2 const nx = this.x.redNeg().redISub(p.x); // Y3 = -Y1 const ny = this.y.redNeg(); // Skip the inverse. return this.curve.point(nx, ny); } // H = X1 - X2 const h = this.x.redSub(p.x); // R = Y1 - Y2 const r = this.y.redSub(p.y); // L = R / H const l = r.redDiv(h); // X3 = L^2 - X1 - X2 const nx = l.redSqr().redISub(this.x).redISub(p.x); // Y3 = L * (X1 - X3) - Y1 const ny = l.redMul(this.x.redSub(nx)).redISub(this.y); return this.curve.point(nx, ny); } dbl() { // [GECC] Page 80, Section 3.1.2. // // Addition Law (doubling): // // l = (3 * x1^2 + a) / (2 * y1) // x3 = l^2 - 2 * x1 // y3 = l * (x1 - x3) - y1 // // 1I + 2M + 2S + 3A + 2*2 + 1*3 // P = O if (this.inf) return this; // Y1 = 0 if (this.y.isZero()) return this.curve.point(); // XX = X1^2 const xx = this.x.redSqr(); // M = 3 * XX + a const m = xx.redIMuln(3).redIAdd(this.curve.a); // Z = 2 * Y1 const z = this.y.redMuln(2); // L = M / Z const l = m.redDiv(z); // X3 = L^2 - 2 * X1 const nx = l.redSqr().redISub(this.x).redISub(this.x); // Y3 = L * (X1 - X3) - Y1 const ny = l.redMul(this.x.redSub(nx)).redISub(this.y); return this.curve.point(nx, ny); } dblp(pow) { return this.toJ().dblp(pow).toP(); } getX() { if (this.inf) throw new Error('Invalid point.'); return this.x.fromRed(); } getY() { if (this.inf) throw new Error('Invalid point.'); return this.y.fromRed(); } eq(p) { assert(p instanceof ShortPoint); // P = Q if (this === p) return true; // P = O if (this.inf) return p.inf; // Q = O if (p.inf) return false; // X1 = X2, Y1 = Y2 return this.x.eq(p.x) && this.y.eq(p.y); } cmp(point) { assert(point instanceof ShortPoint); if (this.inf && !point.inf) return -1; if (!this.inf && point.inf) return 1; if (this.inf && point.inf) return 0; return this.order().cmp(point.order()) || this.getX().cmp(point.getX()) || this.getY().cmp(point.getY()); } isInfinity() { // Infinity cannot be represented in // the affine space, except by a flag. return this.inf; } isOrder2() { if (this.inf) return false; return this.y.isZero(); } isOdd() { if (this.inf) return false; return this.y.redIsOdd(); } isEven() { if (this.inf) return false; return this.y.redIsEven(); } isSquare() { if (this.inf) return false; return this.y.redJacobi() !== -1; } eqX(x) { assert(x instanceof BN); assert(!x.red); if (this.inf) return false; return this.getX().eq(x); } eqR(x) { assert(x instanceof BN); assert(!x.red); assert(!this.curve.n.isZero()); if (this.inf) return false; return this.getX().imod(this.curve.n).eq(x); } mul(k) { return super.mul(k).toP(); } muln(k) { return super.muln(k).toP(); } mulBlind(k, rng) { return super.mulBlind(k, rng).toP(); } mulAdd(k1, p2, k2) { return super.mulAdd(k1, p2, k2).toP(); } mulH() { return super.mulH().toP(); } div(k) { return super.div(k).toP(); } divn(k) { return super.divn(k).toP(); } divH() { return super.divH().toP(); } toP() { return this; } toJ() { // (X3, Y3, Z3) = (1, 1, 0) if (this.inf) return this.curve.jpoint(); // (X3, Y3, Z3) = (X1, Y1, 1) return this.curve.jpoint(this.x, this.y, this.curve.one); } encode(compact) { // [SEC1] Page 10, Section 2.3.3. if (compact == null) compact = true; assert(typeof compact === 'boolean'); const {fieldSize} = this.curve; // We do not serialize points at infinity. if (this.inf) throw new Error('Invalid point.'); // Compressed form (0x02 = even, 0x03 = odd). if (compact) { const p = Buffer.alloc(1 + fieldSize); const x = this.curve.encodeField(this.getX()); p[0] = 0x02 | this.y.redIsOdd(); x.copy(p, 1); return p; } // Uncompressed form (0x04). const p = Buffer.alloc(1 + fieldSize * 2); const x = this.curve.encodeField(this.getX()); const y = this.curve.encodeField(this.getY()); p[0] = 0x04; x.copy(p, 1); y.copy(p, 1 + fieldSize); return p; } static decode(curve, bytes) { // [SEC1] Page 11, Section 2.3.4. assert(curve instanceof ShortCurve); assert(Buffer.isBuffer(bytes)); const len = curve.fieldSize; if (bytes.length < 1 + len) throw new Error('Not a point.'); // Point forms: // // 0x00 -> Infinity (openssl, unsupported) // 0x02 -> Compressed Even // 0x03 -> Compressed Odd // 0x04 -> Uncompressed // 0x06 -> Hybrid Even (openssl) // 0x07 -> Hybrid Odd (openssl) // // Note that openssl supports serializing points // at infinity as {0}. We choose not to support it // because it's strange and not terribly useful. const form = bytes[0]; switch (form) { case 0x02: case 0x03: { if (bytes.length !== 1 + len) throw new Error('Invalid point size for compressed.'); const x = curve.decodeField(bytes.slice(1, 1 + len)); if (x.cmp(curve.p) >= 0) throw new Error('Invalid point.'); const p = curve.pointFromX(x, form === 0x03); assert(!p.isInfinity()); return p; } case 0x04: case 0x06: case 0x07: { if (bytes.length !== 1 + len * 2) throw new Error('Invalid point size for uncompressed.'); const x = curve.decodeField(bytes.slice(1, 1 + len)); const y = curve.decodeField(bytes.slice(1 + len, 1 + 2 * len)); // [GECC] Algorithm 4.3, Page 180, Section 4. if (x.cmp(curve.p) >= 0 || y.cmp(curve.p) >= 0) throw new Error('Invalid point.'); // OpenSSL hybrid encoding. if (form !== 0x04 && form !== (0x06 | y.isOdd())) throw new Error('Invalid hybrid encoding.'); const p = curve.point(x, y); if (!p.validate()) throw new Error('Invalid point.'); assert(!p.isInfinity()); return p; } default: { throw new Error('Unknown point format.'); } } } encodeX() { // [SCHNORR] "Specification". // [BIP340] "Specification". return this.curve.encodeField(this.getX()); } static decodeEven(curve, bytes) { // [BIP340] "Specification". assert(curve instanceof ShortCurve); const x = curve.decodeField(bytes); if (x.cmp(curve.p) >= 0) throw new Error('Invalid point.'); return curve.pointFromX(x, false); } static decodeSquare(curve, bytes) { // [SCHNORR] "Specification". assert(curve instanceof ShortCurve); const x = curve.decodeField(bytes); if (x.cmp(curve.p) >= 0) throw new Error('Invalid point.'); return curve.pointFromX(x); } toJSON(pre) { if (this.inf) return []; const x = this.getX().toJSON(); const y = this.getY().toJSON(); if (pre === true && this.pre) return [x, y, this.pre.toJSON()]; return [x, y]; } toPretty() { if (this.inf) return []; const size = this.curve.fieldSize * 2; const x = toPretty(this.getX(), size); const y = toPretty(this.getY(), size); return [x, y]; } static fromJSON(curve, json) { assert(curve instanceof ShortCurve); assert(Array.isArray(json)); assert(json.length === 0 || json.length === 2 || json.length === 3); if (json.length === 0) return curve.point(); const x = BN.fromJSON(json[0]); const y = BN.fromJSON(json[1]); const point = curve.point(x, y); if (json.length > 2 && json[2] != null) point.pre = Precomp.fromJSON(point, json[2]); return point; } [custom]() { if (this.inf) return ''; return ''; } } /** * JPoint */ class JPoint extends Point { constructor(curve, x, y, z) { assert(curve instanceof ShortCurve); super(curve, types.JACOBIAN); this.x = this.curve.one; this.y = this.curve.one; this.z = this.curve.zero; this.zOne = false; if (x != null) this._init(x, y, z); } _init(x, y, z) { assert(x instanceof BN); assert(y instanceof BN); assert(z == null || (z instanceof BN)); this.x = x; this.y = y; this.z = z || this.curve.one; if (!this.x.red) this.x = this.x.toRed(this.curve.red); if (!this.y.red) this.y = this.y.toRed(this.curve.red); if (!this.z.red) this.z = this.z.toRed(this.curve.red); this.zOne = this.z.eq(this.curve.one); } clone() { return this.curve.jpoint(this.x, this.y, this.z); } validate() { // [GECC] Example 3.20, Page 88, Section 3. const {a, b} = this.curve; // P = O if (this.isInfinity()) return true; // Z1 = 1 if (this.zOne) return this.curve.validate(this.toP()); // y^2 = x^3 + a * x * z^4 + b * z^6 const lhs = this.y.redSqr(); const x3 = this.x.redSqr().redMul(this.x); const z2 = this.z.redSqr(); const z4 = z2.redSqr(); const z6 = z4.redMul(z2); const rhs = x3.redIAdd(b.redMul(z6)); if (!this.curve.zeroA) { // Save some cycles for a = -3. if (this.curve.threeA) rhs.redIAdd(z4.redIMuln(-3).redMul(this.x)); else rhs.redIAdd(a.redMul(z4).redMul(this.x)); } return lhs.eq(rhs); } normalize() { // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#scaling-z // 1I + 3M + 1S // Z = 1 if (this.zOne) return this; // P = O if (this.isInfinity()) return this; // A = 1 / Z1 const a = this.z.redInvert(); // AA = A^2 const aa = a.redSqr(); // X3 = X1 * AA this.x = this.x.redMul(aa); // Y3 = Y1 * AA * A this.y = this.y.redMul(aa).redMul(a); // Z3 = 1 this.z = this.curve.one; this.zOne = true; return this; } scale(a) { assert(a instanceof BN); // P = O if (this.isInfinity()) return this.curve.jpoint(); // AA = A^2 const aa = a.redSqr(); // X3 = X1 * AA const nx = this.x.redMul(aa); // Y3 = Y1 * AA * A const ny = this.y.redMul(aa).redMul(a); // Z3 = Z1 * A const nz = this.z.redMul(a); return this.curve.jpoint(nx, ny, nz); } neg() { // -(X1, Y1, Z1) = (X1, -Y1, Z1) return this.curve.jpoint(this.x, this.y.redNeg(), this.z); } add(p) { assert(p instanceof Point); if (p.type === types.AFFINE) return this._mixedAdd(p); return this._add(p); } _add(p) { assert(p instanceof JPoint); // O + P = P if (this.isInfinity()) return p; // P + O = P if (p.isInfinity()) return this; // Z1 = 1 if (this.zOne) return p._addJA(this); // Z2 = 1 if (p.zOne) return this._addJA(p); return this._addJJ(p); } _mixedAdd(p) { assert(p instanceof ShortPoint); // O + P = P if (this.isInfinity()) return p.toJ(); // P + O = P if (p.isInfinity()) return this; return this._addJA(p); } _addJJ(p) { // No assumptions. // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-add-1998-cmo-2 // 12M + 4S + 6A + 1*2 (implemented as: 12M + 4S + 7A) // Z1Z1 = Z1^2 const z1z1 = this.z.redSqr(); // Z2Z2 = Z2^2 const z2z2 = p.z.redSqr(); // U1 = X1 * Z2Z2 const u1 = this.x.redMul(z2z2); // U2 = X2 * Z1Z1 const u2 = p.x.redMul(z1z1); // S1 = Y1 * Z2 * Z2Z2 const s1 = this.y.redMul(p.z).redMul(z2z2); // S2 = Y2 * Z1 * Z1Z1 const s2 = p.y.redMul(this.z).redMul(z1z1); // H = U2 - U1 const h = u2.redISub(u1); // r = S2 - S1 const r = s2.redISub(s1); // H = 0 if (h.isZero()) { if (!r.isZero()) return this.curve.jpoint(); return this.dbl(); } // HH = H^2 const hh = h.redSqr(); // HHH = H * HH const hhh = h.redMul(hh); // V = U1 * HH const v = u1.redMul(hh); // X3 = r^2 - HHH - 2 * V const nx = r.redSqr().redISub(hhh).redISub(v).redISub(v); // Y3 = r * (V - X3) - S1 * HHH const ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(hhh)); // Z3 = Z1 * Z2 * H const nz = this.z.redMul(p.z).redMul(h); return this.curve.jpoint(nx, ny, nz); } _addJA(p) { // Assumes Z2 = 1. // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-madd // 8M + 3S + 6A + 5*2 (implemented as: 8M + 3S + 7A + 4*2) // Z1Z1 = Z1^2 const z1z1 = this.z.redSqr(); // U2 = X2 * Z1Z1 const u2 = p.x.redMul(z1z1); // S2 = Y2 * Z1 * Z1Z1 const s2 = p.y.redMul(this.z).redMul(z1z1); // H = U2 - X1 const h = u2.redISub(this.x); // r = 2 * (S2 - Y1) const r = s2.redISub(this.y).redIMuln(2); // H = 0 if (h.isZero()) { if (!r.isZero()) return this.curve.jpoint(); return this.dbl(); } // I = (2 * H)^2 const i = h.redMuln(2).redSqr(); // J = H * I const j = h.redMul(i); // V = X1 * I const v = this.x.redMul(i); // X3 = r^2 - J - 2 * V const nx = r.redSqr().redISub(j).redISub(v).redISub(v); // Y3 = r * (V - X3) - 2 * Y1 * J const ny = r.redMul(v.redISub(nx)).redISub(this.y.redMul(j).redIMuln(2)); // Z3 = 2 * Z1 * H const nz = this.z.redMul(h).redIMuln(2); return this.curve.jpoint(nx, ny, nz); } dbl() { // P = O if (this.isInfinity()) return this; // Y1 = 0 if (this.y.isZero()) return this.curve.jpoint(); // a = 0 if (this.curve.zeroA) return this._dbl0(); // a = -3 if (this.curve.threeA) return this._dbl3(); return this._dblJ(); } _dblJ() { // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 // 3M + 6S + 4A + 1*a + 2*2 + 1*3 + 1*4 + 1*8 // (implemented as: 3M + 6S + 5A + 1*a + 1*2 + 1*3 + 1*4 + 1*8) // XX = X1^2 const xx = this.x.redSqr(); // YY = Y1^2 const yy = this.y.redSqr(); // ZZ = Z1^2 const zz = this.z.redSqr(); // S = 4 * X1 * YY const s = this.x.redMul(yy).redIMuln(4); // M = 3 * XX + a * ZZ^2 const m = xx.redIMuln(3).redIAdd(this.curve.a.redMul(zz.redSqr())); // T = M^2 - 2 * S const t = m.redSqr().redISub(s).redISub(s); // X3 = T const nx = t; // Y3 = M * (S - T) - 8 * YY^2 const ny = m.redMul(s.redISub(t)).redISub(yy.redSqr().redIMuln(8)); // Z3 = 2 * Y1 * Z1 const nz = this.y.redMul(this.z).redIMuln(2); return this.curve.jpoint(nx, ny, nz); } _dbl0() { // Assumes a = 0. // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l // 2M + 5S + 6A + 3*2 + 1*3 + 1*8 // (implemented as: 2M + 5S + 7A + 2*2 + 1*3 + 1*8) // A = X1^2 const a = this.x.redSqr(); // B = Y1^2 const b = this.y.redSqr(); // C = B^2 const c = b.redSqr(); // + XB2 = (X1 + B)^2 const xb2 = b.redIAdd(this.x).redSqr(); // D = 2 * ((X1 + B)^2 - A - C) const d = xb2.redISub(a).redISub(c).redIMuln(2); // E = 3 * A const e = a.redIMuln(3); // F = E^2 const f = e.redSqr(); // X3 = F - 2 * D const nx = f.redISub(d).redISub(d); // Y3 = E * (D - X3) - 8 * C const ny = e.redMul(d.redISub(nx)).redISub(c.redIMuln(8)); // Z3 = 2 * Y1 * Z1 const nz = this.y.redMul(this.z).redIMuln(2); return this.curve.jpoint(nx, ny, nz); } _dbl3() { // Assumes a = -3. // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b // 3M + 5S + 8A + 1*3 + 1*4 + 2*8 // (implemented as: 3M + 5S + 8A + 1*2 + 1*3 + 1*4 + 1*8) // delta = Z1^2 const delta = this.z.redSqr(); // gamma = Y1^2 const gamma = this.y.redSqr(); // beta = X1 * gamma const beta = this.x.redMul(gamma); // + xmdelta = X1 - delta const xmdelta = this.x.redSub(delta); // + xpdelta = X1 + delta const xpdelta = this.x.redAdd(delta); // alpha = 3 * (X1 - delta) * (X1 + delta) const alpha = xmdelta.redMul(xpdelta).redIMuln(3); // + beta4 = 4 * beta const beta4 = beta.redIMuln(4); // + beta8 = 2 * beta4 const beta8 = beta4.redMuln(2); // + gamma28 = 8 * gamma^2 const gamma28 = gamma.redSqr().redIMuln(8); // X3 = alpha^2 - 8 * beta const nx = alpha.redSqr().redISub(beta8); // Z3 = (Y1 + Z1)^2 - gamma - delta const nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 const ny = alpha.redMul(beta4.redISub(nx)).redISub(gamma28); return this.curve.jpoint(nx, ny, nz); } getX() { if (this.isInfinity()) throw new Error('Invalid point.'); this.normalize(); return this.x.fromRed(); } getY() { if (this.isInfinity()) throw new Error('Invalid point.'); this.normalize(); return this.y.fromRed(); } eq(p) { assert(p instanceof JPoint); // P = Q if (this === p) return true; // P = O if (this.isInfinity()) return p.isInfinity(); // Q = O if (p.isInfinity()) return false; // Z1 = Z2 if (this.z.eq(p.z)) { return this.x.eq(p.x) && this.y.eq(p.y); } // X1 * Z2^2 = X2 * Z1^2 const zz1 = this.z.redSqr(); const zz2 = p.z.redSqr(); const x1 = this.x.redMul(zz2); const x2 = p.x.redMul(zz1); if (!x1.eq(x2)) return false; // Y1 * Z2^3 = Y2 * Z1^3 const zzz1 = zz1.redMul(this.z); const zzz2 = zz2.redMul(p.z); const y1 = this.y.redMul(zzz2); const y2 = p.y.redMul(zzz1); return y1.eq(y2); } cmp(point) { assert(point instanceof JPoint); const inf1 = this.isInfinity(); const inf2 = point.isInfinity(); if (inf1 && !inf2) return -1; if (!inf1 && inf2) return 1; if (inf1 && inf2) return 0; return this.order().cmp(point.order()) || this.getX().cmp(point.getX()) || this.getY().cmp(point.getY()); } isInfinity() { // Z1 = 0 return this.z.isZero(); } isOrder2() { if (this.isInfinity()) return false; return this.y.isZero(); } isOdd() { if (this.isInfinity()) return false; this.normalize(); return this.y.redIsOdd(); } isEven() { if (this.isInfinity()) return false; this.normalize(); return this.y.redIsEven(); } isSquare() { if (this.isInfinity()) return false; return this.y.redMul(this.z).redJacobi() !== -1; } eqX(x) { // Verify that integer `x` is equal to field // element `x` by scaling it by our z coordinate. // This optimization is mentioned in and used for // bip-schnorr[1]. This avoids having to affinize // the resulting point during verification. // // [1] [SCHNORR] "Optimizations". assert(x instanceof BN); assert(!x.red); if (this.isInfinity()) return false; const zz = this.z.redSqr(); const rx = x.toRed(this.curve.red).redMul(zz); return this.x.eq(rx); } eqR(x) { // Similar to the optimization above, this // optimization, suggested by Maxwell[1], // compares an integer to an X coordinate // by scaling it. // // Since a signature's R value is modulo N // in ECDSA, we may be dealing with an R // value greater than N in actuality. // // If the equality check fails, we can // scale N itself by Z and add it to the // X field element. // // [1] https://github.com/bitcoin-core/secp256k1/commit/ce7eb6f assert(x instanceof BN); assert(!x.red); if (!this.curve.smallGap) return this.toP().eqR(x); if (this.isInfinity()) return false; if (x.cmp(this.curve.p) >= 0) return false; const zz = this.z.redSqr(); const rx = x.toRed(this.curve.red).redMul(zz); if (this.x.eq(rx)) return true; if (this.curve.highOrder) return false; if (x.cmp(this.curve.pmodn) >= 0) return false; const rn = this.curve.redN.redMul(zz); rx.redIAdd(rn); return this.x.eq(rx); } toP() { // P = O if (this.isInfinity()) return this.curve.point(); this.normalize(); // (X3, Y3) = (X1 / Z1^2, Y1 / Z1^3) return this.curve.point(this.x, this.y); } toJ() { return this; } encode(compact) { return this.toP().encode(compact); } static decode(curve, bytes) { return ShortPoint.decode(curve, bytes).toJ(); } encodeX() { return this.toP().encodeX(); } static decodeEven(curve, bytes) { return ShortPoint.decodeEven(curve, bytes).toJ(); } static decodeSquare(curve, bytes) { return ShortPoint.decodeSquare(curve, bytes).toJ(); } toJSON(pre) { return this.toP().toJSON(pre); } toPretty() { return this.toP().toPretty(); } static fromJSON(curve, json) { return ShortPoint.fromJSON(curve, json).toJ(); } [custom]() { if (this.isInfinity()) return ''; return ''; } } /** * MontCurve */ class MontCurve extends Curve { constructor(conf) { super(MontPoint, 'mont', conf); this.a = BN.fromJSON(conf.a).toRed(this.red); this.b = BN.fromJSON(conf.b).toRed(this.red); this.bi = this.b.redInvert(); this.a2 = this.a.redAdd(this.two); this.a24 = this.a2.redMul(this.i4); this.a3 = this.a.redMul(this.i3); this.a0 = this.a.redMul(this.bi); this.b0 = this.bi.redSqr(); this._finalize(conf); } static _isomorphism(curveA, curveB, customB) { // Montgomery Isomorphism. // // [MONT3] Page 3, Section 2.1. // // Transformation: // // A' = A // B' = B' // // Where (B / B') is square. assert(curveA instanceof BN); assert(curveB instanceof BN); assert(customB instanceof BN); const a = curveA.clone(); const b = customB.clone(); const c = curveB.redDiv(customB); if (c.redJacobi() !== 1) throw new Error('Invalid `b` coefficient.'); return [a, b]; } _short(a0, odd) { // Montgomery->Short Weierstrass Equivalence. // // [MONT2] "Equivalence with Weierstrass curves". // // Transformation: // // a = (3 - A^2) / (3 * B^2) // b = (2 * A^3 - 9 * A) / (27 * B^3) const {a, b, three} = this; const a2 = a.redSqr(); const a3 = a2.redMul(a); const b2 = b.redSqr(); const b3 = b2.redMul(b); const n0 = three.redSub(a2); const d0 = b2.redMuln(3); const n1 = a3.redMuln(2).redISub(a.redMuln(9)); const d1 = b3.redMuln(27); const wa = n0.redDiv(d0); const wb = n1.redDiv(d1); if (a0 != null) return ShortCurve._isomorphism(wa, wb, a0, odd); return [wa, wb]; } _mont(b0) { return MontCurve._isomorphism(this.a, this.b, b0); } _edwards(a0, invert = false) { // Montgomery->Twisted Edwards Transformation. // // [MONT1] Page 11, Section 4.3.5. // [TWISTED] Theorem 3.2, Page 4, Section 3. // // Equivalence: // // a = (A + 2) / B // d = (A - 2) / B // // Isomorphism: // // a = a' // d = a' * (A - 2) / (A + 2) // // Where ((A + 2) / (B * a')) is square. // // If `d` is square, we can usually find // a complete curve by using the `invert` // option. This will create an isomorphism // chain of: M(A,B)->E(a,d)->E(d,a). // // The equivalence between E(a,d) and // E(d,a) is: // // (x, y) = (x, 1 / y) // // Meaning our map to E(d,a) is: // // x = u / v // y = 1 / ((u - 1) / (u + 1)) // = (u + 1) / (u - 1) assert(typeof invert === 'boolean'); const {two, bi} = this; const a = this.a.redAdd(two).redMul(bi); const d = this.a.redSub(two).redMul(bi); if (invert) a.swap(d); if (a0 != null) return EdwardsCurve._isomorphism(a, d, a0); return [a, d]; } _scaleShort(curve) { assert(curve instanceof ShortCurve); const [u2, u3] = curve._scale(this); return [this.field(u2.redInvert()), this.field(u3.redInvert())]; } _scaleMont(curve) { // We can extract the isomorphism factor with: // // c = +-sqrt(B / B') // // If base points are available, we can do: // // c = v' / v assert(curve instanceof MontCurve); if (this.g.isInfinity() || curve.g.isInfinity()) return this.field(curve.b).redDivSqrt(this.b); return this.g.y.redDiv(this.field(curve.g.y)); } _scaleEdwards(curve, invert) { // We _could_ do something like: // // B = 4 / (a - d) // c = +-sqrt(B / B') // // Which can be reduced to: // // c = +-sqrt(4 / ((a - d) * B')) // // If base points are available: // // v = u' / x // c = v' / v // // Which can be reduced to: // // c = v' * x / u' // // However, the way our maps are // written, we can re-use the Edwards // isomorphism factor when going the // other direction. assert(curve instanceof EdwardsCurve); const c = curve._scale(this, invert); return this.field(c); } _solveY0(x) { assert(x instanceof BN); // y^2 = x^3 + A * x^2 + B * x const a = this.a0; const b = this.b0; const x2 = x.redSqr(); const x3 = x2.redMul(x); const y2 = x3.redIAdd(a.redMul(x2)).redIAdd(b.redMul(x)); return y2; } _elligator2(u) { // Elligator 2. // // Distribution: 1/2. // // [ELL2] Page 11, Section 5.2. // [H2EC] "Elligator 2 Method". // "Mappings for Montgomery curves". // [SAFE] "Indistinguishability from uniform random strings". // // Assumptions: // // - y^2 = x^3 + A * x^2 + B * x. // - A != 0, B != 0. // - A^2 - 4 * B is non-zero and non-square in F(p). // - Let z be a non-square in F(p). // - u != +-sqrt(-1 / z). // // Note that Elligator 2 is defined over the form: // // y'^2 = x'^3 + A' * x'^2 + B' * x' // // Instead of: // // B * y^2 = x^3 + A * x^2 + x // // Where: // // A' = A / B // B' = 1 / B^2 // x' = x / B // y' = y / B // // And: // // x = B * x' // y = B * y' // // This is presumably the result of Elligator 2 // being designed in long Weierstrass form. If // we want to support B != 1, we need to do the // conversion. // // Map: // // g(x) = x^3 + A * x^2 + B * x // x1 = -A / (1 + z * u^2) // x1 = -A, if x1 = 0 // x2 = -x1 - A // x = x1, if g(x1) is square // = x2, otherwise // y = sign(u) * abs(sqrt(g(x))) const lhs = this.a0.redNeg(); const rhs = this.one.redAdd(this.z.redMul(u.redSqr())); if (rhs.isZero()) rhs.inject(this.one); const x1 = lhs.redMul(rhs.redInvert()); const x2 = x1.redNeg().redISub(this.a0); const y1 = this._solveY0(x1); const y2 = this._solveY0(x2); const alpha = y1.redIsSquare() | 0; const x0 = [x1, x2][alpha ^ 1]; const y0 = [y1, y2][alpha ^ 1].redSqrt(); if (y0.redIsOdd() !== u.redIsOdd()) y0.redINeg(); const x = this.b.redMul(x0); const y = this.b.redMul(y0); return this.point(x, y); } _invert2(p, hint) { // Inverting the Map (Elligator 2). // // [ELL2] Page 12, Section 5.3. // // Assumptions: // // - -z * x * (x + A) is square in F(p). // - If r = 1 then x != 0. // - If r = 2 then x != -A. // // Map: // // u1 = -(x + A) / (x * z) // u2 = -x / ((x + A) * z) // r = random integer in [1,2] // u = sign(y) * abs(sqrt(ur)) // // Note that `0 / 0` can only occur if A = 0 // (this violates the assumptions of Elligator 2). const {x, y} = p; const r = hint & 1; const x0 = x.redMul(this.bi); const y0 = y.redMul(this.bi); const n = x0.redAdd(this.a0); const d = x0; const lhs = [n, d][r].redINeg(); const rhs = [d, n][r].redMul(this.z); const u = lhs.redDivSqrt(rhs); if (u.redIsOdd() !== y0.redIsOdd()) u.redINeg(); return u; } isElliptic() { const a2 = this.a.redSqr(); const d = this.b.redMul(a2.redSub(this.four)); // B * (A^2 - 4) != 0 return !d.isZero(); } jinv() { // [MONT3] Page 3, Section 2. const {a, three, four} = this; const a2 = a.redSqr(); const t0 = a2.redSub(three); const lhs = t0.redPown(3).redIMuln(256); const rhs = a2.redSub(four); if (rhs.isZero()) throw new Error('Curve is not elliptic.'); // (256 * (A^2 - 3)^3) / (A^2 - 4) return lhs.redDiv(rhs).fromRed(); } point(x, y) { return new MontPoint(this, x, y); } jpoint(x, y, z) { assert(x == null && y == null && z == null); return this.point(); } xpoint(x, z) { return new XPoint(this, x, z); } solveY2(x) { // [MONT3] Page 3, Section 2. // https://hyperelliptic.org/EFD/g1p/auto-montgom.html assert(x instanceof BN); // B * y^2 = x^3 + A * x^2 + x const x2 = x.redSqr(); const x3 = x2.redMul(x); const by2 = x3.redIAdd(this.a.redMul(x2)).redIAdd(x); const y2 = by2.redMul(this.bi); return y2; } validate(point) { assert(point instanceof MontPoint); if (point.isInfinity()) return true; const {x, y} = point; const y2 = this.solveY2(x); return y.redSqr().eq(y2); } pointFromX(x, sign = null) { assert(x instanceof BN); assert(sign == null || typeof sign === 'boolean'); if (!x.red) x = x.toRed(this.red); const y = this.solveY(x); if (sign != null) { if (y.isZero() && sign) throw new Error('Invalid point.'); if (y.redIsOdd() !== sign) y.redINeg(); } return this.point(x, y); } isIsomorphic(curve, invert) { // [MONT3] Page 3, Section 2.1. assert(curve instanceof Curve); if (!curve.p.eq(this.p)) return false; // M(A,B) <-> M(A,B') if (curve.type === 'mont') { const a = this.field(curve.a); const b = this.field(curve.b); // A' = A if (!this.a.eq(a)) return false; // B' != 0 if (this.b.isZero()) return false; // jacobi(B / B') = 1 const c = b.redDiv(this.b); return c.redJacobi() === 1; } return curve.isIsomorphic(this, invert); } isIsogenous(curve) { assert(curve instanceof Curve); if (curve.type === 'mont') return false; return curve.isIsogenous(this); } pointFromShort(point) { // [ALT] Appendix E.2 (Switching between Alternative Representations). // [MONT2] "Equivalence with Weierstrass curves" assert(point instanceof ShortPoint); if (this.isIsomorphic(point.curve)) { // Equivalence for E(a,b)->M(A,B): // // u = B * x - A / 3 // v = B * y // // Undefined if ((u^3 + A * u^2 + u) / B) is not square. if (point.isInfinity()) return this.point(); const {a3, b} = this; const [u2, u3] = this._scale(point.curve); const x = this.field(point.x).redMul(u2); const y = this.field(point.y).redMul(u3); const u = b.redMul(x).redISub(a3); const v = b.redMul(y); return this.point(u, v); } throw new Error('Not implemented.'); } pointFromMont(point) { // [MONT3] Page 3, Section 2.1. assert(point instanceof MontPoint); if (this.isIsomorphic(point.curve)) { // Isomorphic maps for M(A,B)<->M(A,B'): // // u' = u // v' = +-sqrt(B / B') * v // // Undefined if (B / B') is not square. if (point.isInfinity()) return this.point(); const c = this._scale(point.curve); const u = this.field(point.x); const v = this.field(point.y); const nu = u; const nv = c.redMul(v); return this.point(nu, nv); } throw new Error('Not implemented.'); } pointFromEdwards(point) { // [RFC7748] Section 4.1 & 4.2. // [MONT3] Page 6, Section 2.5. // [TWISTED] Theorem 3.2, Page 4, Section 3. assert(point instanceof EdwardsPoint); assert(point.curve.p.eq(this.p)); // Edwards `x`, `y`, `z`. const x = this.field(point.x); const y = this.field(point.y); const z = this.field(point.z); if (this.isIsogenous(point.curve)) { // 4-isogeny maps for E(1,d)->M(2-4d,1): // // u = y^2 / x^2 // v = (2 - x^2 - y^2) * y / x^3 // // Undefined for x = 0. // // Exceptional Cases: // - (0, 1) -> O // - (0, -1) -> (0, 0) // // Unexceptional Cases: // - (+-1, 0) -> (0, 0) if (point.isInfinity()) return this.point(); if (point.x.isZero()) return this.point(this.zero, this.zero); const c = z.redSqr().redIMuln(2); const uu = y.redSqr(); const uz = x.redSqr(); const vv = c.redISub(uz).redISub(uu).redMul(y); const vz = uz.redMul(x); return this.cpoint(uu, uz, vv, vz); } if (this.isIsomorphic(point.curve, true)) { // Isomorphic maps for E(d,a)->M(A,B): // // u = (y + 1) / (y - 1) // v = +-sqrt((A - 2) / (B * a)) * u / x // // Undefined for x = 0 or y = 1. // // Exceptional Cases: // - (0, 1) -> O // - (0, -1) -> (0, 0) // // Unexceptional Cases: // - (+-sqrt(1 / a), 0) -> (-1, +-sqrt((A - 2) / B)) if (point.isInfinity()) return this.point(); if (point.x.isZero()) return this.point(this.zero, this.zero); const c = this._scale(point.curve, true); const uu = y.redAdd(z); const uz = y.redSub(z); const vv = c.redMul(z).redMul(uu); const vz = x.redMul(uz); return this.cpoint(uu, uz, vv, vz); } if (this.isIsomorphic(point.curve, false)) { // Isomorphic maps for E(a,d)->M(A,B): // // u = (1 + y) / (1 - y) // v = +-sqrt((A + 2) / (B * a)) * u / x // // Undefined for x = 0 or y = 1. // // Exceptional Cases: // - (0, 1) -> O // - (0, -1) -> (0, 0) // // Unexceptional Cases: // - (+-sqrt(1 / a), 0) -> (1, +-sqrt((A + 2) / B)) if (point.isInfinity()) return this.point(); if (point.x.isZero()) return this.point(this.zero, this.zero); const c = this._scale(point.curve, false); const uu = z.redAdd(y); const uz = z.redSub(y); const vv = c.redMul(z).redMul(uu); const vz = x.redMul(uz); return this.cpoint(uu, uz, vv, vz); } throw new Error('Not implemented.'); } pointFromUniform(u) { assert(u instanceof BN); // z = 0 or A = 0 if (this.z.isZero() || this.a.isZero()) throw new Error('Not implemented.'); return this._elligator2(u); } pointToUniform(p, hint) { // Convert a montgomery point to a field // element by inverting the elligator2 map. // // Hint Layout: // // [00000000] [0000] [0000] // | | | // | | +-- preimage index // | +--- subgroup // +-- bits to OR with uniform bytes assert(p instanceof MontPoint); assert((hint >>> 0) === hint); // z = 0 or A = 0 if (this.z.isZero() || this.a.isZero()) throw new Error('Not implemented.'); // P = O if (p.isInfinity()) throw new Error('Invalid point.'); // Add a random torsion component. const i = ((hint >>> 4) & 15) % this.torsion.length; const q = p.add(this.torsion[i]); return wrapErrors(() => { return this._invert2(q, hint); }); } decodePoint(bytes, sign) { return MontPoint.decode(this, bytes, sign); } encodeX(point) { assert(point instanceof XPoint); return point.encode(); } decodeX(bytes) { return XPoint.decode(this, bytes); } toShort(a0, odd, sign = null) { const [a, b] = this._short(a0, odd); const curve = new ShortCurve({ red: this.red, prime: this.prime, p: this.p, a: a, b: b, n: this.n, h: this.h }); if (sign != null) { const [, u3] = curve._scale(this); if (u3.redIsOdd() !== sign) u3.redINeg(); } if (!this.g.isInfinity()) curve.g = curve.pointFromMont(this.g); for (let i = 0; i < this.h.word(0); i++) curve.torsion[i] = curve.pointFromMont(this.torsion[i]); return curve; } toMont(b0, sign = null) { const [a, b] = this._mont(b0); const curve = new MontCurve({ red: this.red, prime: this.prime, p: this.p, a: a, b: b, n: this.n, h: this.h, z: this.z }); if (sign != null) { const c = curve._scale(this); if (c.redIsOdd() !== sign) c.redINeg(); } if (!this.g.isInfinity()) curve.g = curve.pointFromMont(this.g); for (let i = 0; i < this.h.word(0); i++) curve.torsion[i] = curve.pointFromMont(this.torsion[i]); return curve; } toEdwards(a0, invert, sign = null) { const [a, d] = this._edwards(a0, invert); const curve = new EdwardsCurve({ red: this.red, prime: this.prime, p: this.p, a: a, d: d, n: this.n, h: this.h, z: this.z }); if (sign != null) { const c = curve._scale(this, invert); if (c.redIsOdd() !== sign) c.redINeg(); } if (!this.g.isInfinity()) { curve.g = curve.pointFromMont(this.g); curve.g.normalize(); } if (curve.isComplete()) { for (let i = 0; i < this.h.word(0); i++) { curve.torsion[i] = curve.pointFromMont(this.torsion[i]); curve.torsion[i].normalize(); } } return curve; } pointFromJSON(json) { return MontPoint.fromJSON(this, json); } toJSON(pre) { const json = super.toJSON(pre); json.a = this.a.fromRed().toJSON(); json.b = this.b.fromRed().toJSON(); return json; } } /** * MontPoint */ class MontPoint extends Point { constructor(curve, x, y) { assert(curve instanceof MontCurve); super(curve, types.AFFINE); this.x = this.curve.zero; this.y = this.curve.zero; this.inf = true; if (x != null) this._init(x, y); } _init(x, y) { assert(x instanceof BN); assert(y instanceof BN); this.x = x; this.y = y; if (!this.x.red) this.x = this.x.toRed(this.curve.red); if (!this.y.red) this.y = this.y.toRed(this.curve.red); this.inf = false; } clone() { if (this.inf) return this.curve.point(); return this.curve.point(this.x, this.y); } scale(a) { return this.clone(); } randomize(rng) { return this.clone(); } neg() { // P = O if (this.inf) return this; // -(X1, Y1) = (X1, -Y1) return this.curve.point(this.x, this.y.redNeg()); } add(p) { // [MONT1] Page 8, Section 4.3.2. // // Addition Law: // // l = (y2 - y1) / (x2 - x1) // x3 = b * l^2 - a - x1 - x2 // y3 = l * (x1 - x3) - y1 // // 1I + 2M + 1S + 7A + 1*b assert(p instanceof MontPoint); // O + P = P if (this.inf) return p; // P + O = P if (p.inf) return this; // P + P, P + -P if (this.x.eq(p.x)) { // P + -P = O if (!this.y.eq(p.y)) return this.curve.point(); // P + P = 2P return this.dbl(); } // H = X2 - X1 const h = p.x.redSub(this.x); // R = Y2 - Y1 const r = p.y.redSub(this.y); // L = R / H const l = r.redDiv(h); // K = b * L^2 const k = this.curve.b.redMul(l.redSqr()); // X3 = K - a - X1 - X2 const nx = k.redISub(this.curve.a).redISub(this.x).redISub(p.x); // Y3 = L * (X1 - X3) - Y1 const ny = l.redMul(this.x.redSub(nx)).redISub(this.y); return this.curve.point(nx, ny); } dbl() { // [MONT1] Page 8, Section 4.3.2. // // Addition Law (doubling): // // l = (3 * x1^2 + 2 * a * x1 + 1) / (2 * b * y1) // x3 = b * l^2 - a - 2 * x1 // y3 = l * (x1 - x3) - y1 // // 1I + 3M + 2S + 7A + 1*a + 1*b + 1*b + 2*2 + 1*3 // P = O if (this.inf) return this; // Y1 = 0 if (this.y.isZero()) return this.curve.point(); // M1 = 3 * X1^2 const m1 = this.x.redSqr().redIMuln(3); // M2 = 2 * a * X1 const m2 = this.curve.a.redMul(this.x).redIMuln(2); // M = M1 + M2 + 1 const m = m1.redIAdd(m2).redIAdd(this.curve.one); // Z = 2 * b * Y1 const z = this.curve.b.redMul(this.y).redIMuln(2); // L = M / Z const l = m.redDiv(z); // K = b * L^2 const k = this.curve.b.redMul(l.redSqr()); // X3 = K - a - 2 * X1 const nx = k.redISub(this.curve.a).redISub(this.x).redISub(this.x); // Y3 = L * (X1 - X3) - Y1 const ny = l.redMul(this.x.redSub(nx)).redISub(this.y); return this.curve.point(nx, ny); } getX() { if (this.inf) throw new Error('Invalid point.'); return this.x.fromRed(); } getY() { if (this.inf) throw new Error('Invalid point.'); return this.y.fromRed(); } eq(p) { assert(p instanceof MontPoint); // P = Q if (this === p) return true; // P = O if (this.inf) return p.inf; // Q = O if (p.inf) return false; // X1 = X2, Y1 = Y2 return this.x.eq(p.x) && this.y.eq(p.y); } cmp(point) { assert(point instanceof MontPoint); if (this.inf && !point.inf) return -1; if (!this.inf && point.inf) return 1; if (this.inf && point.inf) return 0; return this.order().cmp(point.order()) || this.getX().cmp(point.getX()) || this.getY().cmp(point.getY()); } isInfinity() { // Infinity cannot be represented in // the affine space, except by a flag. return this.inf; } isOrder2() { if (this.inf) return false; return this.y.isZero(); } isOdd() { if (this.inf) return false; return this.y.redIsOdd(); } isEven() { if (this.inf) return false; return this.y.redIsEven(); } toP() { return this; } toJ() { return this; } toX() { // (X3, Z3) = (1, 0) if (this.inf) return this.curve.xpoint(); // (X3, Z3) = (X1, 1) return this.curve.xpoint(this.x, this.curve.one); } encode() { return this.toX().encode(); } static decode(curve, bytes, sign) { assert(curve instanceof MontCurve); return curve.decodeX(bytes).toP(sign); } toJSON(pre) { if (this.inf) return []; const x = this.getX().toJSON(); const y = this.getY().toJSON(); return [x, y]; } toPretty() { if (this.inf) return []; const size = this.curve.fieldSize * 2; const x = toPretty(this.getX(), size); const y = toPretty(this.getY(), size); return [x, y]; } static fromJSON(curve, json) { assert(curve instanceof MontCurve); assert(Array.isArray(json)); assert(json.length === 0 || json.length === 2 || json.length === 3); if (json.length === 0) return curve.point(); const x = BN.fromJSON(json[0]); const y = BN.fromJSON(json[1]); return curve.point(x, y); } [custom]() { if (this.inf) return ''; return ''; } } /** * XPoint */ class XPoint extends Point { constructor(curve, x, z) { assert(curve instanceof MontCurve); super(curve, types.PROJECTIVE); this.x = this.curve.one; this.z = this.curve.zero; if (x != null) this._init(x, z); } _init(x, z) { assert(x instanceof BN); assert(z == null || (z instanceof BN)); this.x = x; this.z = z || this.curve.one; if (!this.x.red) this.x = this.x.toRed(this.curve.red); if (!this.z.red) this.z = this.z.toRed(this.curve.red); } clone() { return this.curve.xpoint(this.x, this.z); } precompute(power, rng) { // No-op. return this; } validate() { if (this.isInfinity()) return true; // B * y^2 * z = x^3 + A * x^2 * z + x * z^2 const {x, z} = this; const x2 = x.redSqr(); const x3 = x2.redMul(x); const z2 = z.redSqr(); const ax2 = this.curve.a.redMul(x2).redMul(z); const by2 = x3.redIAdd(ax2).redIAdd(x.redMul(z2)); const y2 = by2.redMul(this.curve.bi); // sqrt(y^2 * z^4) = y * z^2 return y2.redMul(z).redJacobi() !== -1; } normalize() { // https://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#scaling-scale // 1I + 1M // P = O if (this.isInfinity()) return this; // Z1 = 1 if (this.z.eq(this.curve.one)) return this; // X3 = X1 / Z1 this.x = this.x.redDiv(this.z); // Z3 = 1 this.z = this.curve.one; return this; } scale(a) { assert(a instanceof BN); // P = O if (this.isInfinity()) return this.curve.xpoint(); // X3 = X1 * A const nx = this.x.redMul(a); // Y3 = Y1 * A const nz = this.z.redMul(a); return this.curve.xpoint(nx, nz); } neg() { // -(X1, Z1) = (X1, Z1) return this; } dbl() { // https://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 // 2M + 2S + 4A + 1*a24 // A = X1 + Z1 const a = this.x.redAdd(this.z); // AA = A^2 const aa = a.redSqr(); // B = X1 - Z1 const b = this.x.redSub(this.z); // BB = B^2 const bb = b.redSqr(); // C = AA - BB const c = aa.redSub(bb); // X3 = AA * BB const nx = aa.redMul(bb); // Z3 = C * (BB + a24 * C) const nz = c.redMul(bb.redIAdd(this.curve.a24.redMul(c))); return this.curve.xpoint(nx, nz); } diffAddDbl(p2, p3) { // https://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#ladder-ladd-1987-m-3 // 6M + 4S + 8A + 1*a24 assert(p2 instanceof XPoint); assert(p3 instanceof XPoint); // A = X2 + Z2 const a = p2.x.redAdd(p2.z); // AA = A^2 const aa = a.redSqr(); // B = X2 - Z2 const b = p2.x.redSub(p2.z); // BB = B^2 const bb = b.redSqr(); // E = AA - BB const e = aa.redSub(bb); // C = X3 + Z3 const c = p3.x.redAdd(p3.z); // D = X3 - Z3 const d = p3.x.redSub(p3.z); // DA = D * A const da = d.redMul(a); // CB = C * B const cb = c.redMul(b); // X5 = Z1 * (DA + CB)^2 const x5 = this.z.redMul(da.redAdd(cb).redSqr()); // Z5 = X1 * (DA - CB)^2 const z5 = this.x.redMul(da.redISub(cb).redSqr()); // X4 = AA * BB const x4 = aa.redMul(bb); // Z4 = E * (BB + a24 * E) const z4 = e.redMul(bb.redIAdd(this.curve.a24.redMul(e))); return [ this.curve.xpoint(x4, z4), this.curve.xpoint(x5, z5) ]; } getX() { if (this.isInfinity()) throw new Error('Invalid point.'); this.normalize(); return this.x.fromRed(); } getY(sign) { return this.toP(sign).getY(); } eq(p) { assert(p instanceof XPoint); // P = Q if (this === p) return true; // P = O if (this.isInfinity()) return p.isInfinity(); // Q = O if (p.isInfinity()) return false; // Z1 = Z2 if (this.z.eq(p.z)) return this.x.eq(p.x); // X1 * Z2 = X2 * Z1 const x1 = this.x.redMul(p.z); const x2 = p.x.redMul(this.z); return x1.eq(x2); } cmp(point) { assert(point instanceof XPoint); const inf1 = this.isInfinity(); const inf2 = point.isInfinity(); if (inf1 && !inf2) return -1; if (!inf1 && inf2) return 1; if (inf1 && inf2) return 0; return this.order().cmp(point.order()) || this.getX().cmp(point.getX()); } isInfinity() { // Z1 = 0 return this.z.isZero(); } isOrder2() { if (this.isInfinity()) return false; return this.x.isZero(); } isOdd() { return false; } isEven() { return false; } hasTorsion() { if (this.isInfinity()) return false; // X1 = 0, Z1 != 0 (edge case) if (this.x.isZero()) return true; return super.hasTorsion(); } order() { try { return this.toP().order(); } catch (e) { return new BN(1); } } jmul(k) { // Multiply with the Montgomery Ladder. // // [MONT3] Algorithm 4, Page 12, Section 4.2. // // Note that any clamping is meant to // be done _outside_ of this function. assert(k instanceof BN); assert(!k.red); const bits = k.bitLength(); let a = this.curve.xpoint(); let b = this; for (let i = bits - 1; i >= 0; i--) { const bit = k.bit(i); if (bit === 0) [a, b] = this.diffAddDbl(a, b); else [b, a] = this.diffAddDbl(b, a); } return a; } jmulBlind(k, rng) { if (!rng) return this.jmul(k); // Randomize if available. return this.randomize(rng).jmul(k); } jmulAdd(k1, p2, k2) { throw new Error('Not implemented.'); } toP(sign = null) { assert(sign == null || typeof sign === 'boolean'); if (this.isInfinity()) return this.curve.point(); this.normalize(); return this.curve.pointFromX(this.x, sign); } toJ() { return this; } toX() { return this; } key() { if (this.isInfinity()) return `${this.curve.uid}:oo`; this.normalize(); const x = this.getX().toString(16); return `${this.curve.uid}:${x}`; } encode() { // [RFC7748] Section 5. return this.curve.encodeField(this.getX()); } static decode(curve, bytes) { assert(curve instanceof MontCurve); // [RFC7748] Section 5. const x = curve.decodeField(bytes); // We're supposed to ignore the hi bit // on montgomery points... I think. If // we don't, the X25519 test vectors // break, which is pretty convincing // evidence. This is a no-op for X448. x.iumaskn(curve.fieldBits); // Note: montgomery points are meant to be // reduced by the prime and do not have to // be explicitly validated in order to do // the montgomery ladder. const p = curve.xpoint(x, curve.one); assert(!p.isInfinity()); return p; } toJSON(pre) { return this.toP().toJSON(pre); } toPretty() { return this.toP().toPretty(); } static fromJSON(curve, json) { return MontPoint.fromJSON(curve, json).toX(); } [custom]() { if (this.isInfinity()) return ''; return ''; } } /** * EdwardsCurve */ class EdwardsCurve extends Curve { constructor(conf) { super(EdwardsPoint, 'edwards', conf); this.a = BN.fromJSON(conf.a).toRed(this.red); this.d = BN.fromJSON(conf.d).toRed(this.red); this.s = BN.fromJSON(conf.s || '0').toRed(this.red); this.si = this.s.isZero() ? this.zero : this.s.redInvert(); this.k = this.d.redMuln(2); this.smi = -this.d.redNeg().word(0); this.ad6 = this.a.redAdd(this.d).redMul(this.i6); this.twisted = !this.a.eq(this.one); this.oneA = this.a.eq(this.one); this.mOneA = this.a.eq(this.one.redNeg()); this.smallD = this.prime != null && this.d.redNeg().length === 1; this.alt = null; this._finalize(conf); } static _isomorphism(curveA, curveD, customA) { // Twisted Edwards Isomorphism. // // [TWISTED] Definition 2.1, Page 3, Section 2. // // Transformation: // // a' = a' // d' = a' * d / a // // Where (a / a') is square. assert(curveA instanceof BN); assert(curveD instanceof BN); assert(customA instanceof BN); const a = customA.clone(); const d = customA.redMul(curveD).redDiv(curveA); const c = curveA.redDiv(customA); if (c.redJacobi() !== 1) throw new Error('Invalid `a` coefficient.'); return [a, d]; } _short(a0, odd) { // Twisted Edwards->Short Weierstrass Equivalence. // // [TWISTEQ] Section 2. // // Transformation: // // a' = -(a^2 + 14 * a * d + d^2) / 48 // b' = (33 * (a^2 * d + a * d^2) - a^3 - d^3) / 864 const {a, d} = this; const a2 = a.redSqr(); const a3 = a2.redMul(a); const d2 = d.redSqr(); const d3 = d2.redMul(d); const ad14 = a.redMul(d).redIMuln(14); const a2d = a2.redMul(d); const ad2 = a.redMul(d2); const t0 = a2d.redIAdd(ad2).redIMuln(33); const wa = a2.redAdd(ad14).redIAdd(d2).redDivn(-48); const wb = t0.redISub(a3).redISub(d3).redDivn(864); if (a0 != null) return ShortCurve._isomorphism(wa, wb, a0, odd); return [wa, wb]; } _mont(b0, invert = false) { // Twisted Edwards->Montgomery Transformation. // // [TWISTED] Theorem 3.2, Page 4, Section 3. // // Equivalence: // // A = 2 * (a + d) / (a - d) // B = 4 / (a - d) // // Isomorphism: // // A = 2 * (a + d) / (a - d) // B = B' // // Where ((4 / (a - d)) / B') is square. // // If `4 / (a - d)` is non-square, we can // usually force B=1 by using the `invert` // option. This will create an isomorphism // chain of: E(a,d)->E(d,a)->M(-A,-B). // // The equivalence between E(a,d) and E(d,a) // is: // // (x, y) = (x, 1 / y) // // Meaning our map to M(-A,-B) is: // // u = (1 + 1 / y) / (1 - 1 / y) // = (y + 1) / (y - 1) // v = u / x assert(typeof invert === 'boolean'); let apd, amd; if (invert) { apd = this.d.redAdd(this.a); amd = this.d.redSub(this.a); } else { apd = this.a.redAdd(this.d); amd = this.a.redSub(this.d); } const z = amd.redInvert(); const a = apd.redMuln(2).redMul(z); const b = z.redMuln(4); if (b0 != null) return MontCurve._isomorphism(a, b, b0); return [a, b]; } _edwards(a0) { return EdwardsCurve._isomorphism(this.a, this.d, a0); } _scaleShort(curve) { assert(curve instanceof ShortCurve); const [u2, u3] = curve._scale(this); return [this.field(u2.redInvert()), this.field(u3.redInvert())]; } _scaleMont(curve, invert = false) { // Calculate isomorphism factor between // Twisted Edwards and Montgomery with: // // a = (A + 2) / B // c = +-sqrt(a / a') // // Which can be reduced to: // // c = +-sqrt((A + 2) / (B * a')) // // If base points are available, we can do: // // x = u / v // c = x' / x // // Which can be reduced to: // // c = v * x' / u // // We can now calculate the Edwards `x` with: // // x' = c * u / v // // And likewise, the Montgomery `v`: // // v = c * u / x' assert(curve instanceof MontCurve); assert(typeof invert === 'boolean'); if (this.g.isInfinity() || curve.g.isInfinity()) { const [a] = curve._edwards(null, invert); return this.field(a).redDivSqrt(this.a); } const x = curve.g.x.redDiv(curve.g.y); return this.g.x.redDiv(this.field(x)); } _scaleEdwards(curve) { // We can extract the isomorphism factor with: // // c = +-sqrt(a / a') // // If base points are available, we can do: // // c = x' / x assert(curve instanceof EdwardsCurve); if (this.g.isInfinity() || curve.g.isInfinity()) return this.field(curve.a).redDivSqrt(this.a); return this.g.x.redDiv(this.field(curve.g.x)); } _mulA(num) { assert(num instanceof BN); // n * a = n if (this.oneA) return num.clone(); // n * a = -n if (this.mOneA) return num.redNeg(); return this.a.redMul(num); } _mulD(num) { assert(num instanceof BN); // -d < 0x4000000 if (this.smallD) return num.redMuln(this.smi); return this.d.redMul(num); } _elligator1(t) { // Elligator 1. // // Distribution: 1/2. // // [ELL1] Page 6, Section 3. // Page 15, Appendix A. // [ELL2] Page 7, Section 3.2. // // Assumptions: // // - Let p be a prime power congruent to 3 mod 4. // - Let s be a nonzero element of F(p). // - Let c = 2 / s^2. // - Let r = c + 1 / c. // - Let d = -(c + 1)^2 / (c - 1)^2. // - (s^2 - 2) * (s^2 + 2) != 0. // - c * (c - 1) * (c + 1) != 0. // - r != 0. // - d is not square. // - x^2 + y^2 = 1 + d * x^2 * y^2. // - u * v * X * Y * x * (Y + 1) != 0. // - Y^2 = X^5 + (r^2 - 2) * X^3 + X. // // Elligator 1, as devised by Fouque et al, // takes place on the hyperelliptic curve of: // // y^2 = x^5 + (r^2 - 2) * x^3 + x // // Not only must our Edwards curve be complete, // with a prime congruent to 3 mod 4, and a = 1, // our curve must be isomorphic to a hyperelliptic // curve of the above form. Roughly one half of // all Edwards curves are isomorphic to a curve // of said form. // // We can derive the isomorphism with: // // c = (d +- 2 * sqrt(-d) - 1) / (d + 1) // s = +-sqrt(2 / c) // r = c + 1 / c // // Note that even if your curve is an Elligator 1 // curve, Elligator 2 is probably still preferable, // as it has nearly the same properties (i.e. the // same distribution), and is much less complex. // // Map: // // f(a) = a^((p - 1) / 2) // u = (1 - t) / (1 + t) // v = u^5 + (r^2 - 2) * u^3 + u // X = f(v) * u // Y = (f(v) * v)^((p + 1) / 4) * f(v) * f(u^2 + 1 / c^2) // Y = 1, if u = 0 // x = (c - 1) * s * X * (1 + X) / Y // y = (r * X - (1 + X)^2) / (r * X + (1 + X)^2) // // When t = +-1, we create the hyperelliptic // 2-torsion point of (0, 0). This needs to be // mapped to (0, -1) in Edwards form, but the x // denominator becomes zero. As far as I can // tell, this is the only exceptional case. // // The only other exceptional case initially // appears to be when the y denominator sums to // zero (when t = sqrt(4 / r + 1)), however, the // hyperelliptic `X` is negated by the sign of // `v`, making this impossible. const {s, si, i2, one, two} = this; const c = si.redSqr().redIMuln(2); const ci = s.redSqr().redMul(i2); const ci2 = ci.redSqr(); const r = c.redAdd(ci); const r2 = r.redSqr().redISub(two); const cm1 = c.redSub(one); const uu = one.redSub(t); const uz = one.redAdd(t); const u = uz.isZero() ? uz : uu.redDiv(uz); const u2 = u.redSqr(); const u3 = u2.redMul(u); const u5 = u3.redMul(u2); const v = u5.redAdd(r2.redMul(u3)).redIAdd(u); const f0 = this.field(v.redJacobi()); const f1 = this.field(u2.redAdd(ci2).redJacobi()); const f2 = f0.redMul(f1); const X = f0.redMul(u); const Y = f0.redMul(v).redSqrt().redMul(f2); const X1 = one.redAdd(X); const rX = r.redMul(X); const X12 = X1.redSqr(); const xx = cm1.redMul(s).redMul(X).redMul(X1); const xz = u.isZero() ? this.one : Y; const yy = rX.redSub(X12); const yz = rX.redAdd(X12); return this.cpoint(xx, xz, yy, yz); } _invert1(p, hint) { // Inverting the Map (Elligator 1). // // [ELL1] Page 6, Section 3. // Page 15, Appendix A. // [ELL2] Page 7, Section 3.3. // // Assumptions: // // - y + 1 != 0. // - (1 + n * r)^2 - 1 is square in F(p). // - If n * r = -2 then x = 2 * s * (c - 1) * f(c) / r. // - Y = (c - 1) * s * X * (1 + X) / x. // // Map: // // f(a) = a^((p - 1) / 2) // n = (y - 1) / (2 * (y + 1)) // X = -(1 + n * r) + ((1 + n * r)^2 - 1)^((p + 1) / 4) // z = f((c - 1) * s * X * (1 + X) * x * (X^2 + 1 / c^2)) // u = z * X // t = (1 - u) / (1 + u) const {s, si, i2, one} = this; const {x, y, z} = p; const sign = hint & 1; const c = si.redSqr().redIMuln(2); const ci = s.redSqr().redMul(i2); const ci2 = ci.redSqr(); const r = c.redAdd(ci); const cm1 = c.redSub(one); const nn = y.redSub(z); const nz = y.redAdd(z).redIMuln(2); const n = nz.isZero() ? nz : nn.redDiv(nz); const nr1 = one.redAdd(n.redMul(r)); const w2 = nr1.redSqr().redISub(one); const w = w2.redSqrt(); const X = w.redSub(nr1); const X1 = one.redAdd(X); const YY = cm1.redMul(s).redMul(X).redMul(X1); const Y = YY.redMul(x.redMul(z)); const X2 = X.redSqr().redIAdd(ci2); const Z = this.field(Y.redMul(X2).redJacobi()); const u = Z.redMul(X); const tt = one.redSub(u); const tz = one.redAdd(u); const t = tz.isZero() ? tz : tt.redDiv(tz); if (t.redIsOdd() !== Boolean(sign)) t.redINeg(); return t; } _alt() { if (!this.alt) this.alt = this.toMont(); return this.alt; } isElliptic() { const ad = this.a.redMul(this.d); const amd = this.a.redSub(this.d); // a * d * (a - d) != 0 return !ad.redMul(amd).isZero(); } jinv() { // [TWISTED] Definition 2.1, Page 3, Section 2. const {a, d} = this; const ad = a.redMul(d); const amd4 = a.redSub(d).redPown(4); const a2 = a.redSqr(); const d2 = d.redSqr(); const t0 = a2.redAdd(ad.redMuln(14)).redIAdd(d2); const lhs = t0.redPown(3).redIMuln(16); const rhs = ad.redMul(amd4); if (rhs.isZero()) throw new Error('Curve is not elliptic.'); // 16 * (a^2 + 14 * a * d + d^2)^3 / (a * d * (a - d)^4) return lhs.redDiv(rhs).fromRed(); } isComplete() { return this.a.redJacobi() === 1 && this.d.redJacobi() === -1; } point(x, y, z, t) { return new EdwardsPoint(this, x, y, z, t); } jpoint(x, y, z) { assert(x == null && y == null && z == null); return this.point(); } cpoint(xx, xz, yy, yz) { assert(xx instanceof BN); assert(xz instanceof BN); assert(yy instanceof BN); assert(yz instanceof BN); const x = xx.redMul(yz); const y = yy.redMul(xz); const z = xz.redMul(yz); const t = xx.redMul(yy); return this.point(x, y, z, t); } solveX2(y) { // [RFC8032] Section 5.1.3 & 5.2.3. assert(y instanceof BN); // x^2 = (y^2 - 1) / (d * y^2 - a) const y2 = y.redSqr(); const rhs = this._mulD(y2).redISub(this.a); const lhs = y2.redISub(this.one); const x2 = lhs.redDiv(rhs); return x2; } solveX(y) { // Optimize with inverse square root trick. // // Note that `0 / 0` can only occur if // `a == d` (i.e. the curve is singular). const y2 = y.redSqr(); const rhs = this._mulD(y2).redISub(this.a); const lhs = y2.redISub(this.one); return lhs.redDivSqrt(rhs); } solveY2(x) { assert(x instanceof BN); // y^2 = (a * x^2 - 1) / (d * x^2 - 1) const x2 = x.redSqr(); const lhs = this._mulA(x2).redISub(this.one); const rhs = this._mulD(x2).redISub(this.one); const y2 = lhs.redDiv(rhs); return y2; } solveY(x) { // Optimize with inverse square root trick. // // Note that `0 / 0` can only occur if // `a == d` (i.e. the curve is singular). const x2 = x.redSqr(); const lhs = this._mulA(x2).redISub(this.one); const rhs = this._mulD(x2).redISub(this.one); return lhs.redDivSqrt(rhs); } validate(point) { // [TWISTED] Definition 2.1, Page 3, Section 2. // Page 11, Section 6. assert(point instanceof EdwardsPoint); // Z1 = 1 if (point.zOne) { // a * x^2 + y^2 = 1 + d * x^2 * y^2 const x2 = point.x.redSqr(); const y2 = point.y.redSqr(); const dxy = this._mulD(x2).redMul(y2); const lhs = this._mulA(x2).redIAdd(y2); const rhs = this.one.redAdd(dxy); const tz = point.t; const xy = point.x.redMul(point.y); return lhs.eq(rhs) && tz.eq(xy); } // (a * x^2 + y^2) * z^2 = z^4 + d * x^2 * y^2 const x2 = point.x.redSqr(); const y2 = point.y.redSqr(); const z2 = point.z.redSqr(); const z4 = z2.redSqr(); const dxy = this._mulD(x2).redMul(y2); const lhs = this._mulA(x2).redIAdd(y2).redMul(z2); const rhs = z4.redIAdd(dxy); const tz = point.t.redMul(point.z); const xy = point.x.redMul(point.y); return lhs.eq(rhs) && tz.eq(xy); } pointFromX(x, sign = null) { assert(x instanceof BN); assert(sign == null || typeof sign === 'boolean'); if (!x.red) x = x.toRed(this.red); const y = this.solveY(x); if (sign != null) { if (y.isZero() && sign) throw new Error('Invalid point.'); if (y.redIsOdd() !== sign) y.redINeg(); } return this.point(x, y); } pointFromY(y, sign = null) { assert(y instanceof BN); assert(sign == null || typeof sign === 'boolean'); if (!y.red) y = y.toRed(this.red); const x = this.solveX(y); if (sign != null) { if (x.isZero() && sign) throw new Error('Invalid point.'); if (x.redIsOdd() !== sign) x.redINeg(); } return this.point(x, y); } isIsomorphic(curve, invert = false) { // [TWISTED] Theorem 3.2, Page 4, Section 3. // Definition 2.1, Page 3, Section 2. assert(curve instanceof Curve); assert(typeof invert === 'boolean'); if (!curve.p.eq(this.p)) return false; // E(a,d) <-> E(a,b) if (curve.type === 'short') return curve.isIsomorphic(this); // E(a,d) <-> M(A,B) // E(a,d) <-> M(-A,-B) if (curve.type === 'mont') { // A * (a - d) = 2 * (a + d) const a = this.field(curve.a); let apd, amd; if (invert) { apd = this.d.redAdd(this.a); amd = this.d.redSub(this.a); } else { apd = this.a.redAdd(this.d); amd = this.a.redSub(this.d); } return a.redMul(amd).eq(apd.redIMuln(2)); } // E(a,d) <-> E(a',a'd/a) if (curve.type === 'edwards') { // a' * d = a * d' const a = this.field(curve.a); const d = this.field(curve.d); return this.a.redMul(d).eq(a.redMul(this.d)); } return false; } isIsogenous(curve) { // Check for the 4-isogenies described by Hamburg: // https://moderncrypto.org/mail-archive/curves/2016/000806.html assert(curve instanceof Curve); if (!curve.p.eq(this.p)) return false; // E(1,d) <-> M(2-4d,1) if (curve.type === 'mont') { if (!this.a.eq(this.one)) return false; const a = this.field(curve.a); const b = this.field(curve.b); const d24 = this.two.redSub(this.d.redMuln(4)); return a.eq(d24) && b.eq(this.one); } // E(a,d) <-> E(-a,d-a) if (curve.type === 'edwards') { const a = this.field(curve.a); const d = this.field(curve.d); return a.eq(this.a.redNeg()) && d.eq(this.d.redSub(this.a)); } return false; } pointFromShort(point) { // [TWISTEQ] Section 1. assert(point instanceof ShortPoint); if (this.isIsomorphic(point.curve)) { // Equivalence for E(a,b)->E(a',d'): // // x' = (6 * x - a' - d') / (6 * y) // y' = (12 * x - 5 * a' + d') / (12 * x + a' - 5 * d') // // Undefined for x = (5 * d' - a') / 12 or y = 0. // // Exceptional Cases: // - O -> (0, 1) // - ((a' + d') / 6, 0) -> (0, -1) // - ((5 * d' - a') / 12, (d' - a') / 4 * sqrt(d')) -> (sqrt(1/d'), oo) // // Unexceptional Cases: // - ((5 * a' - d') / 12, (a' - d') / 4 * sqrt(a')) -> (sqrt(1/a'), 0) if (point.isInfinity()) return this.point(); if (point.y.isZero()) return this.point(this.zero, this.one.redNeg()); const {a, d} = this; const [u2, u3] = this._scale(point.curve); const a5 = a.redMuln(5); const d5 = d.redMuln(5); const x = this.field(point.x).redMul(u2); const y = this.field(point.y).redMul(u3); const x6 = x.redMuln(6); const x12 = x.redMuln(12); const xx = x6.redSub(a).redISub(d); const xz = y.redMuln(6); const yy = x12.redSub(a5).redIAdd(d); const yz = x12.redAdd(a).redISub(d5); return this.cpoint(xx, xz, yy, yz); } throw new Error('Not implemented.'); } pointFromMont(point) { // [RFC7748] Section 4.1 & 4.2. // [MONT3] Page 6, Section 2.5. // [TWISTED] Theorem 3.2, Page 4, Section 3. assert(point instanceof MontPoint); assert(point.curve.p.eq(this.p)); // Montgomery `u`, `v`. const u = this.field(point.x); const v = this.field(point.y); if (this.isIsogenous(point.curve)) { // 4-isogeny maps for M(2-4d,1)->E(1,d): // // x = 4 * v * (u^2 - 1) / (u^4 - 2 * u^2 + 4 * v^2 + 1) // y = -(u^5 - 2 * u^3 - 4 * u * v^2 + u) / // (u^5 - 2 * u^2 * v^2 - 2 * u^3 - 2 * v^2 + u) // // Undefined for u = 0 and v = 0. // // Exceptional Cases: // - O -> (0, 1) // - (0, 0) -> (0, 1) // // Unexceptional Cases: // - (-1, +-sqrt(A - 2)) -> (0, 1) // - (1, +-sqrt(A + 2)) -> (0, -1) // // The point (1, v) is invalid on Curve448. if (point.isInfinity()) return this.point(); if (point.x.isZero()) return this.point(); const u2 = u.redSqr(); const u3 = u2.redMul(u); const u4 = u3.redMul(u); const u5 = u4.redMul(u); const v2 = v.redSqr(); const a = v.redMuln(4); const b = u2.redSub(this.one); const c = u2.redMuln(2); const d = v2.redMuln(4); const e = u3.redIMuln(2); const f = u.redMul(v2).redIMuln(4); const g = u2.redMul(v2).redIMuln(2); const h = v2.redIMuln(2); const xx = a.redMul(b); const xz = u4.redISub(c).redIAdd(d).redIAdd(this.one); const yy = u5.redSub(e).redISub(f).redIAdd(u).redINeg(); const yz = u5.redISub(g).redISub(e).redISub(h).redIAdd(u); return this.cpoint(xx, xz, yy, yz).divn(4); } if (this.isIsomorphic(point.curve, true)) { // Isomorphic maps for M(-A,-B)->E(a,d): // // x = +-sqrt((A - 2) / (B * a)) * u / v // y = (u + 1) / (u - 1) // // Undefined for u = 1 or v = 0. // // Exceptional Cases: // - O -> (0, 1) // - (0, 0) -> (0, -1) // - (1, +-sqrt((A + 2) / B)) -> (+-sqrt(1 / d), oo) // // Unexceptional Cases: // - (-1, +-sqrt((A - 2) / B)) -> (+-sqrt(1 / a), 0) // // The point (1, v) is invalid on Curve448. if (point.isInfinity()) return this.point(); if (point.x.isZero()) return this.point(this.zero, this.one.redNeg()); const c = this._scale(point.curve, true); const xx = c.redMul(u); const xz = v; const yy = u.redAdd(this.one); const yz = u.redSub(this.one); return this.cpoint(xx, xz, yy, yz); } if (this.isIsomorphic(point.curve, false)) { // Isomorphic maps for M(A,B)->E(a,d): // // x = +-sqrt((A + 2) / (B * a)) * u / v // y = (u - 1) / (u + 1) // // Undefined for u = -1 or v = 0. // // Exceptional Cases: // - O -> (0, 1) // - (0, 0) -> (0, -1) // - (-1, +-sqrt((A - 2) / B)) -> (+-sqrt(1 / d), oo) // // Unexceptional Cases: // - (1, +-sqrt((A + 2) / B)) -> (+-sqrt(1 / a), 0) // // The point (-1, v) is invalid on Curve25519. if (point.isInfinity()) return this.point(); if (point.x.isZero()) return this.point(this.zero, this.one.redNeg()); const c = this._scale(point.curve, false); const xx = c.redMul(u); const xz = v; const yy = u.redSub(this.one); const yz = u.redAdd(this.one); return this.cpoint(xx, xz, yy, yz); } throw new Error('Not implemented.'); } pointFromEdwards(point) { // [TWISTED] Definition 2.1, Page 3, Section 2. // [ISOGENY] Page 2, Section 2. assert(point instanceof EdwardsPoint); assert(point.curve.p.eq(this.p)); // Edwards `x`, `y`, `z`, `t`. const a = this.field(point.curve.a); const x = this.field(point.x); const y = this.field(point.y); const z = this.field(point.z); const t = this.field(point.t); if (this.isIsogenous(point.curve)) { // 4-isogeny maps for E(a,d)<->E(-a,d-a): // // x' = (2 * x * y) / (y^2 - a * x^2) // y' = (y^2 + a * x^2) / (2 - y^2 - a * x^2) // // Undefined for y^2 - a * x^2 = 0 // or y^2 + a * x^2 = 2. const xy = x.redMul(y); const x2 = x.redSqr(); const y2 = y.redSqr(); const z2 = z.redSqr(); const ax2 = a.redMul(x2); const xx = xy.redIMuln(2); const xz = y2.redSub(ax2); const yy = y2.redAdd(ax2); const yz = z2.redIMuln(2).redISub(yy); const p = this.cpoint(xx, xz, yy, yz); return !this.twisted ? p.divn(4) : p; } if (this.isIsomorphic(point.curve)) { // Isomorphic maps for E(a,d)<->E(a',a'd/a): // // x' = +-sqrt(a / a') * x // y' = y // // Undefined when (a / a') is not square. const c = this._scale(point.curve); const nx = c.redMul(x); const ny = y; const nz = z; const nt = c.redMul(t); return this.point(nx, ny, nz, nt); } throw new Error('Not implemented.'); } pointFromUniform(u, curve = null) { assert(u instanceof BN); assert(u.red === this.red); assert(curve == null || (curve instanceof MontCurve)); if (!curve) curve = this._alt(); const u0 = curve.field(u); const p0 = curve.pointFromUniform(u0); return this.pointFromMont(p0); } pointToUniform(p, hint, curve = null) { // Convert an edwards point to a field // element by inverting the elligator2 map. // // Hint Layout: // // [00000000] [0000] [0000] // | | | // | | +-- preimage index // | +--- subgroup // +-- bits to OR with uniform bytes assert(p instanceof EdwardsPoint); assert((hint >>> 0) === hint); assert(curve == null || (curve instanceof MontCurve)); if (!curve) curve = this._alt(); // Add a random torsion component. const i = ((hint >> 4) & 15) % this.torsion.length; const q = p.add(this.torsion[i]); // Convert and invert. const p0 = curve.pointFromEdwards(q); const u0 = curve.pointToUniform(p0, hint & 15); return this.field(u0); } pointFromHash(bytes, pake, curve = null) { assert(curve == null || (curve instanceof MontCurve)); if (!curve) curve = this._alt(); const p0 = curve.pointFromHash(bytes, pake); return this.pointFromMont(p0); } pointToHash(p, subgroup, rng, curve = null) { assert(p instanceof EdwardsPoint); assert((subgroup >>> 0) === subgroup); assert(curve == null || (curve instanceof MontCurve)); if (!curve) curve = this._alt(); // Add a random torsion component. const i = subgroup % this.torsion.length; const q = p.add(this.torsion[i]); // Convert and invert. const p0 = curve.pointFromEdwards(q); return curve.pointToHash(p0, 0, rng); } decodePoint(bytes) { return EdwardsPoint.decode(this, bytes); } toShort(a0, odd, sign = null) { const [a, b] = this._short(a0, odd); const curve = new ShortCurve({ red: this.red, prime: this.prime, p: this.p, a: a, b: b, n: this.n, h: this.h }); if (sign != null) { const [, u3] = curve._scale(this); if (u3.redIsOdd() !== sign) u3.redINeg(); } if (!this.g.isInfinity()) curve.g = curve.pointFromEdwards(this.g); for (let i = 0; i < this.h.word(0); i++) curve.torsion[i] = curve.pointFromEdwards(this.torsion[i]); return curve; } toMont(b0, invert, sign = null) { const [a, b] = this._mont(b0, invert); const curve = new MontCurve({ red: this.red, prime: this.prime, p: this.p, a: a, b: b, n: this.n, h: this.h, z: this.z }); if (sign != null) { const c = this._scale(curve, invert); if (c.redIsOdd() !== sign) c.redINeg(); } if (!this.g.isInfinity()) curve.g = curve.pointFromEdwards(this.g); for (let i = 0; i < this.h.word(0); i++) curve.torsion[i] = curve.pointFromEdwards(this.torsion[i]); return curve; } toEdwards(a0, sign = null) { const [a, d] = this._edwards(a0); const curve = new EdwardsCurve({ red: this.red, prime: this.prime, p: this.p, a: a, d: d, n: this.n, h: this.h, z: this.z }); if (sign != null) { const c = curve._scale(this); if (c.redIsOdd() !== sign) c.redINeg(); } if (!this.g.isInfinity()) { curve.g = curve.pointFromEdwards(this.g); curve.g.normalize(); } if (curve.isComplete()) { for (let i = 0; i < this.h.word(0); i++) { curve.torsion[i] = curve.pointFromEdwards(this.torsion[i]); curve.torsion[i].normalize(); } } return curve; } pointFromJSON(json) { return EdwardsPoint.fromJSON(this, json); } toJSON(pre) { const json = super.toJSON(pre); json.a = this.a.fromRed().toJSON(); json.d = this.d.fromRed().toJSON(); if (!this.s.isZero()) json.s = this.s.fromRed().toJSON(); return json; } } /** * EdwardsPoint */ class EdwardsPoint extends Point { constructor(curve, x, y, z, t) { assert(curve instanceof EdwardsCurve); super(curve, types.EXTENDED); this.x = this.curve.zero; this.y = this.curve.one; this.z = this.curve.one; this.t = this.curve.zero; this.zOne = true; if (x != null) this._init(x, y, z, t); } _init(x, y, z, t) { assert(x instanceof BN); assert(y instanceof BN); assert(z == null || (z instanceof BN)); assert(t == null || (t instanceof BN)); this.x = x; this.y = y; this.z = z || this.curve.one; this.t = t || null; if (!this.x.red) this.x = this.x.toRed(this.curve.red); if (!this.y.red) this.y = this.y.toRed(this.curve.red); if (!this.z.red) this.z = this.z.toRed(this.curve.red); if (this.t && !this.t.red) this.t = this.t.toRed(this.curve.red); this.zOne = this.z.eq(this.curve.one); this._check(); if (!this.t) { this.t = this.x.redMul(this.y); if (!this.zOne) this.t = this.t.redDiv(this.z); } } _check() { // In order to achieve complete // addition formulas, `a` must // be a square (always the case // for a=1), and `d` must be a // non-square. // // If this is not the case, the // addition formulas may have // exceptional cases where Z3=0. // // In particular, this can occur // when: Q*h = -P*h and Q != -P. // // This is assuming 4-torsion is // involved (the 4-torsion point // is _not_ representable when // `d` is square). if (this.z.isZero()) throw new Error('Invalid point.'); } clone() { return this.curve.point(this.x, this.y, this.z, this.t); } normalize() { // https://hyperelliptic.org/EFD/g1p/auto-edwards-projective.html#scaling-z // 1I + 2M (+ 1M if extended) // Z1 = 1 if (this.zOne) return this; // A = 1 / Z1 const a = this.z.redInvert(); // X3 = X1 * A this.x = this.x.redMul(a); // Y3 = Y1 * A this.y = this.y.redMul(a); // T3 = T1 * A this.t = this.t.redMul(a); // Z3 = 1 this.z = this.curve.one; this.zOne = true; return this; } scale(a) { assert(a instanceof BN); // X3 = X1 * A const nx = this.x.redMul(a); // Y3 = Y1 * A const ny = this.y.redMul(a); // Z3 = Z1 * A const nz = this.z.redMul(a); // T3 = T1 * A const nt = this.t.redMul(a); return this.curve.point(nx, ny, nz, nt); } neg() { // -(X1, Y1, Z1, T1) = (-X1, Y1, Z1, -T1) const nx = this.x.redNeg(); const ny = this.y; const nz = this.z; const nt = this.t.redNeg(); return this.curve.point(nx, ny, nz, nt); } add(p) { assert(p instanceof EdwardsPoint); // P = O if (this.isInfinity()) return p; // Q = O if (p.isInfinity()) return this; // Z1 = 1 if (this.zOne) return p._add(this); return this._add(p); } _add(p) { // a = -1 if (this.curve.mOneA) return this._addM1(p); return this._addA(p); } _addM1(p) { // Assumes a = -1. // // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-3 // 8M + 8A + 1*k + 1*2 // // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-madd-2008-hwcd-3 // 7M + 8A + 1*k + 1*2 // A = (Y1 - X1) * (Y2 - X2) const a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); // B = (Y1 + X1) * (Y2 + X2) const b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); // C = T1 * k * T2 const c = this.t.redMul(this.curve.k).redMul(p.t); // D = Z1 * 2 * Z2 const d = p.zOne ? this.z.redAdd(this.z) : this.z.redMul(p.z).redIMuln(2); // E = B - A const e = b.redSub(a); // F = D - C const f = d.redSub(c); // G = D + C const g = d.redIAdd(c); // H = B + A const h = b.redIAdd(a); // X3 = E * F const nx = e.redMul(f); // Y3 = G * H const ny = g.redMul(h); // T3 = E * H const nt = e.redMul(h); // Z3 = F * G const nz = f.redMul(g); return this.curve.point(nx, ny, nz, nt); } _addA(p) { // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd // 9M + 7A + 1*a + 1*d // // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd // 8M + 7A + 1*a + 1*d // A = X1 * X2 const a = this.x.redMul(p.x); // B = Y1 * Y2 const b = this.y.redMul(p.y); // C = T1 * d * T2 const c = this.curve._mulD(this.t).redMul(p.t); // D = Z1 * Z2 const d = p.zOne ? this.z.clone() : this.z.redMul(p.z); // + XYXY = (X1 + Y1) * (X2 + Y2) const xyxy = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)); // E = (X1 + Y1) * (X2 + Y2) - A - B const e = xyxy.redISub(a).redISub(b); // F = D - C const f = d.redSub(c); // G = D + C const g = d.redIAdd(c); // H = B - a * A const h = b.redISub(this.curve._mulA(a)); // X3 = E * F const nx = e.redMul(f); // Y3 = G * H const ny = g.redMul(h); // T3 = E * H const nt = e.redMul(h); // Z3 = F * G const nz = f.redMul(g); return this.curve.point(nx, ny, nz, nt); } dbl() { // P = O if (this.isInfinity()) return this; return this._dbl(); } _dbl() { // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd // 4M + 4S + 6A + 1*a + 1*2 // // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-mdbl-2008-hwcd // 3M + 4S + 7A + 1*a + 1*2 // A = X1^2 const a = this.x.redSqr(); // B = Y1^2 const b = this.y.redSqr(); // C = 2 * Z1^2 const c = this.zOne ? this.curve.two : this.z.redSqr().redIMuln(2); // D = a * A const d = this.curve._mulA(a); // E = (X1 + Y1)^2 - A - B const e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); // G = D + B const g = d.redAdd(b); // F = G - C const f = g.redSub(c); // H = D - B const h = d.redISub(b); // X3 = E * F const nx = e.redMul(f); // Y3 = G * H const ny = g.redMul(h); // T3 = E * H const nt = e.redMul(h); // Z3 = F * G const nz = f.redMul(g); return this.curve.point(nx, ny, nz, nt); } getX() { this.normalize(); return this.x.fromRed(); } getY() { this.normalize(); return this.y.fromRed(); } eq(p) { assert(p instanceof EdwardsPoint); assert(!this.z.isZero()); assert(!p.z.isZero()); // P = Q if (this === p) return true; // Z1 = Z2 if (this.z.eq(p.z)) { return this.x.eq(p.x) && this.y.eq(p.y); } // X1 * Z2 = X2 * Z1 const x1 = this.x.redMul(p.z); const x2 = p.x.redMul(this.z); if (!x1.eq(x2)) return false; const y1 = this.y.redMul(p.z); const y2 = p.y.redMul(this.z); return y1.eq(y2); } cmp(point) { assert(point instanceof EdwardsPoint); return this.order().cmp(point.order()) || this.getY().cmp(point.getY()) || this.getX().cmp(point.getX()); } isInfinity() { assert(!this.z.isZero()); // X1 = 0 if (!this.x.isZero()) return false; // Y1 = Z1 return this.y.eq(this.z); } isOrder2() { if (this.isInfinity()) return false; return this.x.isZero(); } isOdd() { this.normalize(); return this.x.redIsOdd(); } isEven() { this.normalize(); return this.x.redIsEven(); } toP() { return this.normalize(); } toJ() { return this; } encode() { // [RFC8032] Section 5.1.2. const y = this.getY(); // Note: `x` normalized from `getY()` call. y.setn(this.curve.signBit, this.x.redIsOdd()); return this.curve.encodeAdjusted(y); } static decode(curve, bytes) { // [RFC8032] Section 5.1.3. assert(curve instanceof EdwardsCurve); const y = curve.decodeAdjusted(bytes); const sign = y.testn(curve.signBit) !== 0; y.setn(curve.signBit, 0); if (y.cmp(curve.p) >= 0) throw new Error('Invalid point.'); return curve.pointFromY(y, sign); } toJSON(pre) { if (this.isInfinity()) return []; const x = this.getX().toJSON(); const y = this.getY().toJSON(); if (pre === true && this.pre) return [x, y, this.pre.toJSON()]; return [x, y]; } toPretty() { const size = this.curve.fieldSize * 2; const x = toPretty(this.getX(), size); const y = toPretty(this.getY(), size); return [x, y]; } static fromJSON(curve, json) { assert(curve instanceof EdwardsCurve); assert(Array.isArray(json)); assert(json.length === 0 || json.length === 2 || json.length === 3); if (json.length === 0) return curve.point(); const x = BN.fromJSON(json[0]); const y = BN.fromJSON(json[1]); const point = curve.point(x, y); if (json.length > 2 && json[2] != null) point.pre = Precomp.fromJSON(point, json[2]); return point; } [custom]() { if (this.isInfinity()) return ''; return ''; } } /** * Precomp */ class Precomp { constructor() { this.naf = null; this.windows = null; this.doubles = null; this.blinding = null; this.beta = null; } map(func) { assert(typeof func === 'function'); const out = new this.constructor(); if (this.naf) out.naf = this.naf.map(func); if (this.doubles) out.doubles = this.doubles.map(func); return out; } toJSON() { return { naf: this.naf ? this.naf.toJSON() : null, windows: this.windows ? this.windows.toJSON() : null, doubles: this.doubles ? this.doubles.toJSON() : null, blinding: this.blinding ? this.blinding.toJSON() : undefined }; } fromJSON(point, json) { assert(point instanceof Point); assert(json && typeof json === 'object'); if (json.naf != null) this.naf = NAF.fromJSON(point, json.naf); if (json.windows != null) this.windows = Windows.fromJSON(point, json.windows); if (json.doubles != null) this.doubles = Doubles.fromJSON(point, json.doubles); if (json.blinding != null) this.blinding = Blinding.fromJSON(point, json.blinding); return this; } static fromJSON(point, json) { return new this().fromJSON(point, json); } } /** * NAF */ class NAF { constructor(width, points) { this.width = width; this.points = points; } map(func) { assert(typeof func === 'function'); const {width} = this; const points = []; for (const point of this.points) points.push(func(point)); return new this.constructor(width, points); } toJSON() { return { width: this.width, points: this.points.slice(1).map((point) => { return point.toJSON(); }) }; } static fromJSON(point, json) { assert(point instanceof Point); assert(json && typeof json === 'object'); assert((json.width >>> 0) === json.width); assert(Array.isArray(json.points)); const {curve} = point; const {width} = json; const points = [point]; for (const item of json.points) points.push(curve.pointFromJSON(item)); return new this(width, points); } } /** * Windows */ class Windows { constructor(width, bits, points) { this.width = width; this.bits = bits; this.points = points; } toJSON() { return { width: this.width, bits: this.bits, points: this.points.slice(1).map((point) => { return point.toJSON(); }) }; } static fromJSON(point, json) { assert(point instanceof Point); assert(json && typeof json === 'object'); assert((json.width >>> 0) === json.width); assert((json.bits >>> 0) === json.bits); assert(Array.isArray(json.points)); const {curve} = point; const {width, bits} = json; const points = [point]; for (const item of json.points) points.push(curve.pointFromJSON(item)); return new this(width, bits, points); } } /** * Doubles */ class Doubles { constructor(step, points) { this.step = step; this.points = points; } map(func) { assert(typeof func === 'function'); const {step} = this; const points = []; for (const point of this.points) points.push(func(point)); return new this.constructor(step, points); } toJSON() { return { step: this.step, points: this.points.slice(1).map((point) => { return point.toJSON(); }) }; } static fromJSON(point, json) { assert(point instanceof Point); assert(json && typeof json === 'object'); assert((json.step >>> 0) === json.step); assert(Array.isArray(json.points)); const {curve} = point; const {step} = json; const points = [point]; for (const item of json.points) points.push(curve.pointFromJSON(item)); return new this(step, points); } } /** * Blinding */ class Blinding { constructor(blind, unblind) { this.blind = blind; this.unblind = unblind; } toJSON() { return { blind: this.blind.toJSON(), unblind: this.unblind.toJSON() }; } static fromJSON(point, json) { assert(point instanceof Point); assert(json && typeof json === 'object'); const {curve} = point; const blind = BN.fromJSON(json.blind); const unblind = curve.pointFromJSON(json.unblind); return new this(blind, unblind); } } /** * Endo */ class Endo { constructor(beta, lambda, basis, pre) { this.beta = beta; this.lambda = lambda; this.basis = basis; this.pre = pre; } toJSON() { return { beta: this.beta.fromRed().toJSON(), lambda: this.lambda.toJSON(), basis: [ this.basis[0].toJSON(), this.basis[1].toJSON() ], pre: [ this.pre[0], this.pre[1].toJSON(), this.pre[2].toJSON() ] }; } static fromJSON(curve, json) { assert(curve instanceof Curve); assert(json && typeof json === 'object'); assert(Array.isArray(json.basis)); assert(Array.isArray(json.pre)); assert(json.basis.length === 2); assert(json.pre.length === 3); assert((json.pre[0] >>> 0) === json.pre[0]); const beta = BN.fromJSON(json.beta).toRed(curve.red); const lambda = BN.fromJSON(json.lambda); const basis = [ Vector.fromJSON(json.basis[0]), Vector.fromJSON(json.basis[1]) ]; const pre = [ json.pre[0], BN.fromJSON(json.pre[1]), BN.fromJSON(json.pre[2]) ]; return new this(beta, lambda, basis, pre); } } /** * Vector */ class Vector { constructor(a, b) { this.a = a; this.b = b; } toJSON() { return { a: this.a.toJSON(), b: this.b.toJSON() }; } static fromJSON(json) { assert(json && typeof json === 'object'); const a = BN.fromJSON(json.a); const b = BN.fromJSON(json.b); return new this(a, b); } } /** * P192 * https://tinyurl.com/fips-186-2 (page 29) * https://tinyurl.com/fips-186-3 (page 88) */ class P192 extends ShortCurve { constructor(pre) { super({ id: 'P192', ossl: 'prime192v1', type: 'short', endian: 'be', hash: 'SHA256', prime: 'p192', // 2^192 - 2^64 - 1 (= 3 mod 4) p: ['ffffffff ffffffff ffffffff fffffffe', 'ffffffff ffffffff'], // -3 mod p a: ['ffffffff ffffffff ffffffff fffffffe', 'ffffffff fffffffc'], b: ['64210519 e59c80e7 0fa7e9ab 72243049', 'feb8deec c146b9b1'], n: ['ffffffff ffffffff ffffffff 99def836', '146bc9b1 b4d22831'], h: '1', // Icart z: '-5', g: [ ['188da80e b03090f6 7cbf20eb 43a18800', 'f4ff0afd 82ff1012'], ['07192b95 ffc8da78 631011ed 6b24cdd5', '73f977a1 1e794811'], pre ] }); } } /** * P224 * https://tinyurl.com/fips-186-2 (page 30) * https://tinyurl.com/fips-186-3 (page 88) */ class P224 extends ShortCurve { constructor(pre) { super({ id: 'P224', ossl: 'secp224r1', type: 'short', endian: 'be', hash: 'SHA256', prime: 'p224', // 2^224 - 2^96 + 1 (1 mod 16) p: ['ffffffff ffffffff ffffffff ffffffff', '00000000 00000000 00000001'], // -3 mod p a: ['ffffffff ffffffff ffffffff fffffffe', 'ffffffff ffffffff fffffffe'], b: ['b4050a85 0c04b3ab f5413256 5044b0b7', 'd7bfd8ba 270b3943 2355ffb4'], n: ['ffffffff ffffffff ffffffff ffff16a2', 'e0b8f03e 13dd2945 5c5c2a3d'], h: '1', // SSWU z: '1f', g: [ ['b70e0cbd 6bb4bf7f 321390b9 4a03c1d3', '56c21122 343280d6 115c1d21'], ['bd376388 b5f723fb 4c22dfe6 cd4375a0', '5a074764 44d58199 85007e34'], pre ] }); } } /** * P256 * https://tinyurl.com/fips-186-2 (page 31) * https://tinyurl.com/fips-186-3 (page 89) */ class P256 extends ShortCurve { constructor(pre) { super({ id: 'P256', ossl: 'prime256v1', type: 'short', endian: 'be', hash: 'SHA256', prime: null, // 2^256 - 2^224 + 2^192 + 2^96 - 1 (= 3 mod 4) p: ['ffffffff 00000001 00000000 00000000', '00000000 ffffffff ffffffff ffffffff'], // -3 mod p a: ['ffffffff 00000001 00000000 00000000', '00000000 ffffffff ffffffff fffffffc'], b: ['5ac635d8 aa3a93e7 b3ebbd55 769886bc', '651d06b0 cc53b0f6 3bce3c3e 27d2604b'], n: ['ffffffff 00000000 ffffffff ffffffff', 'bce6faad a7179e84 f3b9cac2 fc632551'], h: '1', // SSWU z: '-a', g: [ ['6b17d1f2 e12c4247 f8bce6e5 63a440f2', '77037d81 2deb33a0 f4a13945 d898c296'], ['4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16', '2bce3357 6b315ece cbb64068 37bf51f5'], pre ] }); } } /** * P384 * https://tinyurl.com/fips-186-2 (page 32) * https://tinyurl.com/fips-186-3 (page 89) */ class P384 extends ShortCurve { constructor(pre) { super({ id: 'P384', ossl: 'secp384r1', type: 'short', endian: 'be', hash: 'SHA384', prime: null, // 2^384 - 2^128 - 2^96 + 2^32 - 1 (= 3 mod 4) p: ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff fffffffe', 'ffffffff 00000000 00000000 ffffffff'], // -3 mod p a: ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff fffffffe', 'ffffffff 00000000 00000000 fffffffc'], b: ['b3312fa7 e23ee7e4 988e056b e3f82d19', '181d9c6e fe814112 0314088f 5013875a', 'c656398d 8a2ed19d 2a85c8ed d3ec2aef'], n: ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff c7634d81 f4372ddf', '581a0db2 48b0a77a ecec196a ccc52973'], h: '1', // Icart z: '-c', g: [ ['aa87ca22 be8b0537 8eb1c71e f320ad74', '6e1d3b62 8ba79b98 59f741e0 82542a38', '5502f25d bf55296c 3a545e38 72760ab7'], ['3617de4a 96262c6f 5d9e98bf 9292dc29', 'f8f41dbd 289a147c e9da3113 b5f0b8c0', '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f'], pre ] }); } } /** * P521 * https://tinyurl.com/fips-186-2 (page 33) * https://tinyurl.com/fips-186-3 (page 90) */ class P521 extends ShortCurve { constructor(pre) { super({ id: 'P521', ossl: 'secp521r1', type: 'short', endian: 'be', hash: 'SHA512', prime: 'p521', // 2^521 - 1 (= 3 mod 4) p: ['000001ff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff'], // -3 mod p a: ['000001ff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'fffffffc'], b: ['00000051 953eb961 8e1c9a1f 929a21a0', 'b68540ee a2da725b 99b315f3 b8b48991', '8ef109e1 56193951 ec7e937b 1652c0bd', '3bb1bf07 3573df88 3d2c34f1 ef451fd4', '6b503f00'], n: ['000001ff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'fffffffa 51868783 bf2f966b 7fcc0148', 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e', '91386409'], h: '1', // SSWU z: '-4', g: [ ['000000c6 858e06b7 0404e9cd 9e3ecb66', '2395b442 9c648139 053fb521 f828af60', '6b4d3dba a14b5e77 efe75928 fe1dc127', 'a2ffa8de 3348b3c1 856a429b f97e7e31', 'c2e5bd66'], ['00000118 39296a78 9a3bc004 5c8a5fb4', '2c7d1bd9 98f54449 579b4468 17afbd17', '273e662c 97ee7299 5ef42640 c550b901', '3fad0761 353c7086 a272c240 88be9476', '9fd16650'], pre ] }); } } /** * SECP256K1 * https://www.secg.org/SEC2-Ver-1.0.pdf (page 15, section 2.7.1) * https://www.secg.org/sec2-v2.pdf (page 9, section 2.4.1) */ class SECP256K1 extends ShortCurve { constructor(pre) { super({ id: 'SECP256K1', ossl: 'secp256k1', type: 'short', endian: 'be', hash: 'SHA256', prime: 'k256', // 2^256 - 2^32 - 977 (= 3 mod 4) p: ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff fffffffe fffffc2f'], a: '0', b: '7', n: ['ffffffff ffffffff ffffffff fffffffe', 'baaedce6 af48a03b bfd25e8c d0364141'], h: '1', // SVDW z: '1', // sqrt(-3) c: ['0a2d2ba9 3507f1df 233770c2 a797962c', 'c61f6d15 da14ecd4 7d8d27ae 1cd5f852'], g: [ ['79be667e f9dcbbac 55a06295 ce870b07', '029bfcdb 2dce28d9 59f2815b 16f81798'], ['483ada77 26a3c465 5da4fbfc 0e1108a8', 'fd17b448 a6855419 9c47d08f fb10d4b8'], pre ], // Precomputed endomorphism. endo: { beta: ['7ae96a2b 657c0710 6e64479e ac3434e9', '9cf04975 12f58995 c1396c28 719501ee'], lambda: ['5363ad4c c05c30e0 a5261c02 8812645a', '122e22ea 20816678 df02967c 1b23bd72'], basis: [ { a: '3086d221a7d46bcde86c90e49284eb15', b: '-e4437ed6010e88286f547fa90abfe4c3' }, { a: '114ca50f7a8e2f3f657c1108d9d44cfd8', b: '3086d221a7d46bcde86c90e49284eb15' } ], pre: [ 384, ['3086d221 a7d46bcd e86c90e4 9284eb15', '3daa8a14 71e8ca7f e893209a 45dbb031'], ['-', 'e4437ed6 010e8828 6f547fa9 0abfe4c4', '221208ac 9df506c6 1571b4ae 8ac47f71'] ] } }); } } /** * BRAINPOOLP256 * https://tools.ietf.org/html/rfc5639#section-3.4 */ class BRAINPOOLP256 extends ShortCurve { constructor(pre) { super({ id: 'BRAINPOOLP256', ossl: 'brainpoolP256r1', type: 'short', endian: 'be', hash: 'SHA256', prime: null, // (= 3 mod 4) p: ['a9fb57db a1eea9bc 3e660a90 9d838d72', '6e3bf623 d5262028 2013481d 1f6e5377'], a: ['7d5a0975 fc2c3057 eef67530 417affe7', 'fb8055c1 26dc5c6c e94a4b44 f330b5d9'], b: ['26dc5c6c e94a4b44 f330b5d9 bbd77cbf', '95841629 5cf7e1ce 6bccdc18 ff8c07b6'], n: ['a9fb57db a1eea9bc 3e660a90 9d838d71', '8c397aa3 b561a6f7 901e0e82 974856a7'], h: '1', // Icart z: '-2', g: [ ['8bd2aeb9 cb7e57cb 2c4b482f fc81b7af', 'b9de27e1 e3bd23c2 3a4453bd 9ace3262'], ['547ef835 c3dac4fd 97f8461a 14611dc9', 'c2774513 2ded8e54 5c1d54c7 2f046997'], pre ] }); } } /** * BRAINPOOLP384 * https://tools.ietf.org/html/rfc5639#section-3.6 */ class BRAINPOOLP384 extends ShortCurve { constructor(pre) { super({ id: 'BRAINPOOLP384', ossl: 'brainpoolP384r1', type: 'short', endian: 'be', hash: 'SHA384', prime: null, // (= 3 mod 4) p: ['8cb91e82 a3386d28 0f5d6f7e 50e641df', '152f7109 ed5456b4 12b1da19 7fb71123', 'acd3a729 901d1a71 87470013 3107ec53'], a: ['7bc382c6 3d8c150c 3c72080a ce05afa0', 'c2bea28e 4fb22787 139165ef ba91f90f', '8aa5814a 503ad4eb 04a8c7dd 22ce2826'], b: ['04a8c7dd 22ce2826 8b39b554 16f0447c', '2fb77de1 07dcd2a6 2e880ea5 3eeb62d5', '7cb43902 95dbc994 3ab78696 fa504c11'], n: ['8cb91e82 a3386d28 0f5d6f7e 50e641df', '152f7109 ed5456b3 1f166e6c ac0425a7', 'cf3ab6af 6b7fc310 3b883202 e9046565'], h: '1', // SSWU z: '-5', g: [ ['1d1c64f0 68cf45ff a2a63a81 b7c13f6b', '8847a3e7 7ef14fe3 db7fcafe 0cbd10e8', 'e826e034 36d646aa ef87b2e2 47d4af1e'], ['8abe1d75 20f9c2a4 5cb1eb8e 95cfd552', '62b70b29 feec5864 e19c054f f9912928', '0e464621 77918111 42820341 263c5315'], pre ] }); } } /** * BRAINPOOLP512 * https://tools.ietf.org/html/rfc5639#section-3.7 */ class BRAINPOOLP512 extends ShortCurve { constructor(pre) { super({ id: 'BRAINPOOLP512', ossl: 'brainpoolP512r1', type: 'short', endian: 'be', hash: 'SHA512', prime: null, // (= 3 mod 4) p: ['aadd9db8 dbe9c48b 3fd4e6ae 33c9fc07', 'cb308db3 b3c9d20e d6639cca 70330871', '7d4d9b00 9bc66842 aecda12a e6a380e6', '2881ff2f 2d82c685 28aa6056 583a48f3'], a: ['7830a331 8b603b89 e2327145 ac234cc5', '94cbdd8d 3df91610 a83441ca ea9863bc', '2ded5d5a a8253aa1 0a2ef1c9 8b9ac8b5', '7f1117a7 2bf2c7b9 e7c1ac4d 77fc94ca'], b: ['3df91610 a83441ca ea9863bc 2ded5d5a', 'a8253aa1 0a2ef1c9 8b9ac8b5 7f1117a7', '2bf2c7b9 e7c1ac4d 77fc94ca dc083e67', '984050b7 5ebae5dd 2809bd63 8016f723'], n: ['aadd9db8 dbe9c48b 3fd4e6ae 33c9fc07', 'cb308db3 b3c9d20e d6639cca 70330870', '553e5c41 4ca92619 41866119 7fac1047', '1db1d381 085ddadd b5879682 9ca90069'], h: '1', // Icart z: '7', g: [ ['81aee4bd d82ed964 5a21322e 9c4c6a93', '85ed9f70 b5d916c1 b43b62ee f4d0098e', 'ff3b1f78 e2d0d48d 50d1687b 93b97d5f', '7c6d5047 406a5e68 8b352209 bcb9f822'], ['7dde385d 566332ec c0eabfa9 cf7822fd', 'f209f700 24a57b1a a000c55b 881f8111', 'b2dcde49 4a5f485e 5bca4bd8 8a2763ae', 'd1ca2b2f a8f05406 78cd1e0f 3ad80892'], pre ] }); } } /** * X25519 * https://tools.ietf.org/html/rfc7748#section-4.1 */ class X25519 extends MontCurve { constructor() { super({ id: 'X25519', ossl: 'X25519', type: 'mont', endian: 'le', hash: 'SHA512', prime: 'p25519', // 2^255 - 19 (= 5 mod 8) p: ['7fffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff ffffffed'], // 486662 a: '76d06', b: '1', n: ['10000000 00000000 00000000 00000000', '14def9de a2f79cd6 5812631a 5cf5d3ed'], h: '8', // Elligator 2 z: '2', g: [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000009'], // See: https://www.rfc-editor.org/errata/eid4730 ['5f51e65e 475f794b 1fe122d3 88b72eb3', '6dc2b281 92839e4d d6163a5d 81312c14'] ], torsion: [ [], [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000'], ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000'] ], [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000001'], ['6be4f497 f9a9c2af c21fa77a d7f4a6ef', '635a11c7 284a9363 e9a248ef 9c884415'] ], [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000001'], ['141b0b68 06563d50 3de05885 280b5910', '9ca5ee38 d7b56c9c 165db710 6377bbd8'] ], [ ['57119fd0 dd4e22d8 868e1c58 c45c4404', '5bef839c 55b1d0b1 248c50a3 bc959c5f'], ['68c59389 3d458e64 31c6ca00 45fb5015', '20a44346 8eaa68dd 0f103842 048065b7'] ], [ ['57119fd0 dd4e22d8 868e1c58 c45c4404', '5bef839c 55b1d0b1 248c50a3 bc959c5f'], ['173a6c76 c2ba719b ce3935ff ba04afea', 'df5bbcb9 71559722 f0efc7bd fb7f9a36'] ], [ ['00b8495f 16056286 fdb1329c eb8d09da', '6ac49ff1 fae35616 aeb8413b 7c7aebe0'], ['3931c129 569e83a5 29482c14 e628b457', '933bfc29 ed801b4d 68871483 92507b1a'] ], [ ['00b8495f 16056286 fdb1329c eb8d09da', '6ac49ff1 fae35616 aeb8413b 7c7aebe0'], ['46ce3ed6 a9617c5a d6b7d3eb 19d74ba8', '6cc403d6 127fe4b2 9778eb7c 6daf84d3'] ] ] }); } } /** * X448 * https://tools.ietf.org/html/rfc7748#section-4.2 */ class X448 extends MontCurve { constructor() { super({ id: 'X448', ossl: 'X448', type: 'mont', endian: 'le', hash: 'SHAKE256', prime: 'p448', // 2^448 - 2^224 - 1 (= 3 mod 4) p: ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff fffffffe ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff'], // 156326 a: '262a6', b: '1', n: ['3fffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff 7cca23e9', 'c44edb49 aed63690 216cc272 8dc58f55', '2378c292 ab5844f3'], h: '4', // Elligator 2 z: '-1', g: [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000005'], ['7d235d12 95f5b1f6 6c98ab6e 58326fce', 'cbae5d34 f55545d0 60f75dc2 8df3f6ed', 'b8027e23 46430d21 1312c4b1 50677af7', '6fd7223d 457b5b1a'] ], torsion: [ [], [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000'], ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000'] ], [ ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff fffffffe ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff fffffffe'], ['ba4d3a08 29b6112f 8812e51b a0bb2abe', 'bc1cb08e b48e5569 36ba50fd d2e7d68a', 'f8cb3216 0522425b 3f990812 abbe635a', 'd37a21e1 7551b193'] ], [ ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff fffffffe ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff fffffffe'], ['45b2c5f7 d649eed0 77ed1ae4 5f44d541', '43e34f71 4b71aa96 c945af01 2d182975', '0734cde9 faddbda4 c066f7ed 54419ca5', '2c85de1e 8aae4e6c'] ] ] }); } } /** * MONT448 * Isomorphic to Ed448-Goldilocks. */ class MONT448 extends MontCurve { constructor() { super({ id: 'MONT448', ossl: null, type: 'mont', endian: 'le', hash: 'SHAKE256', prime: 'p448', // 2^448 - 2^224 - 1 (= 3 mod 4) p: ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff fffffffe ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff'], // -78160 / -39082 mod p a: ['b2cf97d2 d43459a9 31ed36b1 fc4e3cb5', '5d93f8d2 22746997 60ccffc6 49961ed6', 'c5b05fca c24864ed 6fb59697 931b78da', '84ddecd8 ca2b5cfb'], b: '1', n: ['3fffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff 7cca23e9', 'c44edb49 aed63690 216cc272 8dc58f55', '2378c292 ab5844f3'], h: '4', // Elligator 2 z: '-1', g: [ ['ac0d24cc c6c75cb0 eb71f81e 7a6edf51', '48e88aee 009a2a24 e795687e c28e125a', '3e6730a6 0d46367b aa7fe99d 152128dc', '41321bc7 7817f059'], ['5a4437f6 80c0d0db 9b061276 d5d0ffcc', 'e786ff33 b6a53d30 98746425 82e66f09', '4433dae7 7244a6e2 6b11e905 7228f483', '556c41a5 913f55fe'] ], torsion: [ [], [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000'], ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000'] ], [ ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff fffffffe ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff fffffffe'], ['bec92fd0 6da2acf2 b4e261e8 7cef0d34', '22e75c18 3c589857 b71924e5 73c2f9ce', 'e18da5f2 466e2f39 3c2eedf0 f105a60a', 'b40c717d 4f1e1fd7'] ], [ ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff fffffffe ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff fffffffe'], ['4136d02f 925d530d 4b1d9e17 8310f2cb', 'dd18a3e7 c3a767a8 48e6db19 8c3d0631', '1e725a0d b991d0c6 c3d1120f 0efa59f5', '4bf38e82 b0e1e028'] ] ] }); } } /** * ED25519 * https://tools.ietf.org/html/rfc8032#section-5.1 */ class ED25519 extends EdwardsCurve { constructor(pre) { super({ id: 'ED25519', ossl: 'ED25519', type: 'edwards', endian: 'le', hash: 'SHA512', prefix: 'SigEd25519 no Ed25519 collisions', context: false, prime: 'p25519', // 2^255 - 19 (= 5 mod 8) p: ['7fffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff ffffffed'], a: '-1', // -121665 / 121666 mod p d: ['52036cee 2b6ffe73 8cc74079 7779e898', '00700a4d 4141d8ab 75eb4dca 135978a3'], n: ['10000000 00000000 00000000 00000000', '14def9de a2f79cd6 5812631a 5cf5d3ed'], h: '8', // Elligator 2 z: '2', g: [ ['216936d3 cd6e53fe c0a4e231 fdd6dc5c', '692cc760 9525a7b2 c9562d60 8f25d51a'], // 4/5 ['66666666 66666666 66666666 66666666', '66666666 66666666 66666666 66666658'], pre ], torsion: [ [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000'], ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000001'] ], [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000'], ['7fffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff ffffffec'] ], [ ['2b832480 4fc1df0b 2b4d0099 3dfbd7a7', '2f431806 ad2fe478 c4ee1b27 4a0ea0b0'], ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000'] ], [ ['547cdb7f b03e20f4 d4b2ff66 c2042858', 'd0bce7f9 52d01b87 3b11e4d8 b5f15f3d'], ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000'] ], [ ['1fd5b9a0 06394a28 e9339932 38de4abb', '5c193c70 13e5e238 dea14646 c545d14a'], ['05fc536d 880238b1 3933c6d3 05acdfd5', 'f098eff2 89f4c345 b027b2c2 8f95e826'] ], [ ['602a465f f9c6b5d7 16cc66cd c721b544', 'a3e6c38f ec1a1dc7 215eb9b9 3aba2ea3'], ['05fc536d 880238b1 3933c6d3 05acdfd5', 'f098eff2 89f4c345 b027b2c2 8f95e826'] ], [ ['1fd5b9a0 06394a28 e9339932 38de4abb', '5c193c70 13e5e238 dea14646 c545d14a'], ['7a03ac92 77fdc74e c6cc392c fa53202a', '0f67100d 760b3cba 4fd84d3d 706a17c7'] ], [ ['602a465f f9c6b5d7 16cc66cd c721b544', 'a3e6c38f ec1a1dc7 215eb9b9 3aba2ea3'], ['7a03ac92 77fdc74e c6cc392c fa53202a', '0f67100d 760b3cba 4fd84d3d 706a17c7'] ] ] }); } } /** * ISO448 * https://tools.ietf.org/html/rfc7748#section-4.2 * https://git.zx2c4.com/goldilocks/tree/_aux/ristretto/ristretto.sage#n658 */ class ISO448 extends EdwardsCurve { constructor(pre) { super({ id: 'ISO448', ossl: null, type: 'edwards', endian: 'le', hash: 'SHAKE256', prefix: 'SigEd448', context: true, prime: 'p448', // 2^448 - 2^224 - 1 (= 3 mod 4) p: ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff fffffffe ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff'], a: '1', // 39082 / 39081 mod p d: ['d78b4bdc 7f0daf19 f24f38c2 9373a2cc', 'ad461572 42a50f37 809b1da3 412a12e7', '9ccc9c81 264cfe9a d0809970 58fb61c4', '243cc32d baa156b9'], n: ['3fffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff 7cca23e9', 'c44edb49 aed63690 216cc272 8dc58f55', '2378c292 ab5844f3'], h: '4', // Elligator 2 z: '-1', g: [ ['79a70b2b 70400553 ae7c9df4 16c792c6', '1128751a c9296924 0c25a07d 728bdc93', 'e21f7787 ed697224 9de732f3 8496cd11', '69871309 3e9c04fc'], // Note: the RFC has this wrong. ['7fffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff 80000000', '00000000 00000000 00000000 00000000', '00000000 00000001'], pre ], torsion: [ [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000'], ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000001'] ], [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000'], ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff fffffffe ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff fffffffe'] ], [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000001'], ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000'] ], [ ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff fffffffe ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff fffffffe'], ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000'] ] ] }); } } /** * ED448 * https://tools.ietf.org/html/rfc8032#section-5.2 */ class ED448 extends EdwardsCurve { constructor(pre) { super({ id: 'ED448', ossl: 'ED448', type: 'edwards', endian: 'le', hash: 'SHAKE256', prefix: 'SigEd448', context: true, prime: 'p448', // 2^448 - 2^224 - 1 (= 3 mod 4) p: ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff fffffffe ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff'], a: '1', // -39081 mod p d: ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff fffffffe ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffff6756'], n: ['3fffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff ffffffff 7cca23e9', 'c44edb49 aed63690 216cc272 8dc58f55', '2378c292 ab5844f3'], h: '4', // Elligator 2 z: '-1', g: [ ['4f1970c6 6bed0ded 221d15a6 22bf36da', '9e146570 470f1767 ea6de324 a3d3a464', '12ae1af7 2ab66511 433b80e1 8b00938e', '2626a82b c70cc05e'], ['693f4671 6eb6bc24 88762037 56c9c762', '4bea7373 6ca39840 87789c1e 05a0c2d7', '3ad3ff1c e67c39c4 fdbd132c 4ed7c8ad', '9808795b f230fa14'], pre ], torsion: [ [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000'], ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000001'] ], [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000'], ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff fffffffe ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff fffffffe'] ], [ ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000001'], ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000'] ], [ ['ffffffff ffffffff ffffffff ffffffff', 'ffffffff ffffffff fffffffe ffffffff', 'ffffffff ffffffff ffffffff ffffffff', 'ffffffff fffffffe'], ['00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000 00000000 00000000', '00000000 00000000'] ] ] }); } } /* * Curve Registry */ const curves = { __proto__: null, P192, P224, P256, P384, P521, SECP256K1, BRAINPOOLP256, BRAINPOOLP384, BRAINPOOLP512, X25519, X448, MONT448, ED25519, ISO448, ED448 }; const cache = { __proto__: null, P192: null, P224: null, P256: null, P384: null, P521: null, SECP256K1: null, BRAINPOOLP256: null, BRAINPOOLP384: null, BRAINPOOLP512: null, X25519: null, X448: null, MONT448: null, ED25519: null, ISO448: null, ED448: null }; function curve(name, ...args) { assert(typeof name === 'string'); const key = name.toUpperCase(); let curve = cache[key]; if (!curve) { const Curve = curves[key]; if (!Curve) throw new Error(`Curve not found: "${name}".`); curve = new Curve(...args); cache[key] = curve; } return curve; } function register(name, Curve) { assert(typeof name === 'string'); assert(typeof Curve === 'function'); const key = name.toUpperCase(); if (curves[key]) throw new Error(`Curve already registered: "${name}".`); curves[key] = Curve; cache[key] = null; } /* * Scalar Recoding */ function getNAF(k, width, max) { // Computing the width-w NAF of a positive integer. // // [GECC] Algorithm 3.35, Page 100, Section 3.3. // // The above document describes a rather abstract // method of recoding. The more optimal method // below was ported from libsecp256k1. assert(k instanceof BN); assert(!k.red); assert((width >>> 0) === width); assert((max >>> 0) === max); const naf = new Array(max); const bits = k.bitLength() + 1; const sign = k.sign() | 1; assert(bits <= max); for (let i = 0; i < max; i++) naf[i] = 0; let i = 0; let carry = 0; let word; while (i < bits) { if (k.bit(i) === carry) { i += 1; continue; } word = k.bits(i, width) + carry; carry = (word >> (width - 1)) & 1; word -= carry << width; naf[i] = sign * word; i += width; } assert(carry === 0); return naf; } function getFixedNAF(k, width, max, step) { assert((step >>> 0) === step); // Recode to NAF. const naf = getNAF(k, width, max); // Translate into more windowed form. const len = Math.ceil(naf.length / step); const repr = new Array(len); let i = 0; for (let j = 0; j < naf.length; j += step) { let nafW = 0; for (let k = j + step - 1; k >= j; k--) nafW = (nafW << 1) + naf[k]; repr[i++] = nafW; } assert(i === len); return repr; } function getJSF(k1, k2, max) { // Joint sparse form. // // [GECC] Algorithm 3.50, Page 111, Section 3.3. assert(k1 instanceof BN); assert(k2 instanceof BN); assert(!k1.red); assert(!k2.red); assert((max >>> 0) === max); const jsf = [new Array(max), new Array(max)]; const bits = Math.max(k1.bitLength(), k2.bitLength()) + 1; const s1 = k1.sign() | 1; const s2 = k2.sign() | 1; assert(bits <= max); let d1 = 0; let d2 = 0; for (let i = 0; i < bits; i++) { const b1 = k1.bits(i, 3); const b2 = k2.bits(i, 3); // First phase. let m14 = ((b1 & 3) + d1) & 3; let m24 = ((b2 & 3) + d2) & 3; let u1 = 0; let u2 = 0; if (m14 === 3) m14 = -1; if (m24 === 3) m24 = -1; if (m14 & 1) { const m8 = ((b1 & 7) + d1) & 7; if ((m8 === 3 || m8 === 5) && m24 === 2) u1 = -m14; else u1 = m14; } if (m24 & 1) { const m8 = ((b2 & 7) + d2) & 7; if ((m8 === 3 || m8 === 5) && m14 === 2) u2 = -m24; else u2 = m24; } jsf[0][i] = u1 * s1; jsf[1][i] = u2 * s2; // Second phase. if (2 * d1 === 1 + u1) d1 = 1 - d1; if (2 * d2 === 1 + u2) d2 = 1 - d2; } for (let i = bits; i < max; i++) { jsf[0][i] = 0; jsf[1][i] = 0; } return jsf; } function getJNAF(c1, c2, max) { const jsf = getJSF(c1, c2, max); const naf = new Array(max); // JSF -> NAF conversion. for (let i = 0; i < max; i++) { const ja = jsf[0][i]; const jb = jsf[1][i]; naf[i] = jsfIndex[(ja + 1) * 3 + (jb + 1)]; } return naf; } /* * Helpers */ function assert(val, msg) { if (!val) { const err = new Error(msg || 'Assertion failed'); if (Error.captureStackTrace) Error.captureStackTrace(err, assert); throw err; } } function wrapErrors(fn) { assert(typeof fn === 'function'); try { return fn(); } catch (e) { if (e.message === 'X is not a square mod P.' || e.message === 'Not invertible.') { throw new Error('Invalid point.'); } throw e; } } function mod(x, y) { // Euclidean modulo. let r = x % y; if (r < 0) { if (y < 0) r -= y; else r += y; } return r; } function cubeRoot(x) { assert(x instanceof BN); assert(x.red); const p = x.red.m; if (p.cmpn(3) <= 0) return x.clone(); // p = 2 mod 3 if (p.modrn(3) === 2) { // e = (2 * p - 1) / 3 const e = p.ushln(1).isubn(1).idivn(3); return x.redPow(e); } const mod9 = p.modrn(9); // p = 4 mod 9 if (mod9 === 4) { // e = (2 * p + 1) / 9 const e = p.ushln(1).iaddn(1).idivn(9); const r = x.redPow(e); const c = r.redSqr().redMul(r); if (!c.eq(x)) throw new Error('X is not a cube mod P.'); return r; } // p = 7 mod 9 if (mod9 === 7) { // e = (p + 2) / 9 const e = p.addn(2).idivn(9); const r = x.redPow(e); const c = r.redSqr().redMul(r); if (!c.eq(x)) throw new Error('X is not a cube mod P.'); return r; } throw new Error('Not implemented.'); } function cubeRoots(x) { const r0 = cubeRoot(x); // p = 1 mod 3 if (x.red.m.modrn(3) === 1) { // Multiply by roots of unity to find other roots. const two = new BN(2).toRed(x.red); const three = new BN(3).toRed(x.red); const i2 = two.redInvert(); const s1 = three.redNeg().redSqrt().redMul(i2); const s2 = s1.redNeg(); const u1 = s1.redSub(i2); const u2 = s2.redSub(i2); const r1 = r0.redMul(u1); const r2 = r0.redMul(u2); return [r0, r1, r2]; } // p = 2 mod 3 guarantees 1 cube root per element. return [r0]; } function uncube(x) { // Find a cube root which is also a quadratic residue. for (const root of cubeRoots(x)) { if (root.redJacobi() >= 0) return root; } throw new Error('X^(1/3) is not a square mod P.'); } function randomInt(rng) { return BN.randomBits(rng, 32).toNumber(); } function memoize(method, self) { const cache = new WeakMap(); return function memoized(curve, invert) { const i = invert & 1; const item = cache.get(curve); if (item && item[i] !== null) return item[i]; const result = method.call(self, curve, invert); if (!cache.has(curve)) cache.set(curve, [null, null]); cache.get(curve)[i] = result; return result; }; } function toPretty(x, size) { assert(x instanceof BN); assert((size >>> 0) === size); if (size & 7) size += 8 - (size & 7); const str = x.toString(16, size); const chunks = []; const out = []; assert((str.length & 7) === 0); for (let i = 0; i < str.length; i += 8) chunks.push(str.slice(i, i + 8)); for (let i = 0; i < chunks.length; i += 4) out.push(chunks.slice(i, i + 4).join(' ')); return out; } /* * Expose */ exports.Curve = Curve; exports.Point = Point; exports.ShortCurve = ShortCurve; exports.ShortPoint = ShortPoint; exports.JPoint = JPoint; exports.MontCurve = MontCurve; exports.MontPoint = MontPoint; exports.XPoint = XPoint; exports.EdwardsCurve = EdwardsCurve; exports.EdwardsPoint = EdwardsPoint; exports.curves = curves; exports.curve = curve; exports.register = register; }], [/* 43 */ 'bcrypto', '/lib/js/precomputed/secp256k1.json', function(exports, module, __filename, __dirname, __meta) { module.exports = { "naf": { "width": 9, "points": [ [ "f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9", "388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672" ], [ "2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4", "d8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6" ], [ "5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc", "6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da" ], [ "acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe", "cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37" ], [ "774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb", "d984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b" ], [ "f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8", "0ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81" ], [ "d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e", "581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58" ], [ "defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34", "4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77" ], [ "2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c", "85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a" ], [ "352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5", "321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c" ], [ "2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f", "02de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67" ], [ "9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714", "73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402" ], [ "daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729", "a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55" ], [ "c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db", "2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482" ], [ "6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4", "e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82" ], [ "1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5", "b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396" ], [ "605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479", "02972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49" ], [ "62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d", "80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf" ], [ "80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f", "1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a" ], [ "7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb", "0d0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7" ], [ "d528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9", "eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933" ], [ "049370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963", "758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a" ], [ "77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74", "958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6" ], [ "f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530", "e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37" ], [ "463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b", "5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e" ], [ "f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247", "cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6" ], [ "caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1", "cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476" ], [ "2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120", "4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40" ], [ "7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435", "091b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61" ], [ "754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18", "0673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683" ], [ "e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8", "59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5" ], [ "186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb", "3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b" ], [ "df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f", "55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417" ], [ "5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143", "efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868" ], [ "290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba", "e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a" ], [ "af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45", "f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6" ], [ "766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a", "744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996" ], [ "59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e", "c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e" ], [ "f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8", "e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d" ], [ "7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c", "30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2" ], [ "948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519", "e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e" ], [ "7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab", "100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437" ], [ "3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca", "ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311" ], [ "d3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf", "8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4" ], [ "1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610", "68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575" ], [ "733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4", "f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d" ], [ "15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c", "d56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d" ], [ "a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940", "edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629" ], [ "e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980", "0a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06" ], [ "311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3", "66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374" ], [ "34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf", "09414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee" ], [ "f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63", "4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1" ], [ "d7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448", "fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b" ], [ "32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf", "5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661" ], [ "7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5", "8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6" ], [ "ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6", "8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e" ], [ "16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5", "5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d" ], [ "eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99", "f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc" ], [ "078c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51", "f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4" ], [ "494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5", "42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c" ], [ "a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5", "204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b" ], [ "c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997", "04f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913" ], [ "841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881", "073867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154" ], [ "5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5", "39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865" ], [ "36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66", "d2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc" ], [ "0336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726", "ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224" ], [ "8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede", "6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e" ], [ "1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94", "060660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6" ], [ "85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31", "3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511" ], [ "29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51", "0b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b" ], [ "a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252", "ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2" ], [ "04e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5", "cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c" ], [ "d24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b", "6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3" ], [ "ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4", "322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d" ], [ "af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f", "6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700" ], [ "e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889", "2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4" ], [ "591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246", "b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196" ], [ "11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984", "998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4" ], [ "3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a", "b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257" ], [ "cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030", "bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13" ], [ "c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197", "6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096" ], [ "0c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593", "c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38" ], [ "a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef", "021ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f" ], [ "347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38", "60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448" ], [ "da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a", "49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a" ], [ "c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111", "5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4" ], [ "4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502", "7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437" ], [ "3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea", "be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7" ], [ "cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26", "8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d" ], [ "b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986", "39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a" ], [ "d4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e", "62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54" ], [ "48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4", "25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77" ], [ "dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda", "ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517" ], [ "6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859", "cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10" ], [ "e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f", "f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125" ], [ "eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c", "6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e" ], [ "13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942", "fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1" ], [ "ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a", "1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2" ], [ "b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80", "5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423" ], [ "ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d", "438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8" ], [ "8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1", "cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758" ], [ "52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63", "0c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375" ], [ "e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352", "6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d" ], [ "7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193", "ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec" ], [ "5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00", "09731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0" ], [ "32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58", "ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c" ], [ "e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7", "d3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4" ], [ "8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8", "c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f" ], [ "4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e", "67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649" ], [ "3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d", "0cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826" ], [ "674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b", "299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5" ], [ "d32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f", "f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87" ], [ "30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6", "462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b" ], [ "be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297", "62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc" ], [ "93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a", "7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c" ], [ "b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c", "ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f" ], [ "d5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52", "4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a" ], [ "d3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb", "bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46" ], [ "463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065", "bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f" ], [ "7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917", "603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03" ], [ "74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9", "cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08" ], [ "30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3", "553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8" ], [ "9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57", "0712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373" ], [ "176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66", "ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3" ], [ "75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8", "9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8" ], [ "809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721", "9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1" ], [ "1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180", "4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9" ] ] }, "doubles": { "step": 4, "points": [ [ "e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", "f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821" ], [ "8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508", "11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf" ], [ "175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739", "d3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695" ], [ "363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640", "04e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9" ], [ "8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c", "4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36" ], [ "723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda", "96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f" ], [ "eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa", "5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999" ], [ "100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0", "cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09" ], [ "e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d", "9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d" ], [ "feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d", "e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088" ], [ "da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1", "9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d" ], [ "53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0", "5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8" ], [ "8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047", "10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a" ], [ "385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862", "283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453" ], [ "06f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7", "7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160" ], [ "3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd", "56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0" ], [ "85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83", "7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6" ], [ "0948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a", "53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589" ], [ "6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8", "bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17" ], [ "e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d", "4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda" ], [ "e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725", "7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd" ], [ "213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754", "4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2" ], [ "4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c", "17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6" ], [ "fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6", "6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f" ], [ "76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39", "c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01" ], [ "c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891", "893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3" ], [ "d895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b", "febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f" ], [ "b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03", "2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7" ], [ "e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d", "eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78" ], [ "a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070", "7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1" ], [ "90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4", "0e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150" ], [ "8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da", "662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82" ], [ "e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11", "1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc" ], [ "8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e", "efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b" ], [ "e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41", "2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51" ], [ "b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef", "067c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45" ], [ "d68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8", "db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120" ], [ "324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d", "648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84" ], [ "4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96", "35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d" ], [ "9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd", "ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d" ], [ "6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5", "9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8" ], [ "a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266", "40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8" ], [ "7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71", "34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac" ], [ "0928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac", "c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f" ], [ "85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751", "1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962" ], [ "ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e", "493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907" ], [ "827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241", "c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec" ], [ "eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3", "be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d" ], [ "e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f", "4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414" ], [ "1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19", "aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd" ], [ "146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be", "b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0" ], [ "fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9", "6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811" ], [ "da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2", "8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1" ], [ "a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13", "7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c" ], [ "174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c", "ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73" ], [ "959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba", "2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd" ], [ "d2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151", "e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405" ], [ "64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073", "d99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589" ], [ "8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458", "38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e" ], [ "13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b", "69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27" ], [ "bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366", "0d3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1" ], [ "8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa", "40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482" ], [ "08ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0", "620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945" ], [ "dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787", "7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573" ], [ "f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e", "ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82" ] ] } }; }], [/* 44 */ 'hsd', '/lib/protocol/network.js', function(exports, module, __filename, __dirname, __meta) { /*! * network.js - network object for hsd * Copyright (c) 2017-2018, Christopher Jeffrey (MIT License). * https://github.com/handshake-org/hsd */ 'use strict'; const assert = __node_require__(2 /* 'bsert' */); const binary = __node_require__(45 /* '../utils/binary' */); const networks = __node_require__(46 /* './networks' */); const TimeData = __node_require__(49 /* './timedata' */); /** * Network * Represents a network. * @alias module:protocol.Network */ class Network { /** * Create a network. * @constructor * @param {Object} options */ constructor(options) { assert(!Network[options.type], 'Cannot create two networks.'); this.type = options.type; this.seeds = options.seeds; this.magic = options.magic; this.port = options.port; this.brontidePort = options.brontidePort; this.checkpointMap = options.checkpointMap; this.lastCheckpoint = options.lastCheckpoint; this.checkpoints = []; this.halvingInterval = options.halvingInterval; this.coinbaseMaturity = options.coinbaseMaturity; this.genesis = options.genesis; this.genesisBlock = options.genesisBlock; this.pow = options.pow; this.names = options.names; this.goosigStop = options.goosigStop; this.block = options.block; this.activationThreshold = options.activationThreshold; this.minerWindow = options.minerWindow; this.deployments = options.deployments; this.deploys = options.deploys; this.unknownBits = 0; this.keyPrefix = options.keyPrefix; this.addressPrefix = options.addressPrefix; this.requireStandard = options.requireStandard; this.rpcPort = options.rpcPort; this.walletPort = options.walletPort; this.nsPort = options.nsPort; this.rsPort = options.rsPort; this.minRelay = options.minRelay; this.feeRate = options.feeRate; this.maxFeeRate = options.maxFeeRate; this.identityKey = options.identityKey; this.selfConnect = options.selfConnect; this.requestMempool = options.requestMempool; this.claimPrefix = options.claimPrefix; this.deflationHeight = options.deflationHeight; this.time = new TimeData(); this.txStart = options.txStart; this.init(); } /** * Get a deployment by bit index. * @param {Number} bit * @returns {Object} */ init() { let bits = 0; for (const deployment of this.deploys) bits |= 1 << deployment.bit; this.unknownBits = ~bits >>> 0; for (const key of Object.keys(this.checkpointMap)) { const hash = this.checkpointMap[key]; const height = Number(key); this.checkpoints.push({ hash, height }); } this.checkpoints.sort(cmpNode); } /** * Get a deployment by bit index. * @param {Number} bit * @returns {Object} */ byBit(bit) { const index = binary.search(this.deploys, bit, cmpBit); if (index === -1) return null; return this.deploys[index]; } /** * Get network adjusted time. * @returns {Number} */ now() { return this.time.now(); } /** * Get network adjusted time in milliseconds. * @returns {Number} */ ms() { return this.time.ms(); } /** * Create a network. Get existing network if possible. * @param {NetworkType|Object} options * @returns {Network} */ static create(options) { if (typeof options === 'string') options = networks[options]; assert(options, 'Unknown network.'); if (Network[options.type]) return Network[options.type]; const network = new Network(options); Network[network.type] = network; if (!Network.primary) Network.primary = network; return network; } /** * Set the default network. This network will be used * if nothing is passed as the `network` option for * certain objects. * @param {NetworkType} type - Network type. * @returns {Network} */ static set(type) { assert(typeof type === 'string', 'Bad network.'); Network.primary = Network.get(type); Network.type = type; return Network.primary; } /** * Get a network with a string or a Network object. * @param {NetworkType|Network} type - Network type. * @returns {Network} */ static get(type) { if (!type) { assert(Network.primary, 'No default network.'); return Network.primary; } if (type instanceof Network) return type; if (typeof type === 'string') return Network.create(type); throw new Error('Unknown network.'); } /** * Get a network with a string or a Network object. * @param {NetworkType|Network} type - Network type. * @returns {Network} */ static ensure(type) { if (!type) { assert(Network.primary, 'No default network.'); return Network.primary; } if (type instanceof Network) return type; if (typeof type === 'string') { if (networks[type]) return Network.create(type); } assert(Network.primary, 'No default network.'); return Network.primary; } /** * Get a network by an associated comparator. * @private * @param {Object} value * @param {Function} compare * @param {Network|null} network * @param {String} name * @returns {Network} */ static by(value, compare, network, name) { if (network) { network = Network.get(network); if (compare(network, value)) return network; throw new Error(`Network mismatch for ${name}.`); } for (const type of networks.types) { network = networks[type]; if (compare(network, value)) return Network.get(type); } throw new Error(`Network not found for ${name}.`); } /** * Get a network by its magic number. * @param {Number} value * @param {Network?} network * @returns {Network} */ static fromMagic(value, network) { return Network.by(value, cmpMagic, network, 'magic number'); } /** * Get a network by its WIF prefix. * @param {Number} value * @param {Network?} network * @returns {Network} */ static fromWIF(prefix, network) { return Network.by(prefix, cmpWIF, network, 'WIF'); } /** * Get a network by its xpubkey prefix. * @param {Number} value * @param {Network?} network * @returns {Network} */ static fromPublic(prefix, network) { return Network.by(prefix, cmpPub, network, 'xpubkey'); } /** * Get a network by its xprivkey prefix. * @param {Number} value * @param {Network?} network * @returns {Network} */ static fromPrivate(prefix, network) { return Network.by(prefix, cmpPriv, network, 'xprivkey'); } /** * Get a network by its xpubkey base58 prefix. * @param {String} prefix * @param {Network?} network * @returns {Network} */ static fromPublic58(prefix, network) { return Network.by(prefix, cmpPub58, network, 'xpubkey'); } /** * Get a network by its xprivkey base58 prefix. * @param {String} prefix * @param {Network?} network * @returns {Network} */ static fromPrivate58(prefix, network) { return Network.by(prefix, cmpPriv58, network, 'xprivkey'); } /** * Get a network by its bech32 address prefix. * @param {String} hrp * @param {Network?} network * @returns {Network} */ static fromAddress(hrp, network) { return Network.by(hrp, cmpAddress, network, 'address'); } /** * Convert the network to a string. * @returns {String} */ toString() { return this.type; } /** * Inspect the network. * @returns {String} */ inspect() { return ``; } /** * Test an object to see if it is a Network. * @param {Object} obj * @returns {Boolean} */ static isNetwork(obj) { return obj instanceof Network; } } /** * Default network. * @type {Network} */ Network.primary = null; /** * Default network type. * @type {String} */ Network.type = null; /* * Networks (to avoid hash table mode). */ Network.main = null; Network.testnet = null; Network.regtest = null; Network.segnet4 = null; Network.simnet = null; /* * Set initial network. */ Network.set(process.env.HSD_NETWORK || 'main'); /* * Helpers */ function cmpBit(a, b) { return a.bit - b; } function cmpNode(a, b) { return a.height - b.height; } function cmpMagic(network, magic) { return network.magic === magic; } function cmpWIF(network, prefix) { return network.keyPrefix.privkey === prefix; } function cmpPub(network, prefix) { return network.keyPrefix.xpubkey === prefix; } function cmpPriv(network, prefix) { return network.keyPrefix.xprivkey === prefix; } function cmpPub58(network, prefix) { return network.keyPrefix.xpubkey58 === prefix; } function cmpPriv58(network, prefix) { return network.keyPrefix.xprivkey58 === prefix; } function cmpAddress(network, hrp) { return network.addressPrefix === hrp; } /* * Expose */ module.exports = Network; }], [/* 45 */ 'hsd', '/lib/utils/binary.js', function(exports, module, __filename, __dirname, __meta) { /*! * binary.js - binary search utils for hsd * Copyright (c) 2017-2018, Christopher Jeffrey (MIT License). * https://github.com/handshake-org/hsd */ 'use strict'; /** * Perform a binary search on a sorted array. * @param {Array} items * @param {Object} key * @param {Function} compare * @param {Boolean?} insert * @returns {Number} Index. */ exports.search = function search(items, key, compare, insert) { let start = 0; let end = items.length - 1; while (start <= end) { const pos = (start + end) >>> 1; const cmp = compare(items[pos], key); if (cmp === 0) return pos; if (cmp < 0) start = pos + 1; else end = pos - 1; } if (!insert) return -1; return start; }; /** * Perform a binary insert on a sorted array. * @param {Array} items * @param {Object} item * @param {Function} compare * @returns {Number} index */ exports.insert = function insert(items, item, compare, uniq) { const i = exports.search(items, item, compare, true); if (uniq && i < items.length) { if (compare(items[i], item) === 0) return -1; } if (i === 0) items.unshift(item); else if (i === items.length) items.push(item); else items.splice(i, 0, item); return i; }; /** * Perform a binary removal on a sorted array. * @param {Array} items * @param {Object} item * @param {Function} compare * @returns {Boolean} */ exports.remove = function remove(items, item, compare) { const i = exports.search(items, item, compare, false); if (i === -1) return false; splice(items, i); return true; }; /* * Helpers */ function splice(list, i) { if (i === 0) { list.shift(); return; } let k = i + 1; while (k < list.length) list[i++] = list[k++]; list.pop(); } }], [/* 46 */ 'hsd', '/lib/protocol/networks.js', function(exports, module, __filename, __dirname, __meta) { /*! * network.js - handshake networks for hsd * Copyright (c) 2017-2018, Christopher Jeffrey (MIT License). * https://github.com/handshake-org/hsd */ /* eslint no-implicit-coercion: "off" */ 'use strict'; /** * @module protocol/networks */ const BN = __node_require__(31 /* 'bcrypto/lib/bn.js' */); const genesis = __node_require__(47 /* './genesis' */); const network = exports; /** * Network type list. * @memberof module:protocol/networks * @const {String[]} * @default */ network.types = ['main', 'testnet', 'regtest', 'simnet']; /** * Mainnet * @static * @lends module:protocol/networks * @type {Object} */ const main = {}; /** * Symbolic network type. * @const {String} * @default */ main.type = 'main'; /** * Default DNS seeds. * @const {String[]} * @default */ main.seeds = [ 'hs-mainnet.bcoin.ninja', // Christopher Jeffrey 'seed.easyhandshake.com' // Matthew Zipkin ]; /** * Packet magic number. * @const {Number} * @default */ main.magic = genesis.main.magic; /** * Default network port. * @const {Number} * @default */ main.port = 12038; /** * Default brontide port. * @const {Number} * @default */ main.brontidePort = 44806; /** * Checkpoint block list. * @const {Object} */ main.checkpointMap = { 1008: Buffer.from( '0000000000001013c28fa079b545fb805f04c496687799b98e35e83cbbb8953e', 'hex'), 2016: Buffer.from( '0000000000000424ee6c2a5d6e0da5edfc47a4a10328c1792056ee48303c3e40', 'hex'), 10000: Buffer.from( '00000000000001a86811a6f520bf67cefa03207dc84fd315f58153b28694ec51', 'hex'), 20000: Buffer.from( '0000000000000162c7ac70a582256f59c189b5c90d8e9861b3f374ed714c58de', 'hex'), 30000: Buffer.from( '0000000000000004f790862846b23c3a81585aea0fa79a7d851b409e027bcaa7', 'hex'), 40000: Buffer.from( '0000000000000002966206a40b10a575cb46531253b08dae8e1b356cfa277248', 'hex'), 50000: Buffer.from( '00000000000000020c7447e7139feeb90549bfc77a7f18d4ff28f327c04f8d6e', 'hex'), 56880: Buffer.from( '0000000000000001d4ef9ea6908bb4eb970d556bd07cbd7d06a634e1cd5bbf4e', 'hex'), 61043: Buffer.from( '00000000000000015b84385e0307370f8323420eaa27ef6e407f2d3162f1fd05', 'hex') }; /** * Last checkpoint height. * @const {Number} * @default */ main.lastCheckpoint = 61043; /** * Reward halving interval. * Roughly every 3.25 years. * @const {Number} * @default */ main.halvingInterval = 170000; /** * Number of blocks before a coinbase * spend can occur (consensus). * @const {Number} * @default */ main.coinbaseMaturity = 100; /** * Genesis block header. * @const {Object} */ main.genesis = genesis.main; /** * The network's genesis block in a hex string. * @const {String} */ main.genesisBlock = genesis.mainData; /** * POW-related constants. * @enum {Number} * @default */ main.pow = {}; /** * Default target. * @const {BN} */ main.pow.limit = new BN( '0000000000ffff00000000000000000000000000000000000000000000000000', 'hex' ); /** * Compact pow limit. * @const {Number} * @default */ main.pow.bits = 0x1c00ffff; /** * Minimum chainwork for best chain. * @const {BN} */ main.pow.chainwork = new BN( '00000000000000000000000000000000000000000000000075b5a2b7bf522d45', 'hex' ); /** * Retarget window in blocks. * @const {Number} * @default */ main.pow.targetWindow = 144; /** * Average block time. * @const {Number} * @default */ main.pow.targetSpacing = 10 * 60; /** * Average blocks per day. * @const {Number} * @default */ main.pow.blocksPerDay = ((24 * 60 * 60) / main.pow.targetSpacing) >>> 0; /** * Desired retarget period in seconds. * @const {Number} * @default */ main.pow.targetTimespan = main.pow.targetWindow * main.pow.targetSpacing; /** * Minimum actual time. * @const {Number} * @default */ main.pow.minActual = (main.pow.targetTimespan / 4) >>> 0; /** * Maximum actual time. * @const {Number} * @default */ main.pow.maxActual = main.pow.targetTimespan * 4; /** * Whether to reset target if a block * has not been mined recently. * @const {Boolean} * @default */ main.pow.targetReset = false; /** * Do not allow retargetting. * @const {Boolean} * @default */ main.pow.noRetargeting = false; /** * Prohibit all transactions until * sufficient chainwork has been accumulated. * @const {Number} */ main.txStart = 14 * main.pow.blocksPerDay; /** * Name-related constants. * @enum {Number} * @default */ main.names = { /** * Height at which the auction system activates. * Must be greater or equal to txStart. * @const {Number} */ auctionStart: 14 * main.pow.blocksPerDay, /** * Interval at which names are rolled out. * @const {Number} */ rolloutInterval: 7 * main.pow.blocksPerDay, /** * Amount of time a name is locked for after being claimed. * @const {Number} */ lockupPeriod: 30 * main.pow.blocksPerDay, /** * Time period after which names expire. * @const {Number} */ renewalWindow: (2 * 365) * main.pow.blocksPerDay, /** * Committed renewal block hashes * must be no older than this. * @const {Number} */ renewalPeriod: 182 * main.pow.blocksPerDay, /** * Committed renewal block hashes * must be at least this old. * @const {Number} */ renewalMaturity: 30 * main.pow.blocksPerDay, /** * The time window in which the * nameholders can claim reserved names. * @const {Number} */ claimPeriod: (4 * 365) * main.pow.blocksPerDay, /** * Amount of time required in between * replacement claims. * @const {Number} */ claimFrequency: 2 * main.pow.blocksPerDay, /** * Bidding time period. * @const {Number} */ biddingPeriod: 5 * main.pow.blocksPerDay, /** * Reveal time period. * @const {Number} */ revealPeriod: 10 * main.pow.blocksPerDay, /** * Interval at which the name tree is updated. * @const {Number} */ treeInterval: main.pow.blocksPerDay >>> 2, /** * Amount of time transfers are locked up for. * @const {Number} */ transferLockup: 2 * main.pow.blocksPerDay, /** * Amount of time before a transfer * or revocation is possible. * @const {Number} */ revocationDelay: 14 * main.pow.blocksPerDay, /** * Sum of total period and revocation delay. * @const {Number} */ auctionMaturity: (5 + 10 + 14) * main.pow.blocksPerDay, /** * Whether there is no weekly rollout. * @const {Boolean} */ noRollout: false, /** * Whether there are no names reserved. * @const {Boolean} */ noReserved: false }; /** * Block constants. * @enum {Number} * @default */ main.block = { /** * Safe height to start pruning. */ pruneAfterHeight: 1000, /** * Safe number of blocks to keep. */ keepBlocks: 288, /** * Age used for the time delta to * determine whether the chain is synced. */ maxTipAge: 12 * 60 * 60, /** * Height at which block processing is * slow enough that we can output * logs without spamming. */ slowHeight: 0 }; /** * Block height at which GooSig claims are * disabled. This limits risk associated * with newly discovered cryptography * attacks or social engineering attacks. * * Estimated to be disabled at 1 year + * 1 month from the start of the network * on mainnet. */ main.goosigStop = (365 + 30) * main.pow.blocksPerDay; /** * For versionbits. * @const {Number} * @default */ main.activationThreshold = 1916; /** * Confirmation window for versionbits. * @const {Number} * @default */ main.minerWindow = 2016; /** * Deployments for versionbits. * @const {Object} * @default */ main.deployments = { hardening: { name: 'hardening', bit: 0, startTime: 1581638400, // February 14th, 2020 timeout: 1707868800, // February 14th, 2024 threshold: -1, window: -1, required: false, force: false }, testdummy: { name: 'testdummy', bit: 28, startTime: 1199145601, // January 1, 2008 timeout: 1230767999, // December 31, 2008 threshold: -1, window: -1, required: false, force: true } }; /** * Deployments for versionbits (array form, sorted). * @const {Array} * @default */ main.deploys = [ main.deployments.hardening, main.deployments.testdummy ]; /** * Key prefixes. * @enum {Number} * @default */ main.keyPrefix = { privkey: 0x80, xpubkey: 0x0488b21e, xprivkey: 0x0488ade4, xpubkey58: 'xpub', xprivkey58: 'xprv', coinType: 5353 }; /** * Address prefix. * @const {String} */ main.addressPrefix = 'hs'; /** * Default value for whether the mempool * accepts non-standard transactions. * @const {Boolean} * @default */ main.requireStandard = true; /** * Default http port. * @const {Number} * @default */ main.rpcPort = 12037; /** * Default wallet port. * @const {Number} * @default */ main.walletPort = 12039; /** * Default DNS port. * @const {Number} * @default */ main.nsPort = 5349; /** * Default recursive DNS port. * @const {Number} * @default */ main.rsPort = 5350; /** * Default min relay rate. * @const {Rate} * @default */ main.minRelay = 1000; /** * Default normal relay rate. * @const {Rate} * @default */ main.feeRate = 100000; /** * Maximum normal relay rate. * @const {Rate} * @default */ main.maxFeeRate = 400000; /** * Default identity key (testing only). * @const {Buffer|null} * @default */ main.identityKey = null; /** * Whether to allow self-connection. * @const {Boolean} */ main.selfConnect = false; /** * Whether to request mempool on sync. * @const {Boolean} */ main.requestMempool = false; /** * DNSSEC ownership prefix. * @const {String} */ main.claimPrefix = 'hns-claim:'; /** * Activation height for inflation bug fix. * @const {Number} */ main.deflationHeight = 61043; /* * Testnet */ const testnet = {}; testnet.type = 'testnet'; testnet.seeds = [ 'hs-testnet.bcoin.ninja' // Christopher Jeffrey ]; testnet.magic = genesis.testnet.magic; testnet.port = 13038; testnet.brontidePort = 45806; testnet.checkpointMap = {}; testnet.lastCheckpoint = 0; testnet.halvingInterval = 170000; testnet.coinbaseMaturity = 100; testnet.genesis = genesis.testnet; testnet.genesisBlock = genesis.testnetData; testnet.pow = {}; // Probably minable very quick with 1 GPU. testnet.pow.limit = new BN( '00000000ffff0000000000000000000000000000000000000000000000000000', 'hex' ); testnet.pow.bits = 0x1d00ffff; testnet.pow.chainwork = new BN( '0000000000000000000000000000000000000000000000000000000000000000', 'hex' ); testnet.pow.targetWindow = 144; testnet.pow.targetSpacing = 10 * 60; testnet.pow.blocksPerDay = ((24 * 60 * 60) / testnet.pow.targetSpacing) >>> 0; testnet.pow.targetTimespan = testnet.pow.targetWindow * testnet.pow.targetSpacing; testnet.pow.minActual = (testnet.pow.targetTimespan / 4) >>> 0; testnet.pow.maxActual = testnet.pow.targetTimespan * 4; testnet.pow.targetReset = true; testnet.pow.noRetargeting = false; testnet.txStart = 0; testnet.names = { auctionStart: (0.25 * testnet.pow.blocksPerDay) | 0, rolloutInterval: (0.25 * testnet.pow.blocksPerDay) | 0, lockupPeriod: (0.25 * testnet.pow.blocksPerDay) | 0, renewalWindow: 30 * testnet.pow.blocksPerDay, renewalPeriod: 7 * testnet.pow.blocksPerDay, renewalMaturity: 1 * testnet.pow.blocksPerDay, claimPeriod: 90 * testnet.pow.blocksPerDay, claimFrequency: 2 * testnet.pow.blocksPerDay, biddingPeriod: 1 * testnet.pow.blocksPerDay, revealPeriod: 2 * testnet.pow.blocksPerDay, treeInterval: testnet.pow.blocksPerDay >>> 2, transferLockup: 2 * testnet.pow.blocksPerDay, revocationDelay: 4 * testnet.pow.blocksPerDay, auctionMaturity: (1 + 2 + 4) * testnet.pow.blocksPerDay, noRollout: false, noReserved: false }; testnet.block = { pruneAfterHeight: 1000, keepBlocks: 10000, maxTipAge: 12 * 60 * 60, slowHeight: 0 }; testnet.goosigStop = 20 * testnet.pow.blocksPerDay; testnet.activationThreshold = 1512; testnet.minerWindow = 2016; testnet.deployments = { hardening: { name: 'hardening', bit: 0, startTime: 1581638400, // February 14th, 2020 timeout: 1707868800, // February 14th, 2024 threshold: -1, window: -1, required: false, force: false }, testdummy: { name: 'testdummy', bit: 28, startTime: 1199145601, // January 1, 2008 timeout: 1230767999, // December 31, 2008 threshold: -1, window: -1, required: false, force: true } }; testnet.deploys = [ testnet.deployments.hardening, testnet.deployments.testdummy ]; testnet.keyPrefix = { privkey: 0xef, xpubkey: 0x043587cf, xprivkey: 0x04358394, xpubkey58: 'tpub', xprivkey58: 'tprv', coinType: 5354 }; testnet.addressPrefix = 'ts'; testnet.requireStandard = false; testnet.rpcPort = 13037; testnet.walletPort = 13039; testnet.nsPort = 15349; testnet.rsPort = 15350; testnet.minRelay = 1000; testnet.feeRate = 20000; testnet.maxFeeRate = 60000; testnet.identityKey = null; testnet.selfConnect = false; testnet.requestMempool = false; testnet.claimPrefix = 'hns-testnet:'; testnet.deflationHeight = 0; /* * Regtest */ const regtest = {}; regtest.type = 'regtest'; regtest.seeds = []; regtest.magic = genesis.regtest.magic; regtest.port = 14038; regtest.brontidePort = 46806; regtest.checkpointMap = {}; regtest.lastCheckpoint = 0; regtest.halvingInterval = 2500; regtest.coinbaseMaturity = 2; regtest.genesis = genesis.regtest; regtest.genesisBlock = genesis.regtestData; regtest.pow = {}; regtest.pow.limit = new BN( '7fffff0000000000000000000000000000000000000000000000000000000000', 'hex' ); regtest.pow.bits = 0x207fffff; regtest.pow.chainwork = new BN( '0000000000000000000000000000000000000000000000000000000000000000', 'hex' ); regtest.pow.targetWindow = 144; regtest.pow.targetSpacing = 10 * 60; regtest.pow.blocksPerDay = ((24 * 60 * 60) / regtest.pow.targetSpacing) >>> 0; regtest.pow.targetTimespan = regtest.pow.targetWindow * regtest.pow.targetSpacing; regtest.pow.minActual = (regtest.pow.targetTimespan / 4) >>> 0; regtest.pow.maxActual = regtest.pow.targetTimespan * 4; regtest.pow.targetReset = true; regtest.pow.noRetargeting = true; regtest.txStart = 0; regtest.names = { auctionStart: 0, rolloutInterval: 2, lockupPeriod: 2, renewalWindow: 5000, renewalPeriod: 2500, renewalMaturity: 50, claimPeriod: 250000, claimFrequency: 0, biddingPeriod: 5, revealPeriod: 10, treeInterval: 5, transferLockup: 10, revocationDelay: 50, auctionMaturity: 5 + 10 + 50, noRollout: false, noReserved: false }; regtest.block = { pruneAfterHeight: 1000, keepBlocks: 10000, maxTipAge: 0xffffffff, slowHeight: 0 }; regtest.goosigStop = -1 >>> 0; regtest.activationThreshold = 108; regtest.minerWindow = 144; regtest.deployments = { hardening: { name: 'hardening', bit: 0, startTime: 1581638400, // February 14th, 2020 timeout: 1707868800, // February 14th, 2024 threshold: -1, window: -1, required: false, force: false }, testdummy: { name: 'testdummy', bit: 28, startTime: 0, timeout: 0xffffffff, threshold: -1, window: -1, required: false, force: true } }; regtest.deploys = [ regtest.deployments.hardening, regtest.deployments.testdummy ]; regtest.keyPrefix = { privkey: 0x5a, xpubkey: 0xeab4fa05, xprivkey: 0xeab404c7, xpubkey58: 'rpub', xprivkey58: 'rprv', coinType: 5355 }; regtest.addressPrefix = 'rs'; regtest.requireStandard = false; regtest.rpcPort = 14037; regtest.walletPort = 14039; regtest.nsPort = 25349; regtest.rsPort = 25350; regtest.minRelay = 1000; regtest.feeRate = 20000; regtest.maxFeeRate = 60000; regtest.identityKey = Buffer.from( '104932181cfed7584105c728cdc0eb9af1e7ffdc4a00743fd45e5de66cac7668', 'hex' ); regtest.selfConnect = true; regtest.requestMempool = true; regtest.claimPrefix = 'hns-regtest:'; regtest.deflationHeight = 200; /* * Simnet */ const simnet = {}; simnet.type = 'simnet'; simnet.seeds = []; simnet.magic = genesis.simnet.magic; simnet.port = 15038; simnet.brontidePort = 47806; simnet.checkpointMap = {}; simnet.lastCheckpoint = 0; simnet.halvingInterval = 170000; simnet.coinbaseMaturity = 6; simnet.genesis = genesis.simnet; simnet.genesisBlock = genesis.simnetData; simnet.pow = {}; simnet.pow.limit = new BN( '7fffff0000000000000000000000000000000000000000000000000000000000', 'hex' ); simnet.pow.bits = 0x207fffff; simnet.pow.chainwork = new BN( '0000000000000000000000000000000000000000000000000000000000000000', 'hex' ); simnet.pow.targetWindow = 144; simnet.pow.targetSpacing = 10 * 60; simnet.pow.blocksPerDay = ((24 * 60 * 60) / simnet.pow.targetSpacing) >>> 0; simnet.pow.targetTimespan = simnet.pow.targetWindow * simnet.pow.targetSpacing; simnet.pow.minActual = (simnet.pow.targetTimespan / 4) >>> 0; simnet.pow.maxActual = simnet.pow.targetTimespan * 4; simnet.pow.targetReset = false; simnet.pow.noRetargeting = false; simnet.txStart = 0; simnet.names = { auctionStart: 0, rolloutInterval: 1, lockupPeriod: 1, renewalWindow: 2500, renewalPeriod: 1250, renewalMaturity: 25, claimPeriod: 75000, claimFrequency: 0, biddingPeriod: 25, revealPeriod: 50, treeInterval: 2, transferLockup: 5, revocationDelay: 25, auctionMaturity: 25 + 50 + 25, noRollout: false, noReserved: false }; simnet.block = { pruneAfterHeight: 1000, keepBlocks: 10000, maxTipAge: 0xffffffff, slowHeight: 0 }; simnet.goosigStop = -1 >>> 0; simnet.activationThreshold = 75; simnet.minerWindow = 100; simnet.deployments = { hardening: { name: 'hardening', bit: 0, startTime: 1581638400, // February 14th, 2020 timeout: 1707868800, // February 14th, 2024 threshold: -1, window: -1, required: false, force: false }, testdummy: { name: 'testdummy', bit: 28, startTime: 1199145601, // January 1, 2008 timeout: 1230767999, // December 31, 2008 threshold: -1, window: -1, required: false, force: true } }; simnet.deploys = [ simnet.deployments.hardening, simnet.deployments.testdummy ]; simnet.keyPrefix = { privkey: 0x64, xpubkey: 0x0420bd3a, xprivkey: 0x0420b900, xpubkey58: 'spub', xprivkey58: 'sprv', coinType: 5356 }; simnet.addressPrefix = 'ss'; simnet.requireStandard = false; simnet.rpcPort = 15037; simnet.walletPort = 15039; simnet.nsPort = 35349; simnet.rsPort = 35350; simnet.minRelay = 1000; simnet.feeRate = 20000; simnet.maxFeeRate = 60000; simnet.identityKey = Buffer.from( '104932181cfed7584105c728cdc0eb9af1e7ffdc4a00743fd45e5de66cac7668', 'hex' ); simnet.selfConnect = true; simnet.requestMempool = false; simnet.claimPrefix = 'hns-simnet:'; simnet.deflationHeight = 0; /* * Expose */ network.main = main; network.testnet = testnet; network.regtest = regtest; network.simnet = simnet; }], [/* 47 */ 'hsd', '/lib/protocol/genesis.js', function(exports, module, __filename, __dirname, __meta) { // Autogenerated, do not edit. 'use strict'; const data = __node_require__(48 /* './genesis-data.json' */); const genesis = exports; /* * Main */ genesis.main = { version: 0, hash: Buffer.from( '5b6ef2d3c1f3cdcadfd9a030ba1811efdd17740f14e166489760741d075992e0', 'hex'), prevBlock: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), merkleRoot: Buffer.from( '8e4c9756fef2ad10375f360e0560fcc7587eb5223ddf8cd7c7e06e60a1140b15', 'hex'), witnessRoot: Buffer.from( '1a2c60b9439206938f8d7823782abdb8b211a57431e9c9b6a6365d8d42893351', 'hex'), treeRoot: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), reservedRoot: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), time: 1580745078, bits: 0x1c00ffff, nonce: 0x00000000, extraNonce: Buffer.from( '000000000000000000000000000000000000000000000000', 'hex'), mask: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), height: 0, magic: 1533997779 }; genesis.mainData = Buffer.from(data.main, 'base64'); /* * Testnet */ genesis.testnet = { version: 0, hash: Buffer.from( 'b1520dd24372f82ec94ebf8cf9d9b037d419c4aa3575d05dec70aedd1b427901', 'hex'), prevBlock: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), merkleRoot: Buffer.from( '8e4c9756fef2ad10375f360e0560fcc7587eb5223ddf8cd7c7e06e60a1140b15', 'hex'), witnessRoot: Buffer.from( '1a2c60b9439206938f8d7823782abdb8b211a57431e9c9b6a6365d8d42893351', 'hex'), treeRoot: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), reservedRoot: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), time: 1580745079, bits: 0x1d00ffff, nonce: 0x00000000, extraNonce: Buffer.from( '000000000000000000000000000000000000000000000000', 'hex'), mask: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), height: 0, magic: 2974944722 }; genesis.testnetData = Buffer.from(data.testnet, 'base64'); /* * Regtest */ genesis.regtest = { version: 0, hash: Buffer.from( 'ae3895cf597eff05b19e02a70ceeeecb9dc72dbfe6504a50e9343a72f06a87c5', 'hex'), prevBlock: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), merkleRoot: Buffer.from( '8e4c9756fef2ad10375f360e0560fcc7587eb5223ddf8cd7c7e06e60a1140b15', 'hex'), witnessRoot: Buffer.from( '1a2c60b9439206938f8d7823782abdb8b211a57431e9c9b6a6365d8d42893351', 'hex'), treeRoot: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), reservedRoot: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), time: 1580745080, bits: 0x207fffff, nonce: 0x00000000, extraNonce: Buffer.from( '000000000000000000000000000000000000000000000000', 'hex'), mask: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), height: 0, magic: 2922943951 }; genesis.regtestData = Buffer.from(data.regtest, 'base64'); /* * Simnet */ genesis.simnet = { version: 0, hash: Buffer.from( '0e648edc9cddb179014658061ea3f666a45cf44881877ae506e6babefbef6992', 'hex'), prevBlock: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), merkleRoot: Buffer.from( '8e4c9756fef2ad10375f360e0560fcc7587eb5223ddf8cd7c7e06e60a1140b15', 'hex'), witnessRoot: Buffer.from( '1a2c60b9439206938f8d7823782abdb8b211a57431e9c9b6a6365d8d42893351', 'hex'), treeRoot: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), reservedRoot: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), time: 1580745081, bits: 0x207fffff, nonce: 0x00000000, extraNonce: Buffer.from( '000000000000000000000000000000000000000000000000', 'hex'), mask: Buffer.from( '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), height: 0, magic: 241471196 }; genesis.simnetData = Buffer.from(data.simnet, 'base64'); }], [/* 48 */ 'hsd', '/lib/protocol/genesis-data.json', function(exports, module, __filename, __dirname, __meta) { module.exports = { "main": "AAAAAHZBOF4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGixguUOSBpOPjXgjeCq9uLIRpXQx6cm2pjZdjUKJM1GOTJdW/vKtEDdfNg4FYPzHWH61Ij3fjNfH4G5goRQLFQAAAAD//wAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AdBMV3cAAAAAABTwI3ri6Phg99eRJPxRPwEuWqqNIwAAAAAAAAQgULiTf8Xe8I+fPL2n5fCMcG7bgKuliAwAAAAAAAAAAAAgLV3lhgnUlw+1SPha0HqH20DgVONMyByVHKmVpY9nTbcgENdI7aG5xnuU0yROAhFndhiptLMp6JatkEMfn0gDS60g4sApmh5GZ3NRZlXwmmSx4WsleVMN5sSlnOVlTepFGA8=", "testnet": "AAAAAHdBOF4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGixguUOSBpOPjXgjeCq9uLIRpXQx6cm2pjZdjUKJM1GOTJdW/vKtEDdfNg4FYPzHWH61Ij3fjNfH4G5goRQLFQAAAAD//wAdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AdBMV3cAAAAAABTwI3ri6Phg99eRJPxRPwEuWqqNIwAAAAAAAAQgULiTf8Xe8I+fPL2n5fCMcG7bgKuliAwAAAAAAAAAAAAgLV3lhgnUlw+1SPha0HqH20DgVONMyByVHKmVpY9nTbcgENdI7aG5xnuU0yROAhFndhiptLMp6JatkEMfn0gDS60g4sApmh5GZ3NRZlXwmmSx4WsleVMN5sSlnOVlTepFGA8=", "regtest": "AAAAAHhBOF4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGixguUOSBpOPjXgjeCq9uLIRpXQx6cm2pjZdjUKJM1GOTJdW/vKtEDdfNg4FYPzHWH61Ij3fjNfH4G5goRQLFQAAAAD//38gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AdBMV3cAAAAAABTwI3ri6Phg99eRJPxRPwEuWqqNIwAAAAAAAAQgULiTf8Xe8I+fPL2n5fCMcG7bgKuliAwAAAAAAAAAAAAgLV3lhgnUlw+1SPha0HqH20DgVONMyByVHKmVpY9nTbcgENdI7aG5xnuU0yROAhFndhiptLMp6JatkEMfn0gDS60g4sApmh5GZ3NRZlXwmmSx4WsleVMN5sSlnOVlTepFGA8=", "simnet": "AAAAAHlBOF4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGixguUOSBpOPjXgjeCq9uLIRpXQx6cm2pjZdjUKJM1GOTJdW/vKtEDdfNg4FYPzHWH61Ij3fjNfH4G5goRQLFQAAAAD//38gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AdBMV3cAAAAAABTwI3ri6Phg99eRJPxRPwEuWqqNIwAAAAAAAAQgULiTf8Xe8I+fPL2n5fCMcG7bgKuliAwAAAAAAAAAAAAgLV3lhgnUlw+1SPha0HqH20DgVONMyByVHKmVpY9nTbcgENdI7aG5xnuU0yROAhFndhiptLMp6JatkEMfn0gDS60g4sApmh5GZ3NRZlXwmmSx4WsleVMN5sSlnOVlTepFGA8=" }; }], [/* 49 */ 'hsd', '/lib/protocol/timedata.js', function(exports, module, __filename, __dirname, __meta) { /*! * timedata.js - time management for hsd * Copyright (c) 2017-2018, Christopher Jeffrey (MIT License). * https://github.com/handshake-org/hsd */ 'use strict'; const EventEmitter = require('events'); const util = __node_require__(50 /* '../utils/util' */); const binary = __node_require__(45 /* '../utils/binary' */); /** * Time Data * An object which handles "adjusted time". This may not * look it, but this is actually a semi-consensus-critical * piece of code. It handles version packets from peers * and calculates what to offset our system clock's time by. * @alias module:protocol.TimeData * @extends EventEmitter * @property {Array} samples * @property {Object} known * @property {Number} limit * @property {Number} offset */ class TimeData extends EventEmitter { /** * Create time data. * @constructor * @param {Number} [limit=200] */ constructor(limit) { super(); if (limit == null) limit = 200; this.samples = []; this.known = new Map(); this.limit = limit; this.offset = 0; this.checked = false; } /** * Add time data. * @param {String} id * @param {Number} time */ add(id, time) { if (this.samples.length >= this.limit) return; if (this.known.has(id)) return; const sample = time - util.now(); this.known.set(id, sample); binary.insert(this.samples, sample, compare); this.emit('sample', sample, this.samples.length); if (this.samples.length >= 5 && this.samples.length % 2 === 1) { let median = this.samples[this.samples.length >>> 1]; if (Math.abs(median) >= 70 * 60) { if (!this.checked) { let match = false; for (const offset of this.samples) { if (offset !== 0 && Math.abs(offset) < 5 * 60) { match = true; break; } } if (!match) { this.checked = true; this.emit('mismatch'); } } median = 0; } this.offset = median; this.emit('offset', this.offset); } } /** * Get the current adjusted time. * @returns {Number} Adjusted Time. */ now() { return util.now() + this.offset; } /** * Adjust a timestamp. * @param {Number} time * @returns {Number} Adjusted Time. */ adjust(time) { return time + this.offset; } /** * Unadjust a timestamp. * @param {Number} time * @returns {Number} Local Time. */ local(time) { return time - this.offset; } /** * Get the current adjusted time in milliseconds. * @returns {Number} Adjusted Time. */ ms() { return Date.now() + this.offset * 1000; } } /* * Helpers */ function compare(a, b) { return a - b; } /* * Expose */ module.exports = TimeData; }], [/* 50 */ 'hsd', '/lib/utils/util.js', function(exports, module, __filename, __dirname, __meta) { /*! * util.js - utils for hsd * Copyright (c) 2017-2018, Christopher Jeffrey (MIT License). * https://github.com/handshake-org/hsd */ 'use strict'; const assert = __node_require__(2 /* 'bsert' */); /** * @exports utils/util */ const util = exports; /** * Return hrtime (shim for browser). * @param {Array} time * @returns {Array} [seconds, nanoseconds] */ util.bench = function bench(time) { if (!process.hrtime) { const now = Date.now(); if (time) { const [hi, lo] = time; const start = hi * 1000 + lo / 1e6; return now - start; } const ms = now % 1000; // Seconds const hi = (now - ms) / 1000; // Nanoseconds const lo = ms * 1e6; return [hi, lo]; } if (time) { const [hi, lo] = process.hrtime(time); return hi * 1000 + lo / 1e6; } return process.hrtime(); }; /** * Get current time in unix time (seconds). * @returns {Number} */ util.now = function now() { return Math.floor(Date.now() / 1000); }; /** * Get current time in unix time (milliseconds). * @returns {Number} */ util.ms = function ms() { return Date.now(); }; /** * Create a Date ISO string from time in unix time (seconds). * @param {Number?} time - Seconds in unix time. * @returns {String} */ util.date = function date(time) { if (time == null) time = util.now(); return new Date(time * 1000).toISOString().slice(0, -5) + 'Z'; }; /** * Get unix seconds from a Date string. * @param {String?} date - Date ISO String. * @returns {Number} */ util.time = function time(date) { if (date == null) return util.now(); return new Date(date) / 1000 | 0; }; /** * Convert u32 to padded hex. * @param {Number} num * @returns {String} */ util.hex32 = function hex32(num) { assert((num >>> 0) === num); num = num.toString(16); switch (num.length) { case 1: return `0000000${num}`; case 2: return `000000${num}`; case 3: return `00000${num}`; case 4: return `0000${num}`; case 5: return `000${num}`; case 6: return `00${num}`; case 7: return `0${num}`; case 8: return `${num}`; default: throw new Error(); } }; /** * Parse hex. * @param {String} str * @param {Number} size * @returns {Buffer} */ util.parseHex = function parseHex(str, size) { if (size == null) size = -1; assert(typeof str === 'string'); assert(size === -1 || (size >>> 0) === size); if (str.length & 1) throw new Error('Invalid hex string.'); if (size !== -1) { if ((str.length >>> 1) !== size) throw new Error('Invalid hex string.'); } const data = Buffer.from(str, 'hex'); if (data.length !== (str.length >>> 1)) throw new Error('Invalid hex string.'); return data; }; /** * Test whether a number is a safe uint64. * @param {Number} num * @returns {Boolean} */ util.isU64 = function isU64(num) { return Number.isSafeInteger(num) && num >= 0; }; /** * Encode a uint32. * @param {Number} num * @returns {Buffer} */ util.encodeU32 = function encodeU32(num) { assert(Number.isSafeInteger(num)); const buf = Buffer.allocUnsafe(4); buf[0] = num; num >>>= 8; buf[1] = num; num >>>= 8; buf[2] = num; num >>>= 8; buf[3] = num; return buf; }; }], [/* 51 */ 'hsd', '/lib/protocol/consensus.js', function(exports, module, __filename, __dirname, __meta) { /*! * consensus.js - consensus constants and helpers for hsd * Copyright (c) 2017-2018, Christopher Jeffrey (MIT License). * https://github.com/handshake-org/hsd */ 'use strict'; /** * @module protocol/consensus */ const assert = __node_require__(2 /* 'bsert' */); const BN = __node_require__(31 /* 'bcrypto/lib/bn.js' */); /** * Coin exponent. * @const {Number} * @default */ exports.EXP = 6; /** * One handshake in dollarydoos. * @const {Amount} * @default */ exports.COIN = Math.pow(10, exports.EXP); /** * Maximum creators amount in dollarydoos (consensus). * @const {Amount} * @default */ exports.MAX_CREATORS = 102e6 * exports.COIN; /** * Maximum sponsors amount in dollarydoos (consensus). * @const {Amount} * @default */ exports.MAX_SPONSORS = 102e6 * exports.COIN; /** * Maximum TLD holder amount in dollarydoos (consensus). * @const {Amount} * @default */ exports.MAX_TLD = 51e6 * exports.COIN; /** * Maximum domain holder amount in dollarydoos (consensus). * @const {Amount} * @default */ exports.MAX_DOMAIN = 51e6 * exports.COIN; /** * Maximum CA/naming amount in dollarydoos (consensus). * @const {Amount} * @default */ exports.MAX_CA_NAMING = 102e6 * exports.COIN; /** * Maximum airdrop amount in dollarydoos (consensus). * @const {Amount} * @default */ exports.MAX_AIRDROP = 0.952e9 * exports.COIN; /** * Maximum initial supply in dollarydoos (consensus). * @const {Amount} * @default */ exports.MAX_INITIAL = 1.36e9 * exports.COIN; assert(exports.MAX_CREATORS + exports.MAX_SPONSORS + exports.MAX_TLD + exports.MAX_DOMAIN + exports.MAX_CA_NAMING + exports.MAX_AIRDROP === exports.MAX_INITIAL); /** * Maximum amount of subsidies in dollarydoos (consensus). * @const {Amount} * @default */ exports.MAX_SUBSIDY = 0.68e9 * exports.COIN; assert(exports.MAX_INITIAL / 2 === exports.MAX_SUBSIDY); /** * Maximum amount of money in dollarydoos (consensus). * @const {Amount} * @default */ exports.MAX_MONEY = 2.04e9 * exports.COIN; assert(exports.MAX_INITIAL + exports.MAX_SUBSIDY === exports.MAX_MONEY); /** * Base block subsidy (consensus). * @const {Amount} * @default */ exports.BASE_REWARD = 2000 * exports.COIN; assert(2 * exports.BASE_REWARD * 170000 === exports.MAX_SUBSIDY); /** * Block subsidy specifically for the genesis block. * * Explanation: * The max miner subsidy is 680000000, but due * to the halving interval it actually ends up * as 679999995.79, so add 2.21 coins to the * genesis reward output to make MAX_MONEY a * thoroughly true value. * * This, combined with the 3 1/4 year halving * interval, causes the supply to run dry * after about 100 years (around the year 2119, * or height=5,270,000). * * @const {Amount} * @default */ exports.GENESIS_REWARD = exports.BASE_REWARD + ((2.21 * exports.COIN) | 0); /** * Genesis key. * @const {Buffer} */ exports.GENESIS_KEY = Buffer.from('f0237ae2e8f860f7d79124fc513f012e5aaa8d23', 'hex'); /** * Maximum block base size (consensus). * @const {Number} * @default */ exports.MAX_BLOCK_SIZE = 1000000; /** * Maximum block serialization size (protocol). * @const {Number} * @default */ exports.MAX_RAW_BLOCK_SIZE = 4000000; /** * Maximum block weight (consensus). * @const {Number} * @default */ exports.MAX_BLOCK_WEIGHT = 4000000; /** * Maximum block sigops cost (consensus). * @const {Number} * @default */ exports.MAX_BLOCK_SIGOPS = 80000; /** * Maximum block tree opens. * @const {Number} * @default */ exports.MAX_BLOCK_OPENS = 300; /** * Maximum block tree updates. * @const {Number} * @default */ exports.MAX_BLOCK_UPDATES = 600; /** * Maximum block tree renewals. * @const {Number} * @default */ exports.MAX_BLOCK_RENEWALS = 600; /** * Size of set to pick median time from. * @const {Number} * @default */ exports.MEDIAN_TIMESPAN = 11; /** * Amount to multiply base/non-witness sizes by. * @const {Number} * @default */ exports.WITNESS_SCALE_FACTOR = 4; /** * Maximum TX base size (consensus). * @const {Number} * @default */ exports.MAX_TX_SIZE = 1000000; /** * Maximum TX weight (consensus). * @const {Number} * @default */ exports.MAX_TX_WEIGHT = 4000000; /** * Locktime flag. * @const {Number} * @default */ exports.LOCKTIME_FLAG = (1 << 31) >>> 0; /** * Locktime mask. * @const {Number} * @default */ exports.LOCKTIME_MASK = exports.LOCKTIME_FLAG - 1; /** * Locktime granularity. * @const {Number} * @default */ exports.LOCKTIME_GRANULARITY = 9; /** * Locktime multiplier. * @const {Number} * @default */ exports.LOCKTIME_MULT = 2 ** exports.LOCKTIME_GRANULARITY; /** * Highest nSequence bit -- disables * sequence locktimes (consensus). * @const {Number} */ exports.SEQUENCE_DISABLE_FLAG = (1 << 31) >>> 0; /** * Sequence time: height or time (consensus). * @const {Number} * @default */ exports.SEQUENCE_TYPE_FLAG = 1 << 22; /** * Sequence granularity for time (consensus). * @const {Number} * @default */ exports.SEQUENCE_GRANULARITY = 9; /** * Sequence mask (consensus). * @const {Number} * @default */ exports.SEQUENCE_MASK = 0x0000ffff; /** * Max serialized script size (consensus). * @const {Number} * @default */ exports.MAX_SCRIPT_SIZE = 10000; /** * Max stack size during execution (consensus). * @const {Number} * @default */ exports.MAX_SCRIPT_STACK = 1000; /** * Max script element size (consensus). * @const {Number} * @default */ exports.MAX_SCRIPT_PUSH = 520; /** * Max opcodes executed (consensus). * @const {Number} * @default */ exports.MAX_SCRIPT_OPS = 201; /** * Max `n` value for multisig (consensus). * @const {Number} * @default */ exports.MAX_MULTISIG_PUBKEYS = 20; /** * A hash of all zeroes. * @const {Buffer} * @default */ exports.ZERO_HASH = Buffer.alloc(32, 0x00); /** * Block header size. * @const {Number} * @default */ exports.HEADER_SIZE = 236; /** * Block header nonce size. * @const {Number} * @default */ exports.NONCE_SIZE = 24; /** * Block header of all zeroes. * @const {Buffer} * @default */ exports.ZERO_HEADER = Buffer.alloc(exports.HEADER_SIZE, 0x00); /** * Block header nonce of all zeroes. * @const {Buffer} * @default */ exports.ZERO_NONCE = Buffer.alloc(exports.NONCE_SIZE, 0x00); /** * Convert a compact number to a big number. * Used for `block.bits` -> `target` conversion. * @param {Number} compact * @returns {BN} */ exports.fromCompact = function fromCompact(compact) { if (compact === 0) return new BN(0); const exponent = compact >>> 24; const negative = (compact >>> 23) & 1; let mantissa = compact & 0x7fffff; let num; if (exponent <= 3) { mantissa >>>= 8 * (3 - exponent); num = new BN(mantissa); } else { num = new BN(mantissa); num.iushln(8 * (exponent - 3)); } if (negative) num.ineg(); return num; }; /** * Convert a big number to a compact number. * Used for `target` -> `block.bits` conversion. * @param {BN} num * @returns {Number} */ exports.toCompact = function toCompact(num) { if (num.isZero()) return 0; let exponent = num.byteLength(); let mantissa; if (exponent <= 3) { mantissa = num.toNumber(); mantissa <<= 8 * (3 - exponent); } else { mantissa = num.ushrn(8 * (exponent - 3)).toNumber(); } if (mantissa & 0x800000) { mantissa >>>= 8; exponent += 1; } let compact = (exponent << 24) | mantissa; if (num.isNeg()) compact |= 0x800000; compact >>>= 0; return compact; }; /** * Verify proof-of-work. * @param {Hash} hash * @param {Number} bits * @returns {Boolean} */ exports.verifyPOW = function verifyPOW(hash, bits) { const target = exports.fromCompact(bits); if (target.isNeg() || target.isZero()) return false; if (target.bitLength() > 256) return false; const num = new BN(hash, 'be'); if (num.gt(target)) return false; return true; }; /** * Calculate block subsidy. * @param {Number} height - Reward era by height. * @returns {Amount} */ exports.getReward = function getReward(height, interval) { assert((height >>> 0) === height, 'Bad height for reward.'); assert((interval >>> 0) === interval); const halvings = Math.floor(height / interval); if (halvings >= 52) return 0; return Math.floor(exports.BASE_REWARD / Math.pow(2, halvings)); }; /** * Test version bit. * @param {Number} version * @param {Number} bit * @returns {Boolean} */ exports.hasBit = function hasBit(version, bit) { return (version & (1 << bit)) !== 0; }; }], [/* 52 */ 'hsd', '/lib/hd/common.js', function(exports, module, __filename, __dirname, __meta) { /*! * common.js - common functions for hd * Copyright (c) 2017-2018, Christopher Jeffrey (MIT License). * https://github.com/handshake-org/hsd */ 'use strict'; const assert = __node_require__(2 /* 'bsert' */); const LRU = __node_require__(53 /* 'blru' */); const common = exports; /** * Index at which hardening begins. * @const {Number} * @default */ common.HARDENED = 0x80000000; /** * Min entropy bits. * @const {Number} * @default */ common.MIN_ENTROPY = 128; /** * Max entropy bits. * @const {Number} * @default */ common.MAX_ENTROPY = 512; /** * LRU cache to avoid deriving keys twice. * @type {LRU} */ common.cache = new LRU(500); /** * Parse a derivation path and return an array of indexes. * @see https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki * @param {String} path * @param {Boolean} hard * @returns {Number[]} */ common.parsePath = function parsePath(path, hard) { assert(typeof path === 'string'); assert(typeof hard === 'boolean'); assert(path.length >= 1); assert(path.length <= 3062); const parts = path.split('/'); const root = parts[0]; if (root !== 'm' && root !== 'M' && root !== 'm\'' && root !== 'M\'') { throw new Error('Invalid path root.'); } const result = []; for (let i = 1; i < parts.length; i++) { let part = parts[i]; const hardened = part[part.length - 1] === '\''; if (hardened) part = part.slice(0, -1); if (part.length > 10) throw new Error('Path index too large.'); if (!/^\d+$/.test(part)) throw new Error('Path index is non-numeric.'); let index = parseInt(part, 10); if ((index >>> 0) !== index) throw new Error('Path index out of range.'); if (hardened) { index |= common.HARDENED; index >>>= 0; } if (!hard && (index & common.HARDENED)) throw new Error('Path index cannot be hardened.'); result.push(index); } return result; }; /** * Test whether the key is a master key. * @param {HDPrivateKey|HDPublicKey} key * @returns {Boolean} */ common.isMaster = function isMaster(key) { return key.depth === 0 && key.childIndex === 0 && key.parentFingerPrint === 0; }; /** * Test whether the key is (most likely) a BIP44 account key. * @param {HDPrivateKey|HDPublicKey} key * @param {Number?} account * @returns {Boolean} */ common.isAccount = function isAccount(key, account) { if (account != null) { const index = (common.HARDENED | account) >>> 0; if (key.childIndex !== index) return false; } return key.depth === 3 && (key.childIndex & common.HARDENED) !== 0; }; /** * A compressed pubkey of all zeroes. * @const {Buffer} * @default */ common.ZERO_KEY = Buffer.alloc(33, 0x00); }], [/* 53 */ 'blru', '/lib/blru.js', function(exports, module, __filename, __dirname, __meta) { 'use strict'; module.exports = __node_require__(54 /* './lru' */); }], [/* 54 */ 'blru', '/lib/lru.js', function(exports, module, __filename, __dirname, __meta) { /*! * lru.js - LRU cache for bcoin * Copyright (c) 2014-2018, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcoin */ 'use strict'; const assert = __node_require__(2 /* 'bsert' */); /** * LRU Cache */ class LRU { /** * Create an LRU cache. * @constructor * @param {Number} capacity * @param {Function?} getSize * @param {Function?} CustomMap */ constructor(capacity, getSize, CustomMap) { assert(typeof capacity === 'number', 'Capacity must be a number.'); assert(capacity >= 0, 'Capacity cannot be negative.'); assert(!getSize || typeof getSize === 'function', 'Bad size callback.'); assert(!CustomMap || typeof CustomMap === 'function'); this.map = CustomMap ? new CustomMap() : new Map(); this.size = 0; this.items = 0; this.head = null; this.tail = null; this.pending = null; this.capacity = capacity; this.getSize = getSize; } /** * Calculate size of an item. * @private * @param {LRUItem} item * @returns {Number} Size. */ _getSize(item) { if (this.getSize) return 120 + this.getSize(item.value, item.key); return 1; } /** * Compact the LRU linked list. * @private */ _compact() { if (this.size <= this.capacity) return; let item = null; let next = null; for (item = this.head; item; item = next) { if (this.size <= this.capacity) break; this.size -= this._getSize(item); this.items -= 1; this.map.delete(item.key); next = item.next; item.prev = null; item.next = null; } if (!item) { this.head = null; this.tail = null; return; } this.head = item; item.prev = null; } /** * Reset the cache. Clear all items. */ reset() { let item, next; for (item = this.head; item; item = next) { this.map.delete(item.key); this.items -= 1; next = item.next; item.prev = null; item.next = null; } assert(!item); this.size = 0; this.head = null; this.tail = null; } /** * Add an item to the cache. * @param {String|Number} key * @param {Object} value */ set(key, value) { if (this.capacity === 0) return; let item = this.map.get(key); if (item) { this.size -= this._getSize(item); item.value = value; this.size += this._getSize(item); this._removeList(item); this._appendList(item); this._compact(); return; } item = new LRUItem(key, value); this.map.set(key, item); this._appendList(item); this.size += this._getSize(item); this.items += 1; this._compact(); } /** * Retrieve an item from the cache. * @param {String|Number} key * @returns {Object} Item. */ get(key) { if (this.capacity === 0) return null; const item = this.map.get(key); if (!item) return null; this._removeList(item); this._appendList(item); return item.value; } /** * Test whether the cache contains a key. * @param {String|Number} key * @returns {Boolean} */ has(key) { if (this.capacity === 0) return false; return this.map.has(key); } /** * Remove an item from the cache. * @param {String|Number} key * @returns {Boolean} Whether an item was removed. */ remove(key) { if (this.capacity === 0) return false; const item = this.map.get(key); if (!item) return false; this.size -= this._getSize(item); this.items -= 1; this.map.delete(key); this._removeList(item); return true; } /** * Prepend an item to the linked list (sets new head). * @private * @param {LRUItem} */ _prependList(item) { this._insertList(null, item); } /** * Append an item to the linked list (sets new tail). * @private * @param {LRUItem} */ _appendList(item) { this._insertList(this.tail, item); } /** * Insert item into the linked list. * @private * @param {LRUItem|null} ref * @param {LRUItem} item */ _insertList(ref, item) { assert(!item.next); assert(!item.prev); if (ref == null) { if (!this.head) { this.head = item; this.tail = item; } else { this.head.prev = item; item.next = this.head; this.head = item; } return; } item.next = ref.next; item.prev = ref; ref.next = item; if (item.next) item.next.prev = item; if (ref === this.tail) this.tail = item; } /** * Remove item from the linked list. * @private * @param {LRUItem} */ _removeList(item) { if (item.prev) item.prev.next = item.next; if (item.next) item.next.prev = item.prev; if (item === this.head) this.head = item.next; if (item === this.tail) this.tail = item.prev || this.head; if (!this.head) assert(!this.tail); if (!this.tail) assert(!this.head); item.prev = null; item.next = null; } /** * Collect all keys in the cache, sorted by LRU. * @returns {String[]} */ keys() { const items = []; for (let item = this.head; item; item = item.next) { if (item === this.head) assert(!item.prev); if (!item.prev) assert(item === this.head); if (!item.next) assert(item === this.tail); items.push(item.key); } return items; } /** * Collect all values in the cache, sorted by LRU. * @returns {String[]} */ values() { const items = []; for (let item = this.head; item; item = item.next) items.push(item.value); return items; } /** * Convert the LRU cache to an array of items. * @returns {Object[]} */ toArray() { const items = []; for (let item = this.head; item; item = item.next) items.push(item); return items; } /** * Create an atomic batch for the lru * (used for caching database writes). * @returns {LRUBatch} */ batch() { return new LRUBatch(this); } /** * Start the pending batch. */ start() { assert(!this.pending); this.pending = this.batch(); } /** * Clear the pending batch. */ clear() { assert(this.pending); this.pending.clear(); } /** * Drop the pending batch. */ drop() { assert(this.pending); this.pending = null; } /** * Commit the pending batch. */ commit() { assert(this.pending); this.pending.commit(); this.pending = null; } /** * Push an item onto the pending batch. * @param {String} key * @param {Object} value */ push(key, value) { assert(this.pending); if (this.capacity === 0) return; this.pending.set(key, value); } /** * Push a removal onto the pending batch. * @param {String} key */ unpush(key) { assert(this.pending); if (this.capacity === 0) return; this.pending.remove(key); } } /** * LRU Item * @alias module:utils.LRUItem */ class LRUItem { /** * Create an LRU item. * @constructor * @private * @param {String} key * @param {Object} value */ constructor(key, value) { this.key = key; this.value = value; this.next = null; this.prev = null; } } /** * LRU Batch * @alias module:utils.LRUBatch */ class LRUBatch { /** * Create an LRU batch. * @constructor * @param {LRU} lru */ constructor(lru) { this.lru = lru; this.ops = []; } /** * Push an item onto the batch. * @param {String} key * @param {Object} value */ set(key, value) { this.ops.push(new LRUOp(false, key, value)); } /** * Push a removal onto the batch. * @param {String} key */ remove(key) { this.ops.push(new LRUOp(true, key, null)); } /** * Clear the batch. */ clear() { this.ops.length = 0; } /** * Commit the batch. */ commit() { for (const op of this.ops) { if (op.remove) { this.lru.remove(op.key); continue; } this.lru.set(op.key, op.value); } this.ops.length = 0; } } /** * LRU Op * @alias module:utils.LRUOp * @private */ class LRUOp { /** * Create an LRU op. * @constructor * @param {Boolean} remove * @param {String} key * @param {Object} value */ constructor(remove, key, value) { this.remove = remove; this.key = key; this.value = value; } } /* * Expose */ module.exports = LRU; }], [/* 55 */ 'hsd', '/lib/primitives/address.js', function(exports, module, __filename, __dirname, __meta) { /*! * address.js - address object for hsd * Copyright (c) 2017-2018, Christopher Jeffrey (MIT License). * https://github.com/handshake-org/hsd */ 'use strict'; const assert = __node_require__(2 /* 'bsert' */); const bio = __node_require__(3 /* 'bufio' */); const bech32 = __node_require__(56 /* 'bcrypto/lib/encoding/bech32' */); const blake2b = __node_require__(58 /* 'bcrypto/lib/blake2b' */); const sha3 = __node_require__(60 /* 'bcrypto/lib/sha3' */); const Network = __node_require__(44 /* '../protocol/network' */); const consensus = __node_require__(51 /* '../protocol/consensus' */); /* * Constants */ const ZERO_HASH160 = Buffer.alloc(20, 0x00); /** * Address * Represents an address. * @alias module:primitives.Address * @property {Number} version * @property {Buffer} hash */ class Address extends bio.Struct { /** * Create an address. * @constructor * @param {Object?} options */ constructor(options, network) { super(); this.version = 0; this.hash = ZERO_HASH160; if (options) this.fromOptions(options, network); } /** * Inject properties from options object. * @private * @param {Object} options */ fromOptions(options, network) { if (typeof options === 'string') return this.fromString(options, network); assert(options); const {hash, version} = options; return this.fromHash(hash, version); } /** * Count the sigops in a script, taking into account witness programs. * @param {Witness} witness * @returns {Number} sigop count */ getSigops(witness) { if (this.version === 0) { if (this.hash.length === 20) return 1; if (this.hash.length === 32 && witness.items.length > 0) { const redeem = witness.getRedeem(); return redeem.getSigops(); } } return 0; } /** * Get the address hash. * @returns {Hash} */ getHash() { return this.hash; } /** * Test whether the address is null. * @returns {Boolean} */ isNull() { if (this.hash.length === 20) return this.hash.equals(ZERO_HASH160); if (this.hash.length === 32) return this.hash.equals(consensus.ZERO_HASH); for (let i = 0; i < this.hash.length; i++) { if (this.hash[i] !== 0) return false; } return true; } /** * Test whether the address is unspendable. * @returns {Boolean} */ isUnspendable() { return this.isNulldata(); } /** * Test equality against another address. * @param {Address} addr * @returns {Boolean} */ equals(addr) { assert(addr instanceof Address); return this.version === addr.version && this.hash.equals(addr.hash); } /** * Compare against another address. * @param {Address} addr * @returns {Boolean} */ compare(addr) { assert(addr instanceof Address); const cmp = this.version - addr.version; if (cmp !== 0) return cmp; return this.hash.compare(addr.hash); } /** * Inject properties from another address. * @param {Address} addr * @returns {Boolean} */ inject(addr) { this.version = addr.version; this.hash = addr.hash; return this; } /** * Clone address. * @returns {Address} */ clone() { return new this.constructor().inject(this); } /** * Compile the address object to a bech32 address. * @param {{NetworkType|Network)?} network * @returns {String} * @throws Error on bad hash/prefix. */ toString(network) { const version = this.version; const hash = this.hash; assert(version <= 31); assert(hash.length >= 2 && hash.length <= 40); network = Network.get(network); const hrp = network.addressPrefix; return bech32.encode(hrp, version, hash); } /** * Instantiate address from pubkey. * @param {Buffer} key * @returns {Address} */ fromPubkey(key) { assert(Buffer.isBuffer(key) && key.length === 33); return this.fromHash(blake2b.digest(key, 20), 0); } /** * Instantiate address from script. * @param {Script} script * @returns {Address} */ fromScript(script) { assert(script && typeof script.encode === 'function'); return this.fromHash(sha3.digest(script.encode()), 0); } /** * Inject properties from bech32 address. * @private * @param {String} data * @param {Network?} network * @throws Parse error */ fromString(data, network) { assert(typeof data === 'string'); const [hrp, version, hash] = bech32.decode(data); Network.fromAddress(hrp, network); return this.fromHash(hash, version); } /** * Inject properties from witness. * @private * @param {Witness} witness */ fromWitness(witness) { const [, pk] = witness.getPubkeyhashInput(); if (pk) { this.hash = blake2b.digest(pk, 20); this.version = 0; return this; } const redeem = witness.getScripthashInput(); if (redeem) { this.hash = sha3.digest(redeem); this.version = 0; return this; } return null; } /** * Inject properties from a hash. * @private * @param {Buffer|Hash} hash * @param {Number} [version=-1] * @throws on bad hash size */ fromHash(hash, version) { if (version == null) version = 0; assert(Buffer.isBuffer(hash)); assert((version & 0xff) === version); assert(version >= 0 && version <= 31, 'Bad program version.'); assert(hash.length >= 2 && hash.length <= 40, 'Hash is the wrong size.'); if (version === 0) { assert(hash.length === 20 || hash.length === 32, 'Witness program hash is the wrong size.'); } this.hash = hash; this.version = version; return this; } /** * Inject properties from witness pubkeyhash. * @private * @param {Buffer} hash * @returns {Address} */ fromPubkeyhash(hash) { assert(hash && hash.length === 20, 'P2WPKH must be 20 bytes.'); return this.fromHash(hash, 0); } /** * Inject properties from witness scripthash. * @private * @param {Buffer} hash * @returns {Address} */ fromScripthash(hash) { assert(hash && hash.length === 32, 'P2WSH must be 32 bytes.'); return this.fromHash(hash, 0); } /** * Inject properties from witness program. * @private * @param {Number} version * @param {Buffer} hash * @returns {Address} */ fromProgram(version, hash) { assert(version >= 0, 'Bad version for witness program.'); return this.fromHash(hash, version); } /** * Instantiate address from nulldata. * @param {Buffer} data * @returns {Address} */ fromNulldata(data) { return this.fromHash(data, 31); } /** * Test whether the address is witness pubkeyhash. * @returns {Boolean} */ isPubkeyhash() { return this.version === 0 && this.hash.length === 20; } /** * Test whether the address is witness scripthash. * @returns {Boolean} */ isScripthash() { return this.version === 0 && this.hash.length === 32; } /** * Test whether the address is unspendable. * @returns {Boolean} */ isNulldata() { return this.version === 31; } /** * Test whether the address is an unknown witness program. * @returns {Boolean} */ isUnknown() { switch (this.version) { case 0: return this.hash.length !== 20 && this.hash.length !== 32; case 31: return false; } return true; } /** * Test address validity. * @returns {Boolean} */ isValid() { assert(this.version >= 0); if (this.version > 31) return false; if (this.hash.length < 2 || this.hash.length > 40) return false; return true; } /** * Calculate address size. * @returns {Number} */ getSize() { return 1 + 1 + this.hash.length; } /** * Write address to buffer writer. * @param {BufferWriter} bw * @returns {BufferWriter} */ write(bw) { bw.writeU8(this.version); bw.writeU8(this.hash.length); bw.writeBytes(this.hash); return bw; } /** * Read address from buffer reader. * @param {BufferReader} br * @returns {Address} */ read(br) { const version = br.readU8(); assert(version <= 31); const size = br.readU8(); assert(size >= 2 && size <= 40); const hash = br.readBytes(size); return this.fromHash(hash, version); } /** * Inspect the Address. * @returns {Object} */ format() { return ''; } /** * Instantiate address from pubkey. * @param {Buffer} key * @returns {Address} */ static fromPubkey(key) { return new this().fromPubkey(key); } /** * Instantiate address from script. * @param {Script} script * @returns {Address} */ static fromScript(script) { return new this().fromScript(script); } /** * Create an Address from a witness. * Attempt to extract address * properties from a witness. * @param {Witness} * @returns {Address|null} */ static fromWitness(witness) { return new this().fromWitness(witness); } /** * Create a naked address from hash/version. * @param {Hash} hash * @param {Number} [version=-1] * @returns {Address} * @throws on bad hash size */ static fromHash(hash, version) { return new this().fromHash(hash, version); } /** * Instantiate address from witness pubkeyhash. * @param {Buffer} hash * @returns {Address} */ static fromPubkeyhash(hash) { return new this().fromPubkeyhash(hash); } /** * Instantiate address from witness scripthash. * @param {Buffer} hash * @returns {Address} */ static fromScripthash(hash) { return new this().fromScripthash(hash); } /** * Instantiate address from witness program. * @param {Number} version * @param {Buffer} hash * @returns {Address} */ static fromProgram(version, hash) { return new this().fromProgram(version, hash); } /** * Instantiate address from nulldata. * @param {Buffer} data * @returns {Address} */ static fromNulldata(data) { return new this().fromNulldata(data); } /** * Get the hash of a base58 address or address-related object. * @param {String|Address|Hash} data * @param {Network?} network * @returns {Hash} */ static getHash(data, network) { if (!data) throw new Error('Object is not an address.'); if (Buffer.isBuffer(data)) { return data; } if (data instanceof Address) return data.hash; throw new Error('Object is not an address.'); } } /* * Expose */ module.exports = Address; }], [/* 56 */ 'bcrypto', '/lib/encoding/bech32-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * bech32.js - bech32 for bcrypto * Copyright (c) 2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; module.exports = __node_require__(57 /* '../js/bech32' */); }], [/* 57 */ 'bcrypto', '/lib/js/bech32.js', function(exports, module, __filename, __dirname, __meta) { /*! * bech32.js - bech32 for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Parts of this software are based on sipa/bech32: * Copyright (c) 2017, Pieter Wuille (MIT License). * https://github.com/sipa/bech32 * * Resources: * https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki * https://github.com/sipa/bech32/blob/master/ref/c/segwit_addr.c * https://github.com/bitcoin/bitcoin/blob/master/src/bech32.cpp */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); /** * Constants */ const POOL65 = Buffer.alloc(65); const CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'; const TABLE = [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1, -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1, -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1 ]; /** * Update checksum. * @ignore * @param {Number} c * @returns {Number} */ function polymod(c) { const b = c >>> 25; return ((c & 0x1ffffff) << 5) ^ (0x3b6a57b2 & -((b >> 0) & 1)) ^ (0x26508e6d & -((b >> 1) & 1)) ^ (0x1ea119fa & -((b >> 2) & 1)) ^ (0x3d4233dd & -((b >> 3) & 1)) ^ (0x2a1462b3 & -((b >> 4) & 1)); } /** * Encode hrp and data as a bech32 string. * @param {String} hrp * @param {Buffer} data * @returns {String} */ function serialize(hrp, data) { assert(typeof hrp === 'string'); assert(Buffer.isBuffer(data)); if (hrp.length === 0 || hrp.length > 83) throw new Error('Invalid bech32 human-readable part.'); if (hrp.length + 1 + data.length + 6 > 90) throw new Error('Invalid bech32 data length.'); let str = ''; let chk = 1; let i; for (i = 0; i < hrp.length; i++) { const ch = hrp.charCodeAt(i); if (ch < 33 || ch > 126) throw new Error('Invalid bech32 character.'); if (ch >= 65 && ch <= 90) throw new Error('Invalid bech32 character.'); chk = polymod(chk) ^ (ch >> 5); } chk = polymod(chk); for (let i = 0; i < hrp.length; i++) { const ch = hrp.charCodeAt(i); chk = polymod(chk) ^ (ch & 0x1f); str += hrp[i]; } str += '1'; for (let i = 0; i < data.length; i++) { const ch = data[i]; if (ch >> 5) throw new Error('Invalid bech32 value.'); chk = polymod(chk) ^ ch; str += CHARSET[ch]; } for (let i = 0; i < 6; i++) chk = polymod(chk); chk ^= 1; for (let i = 0; i < 6; i++) str += CHARSET[(chk >>> ((5 - i) * 5)) & 0x1f]; return str; } /** * Decode a bech32 string. * @param {String} str * @returns {Array} [hrp, data] */ function deserialize(str) { assert(typeof str === 'string'); if (str.length < 8 || str.length > 90) throw new Error('Invalid bech32 string length.'); let lower = false; let upper = false; let hlen = 0; for (let i = 0; i < str.length; i++) { const ch = str.charCodeAt(i); if (ch < 33 || ch > 126) throw new Error('Invalid bech32 character.'); if (ch >= 97 && ch <= 122) lower = true; else if (ch >= 65 && ch <= 90) upper = true; else if (ch === 49) hlen = i; } if (hlen === 0) throw new Error('Invalid bech32 human-readable part.'); const dlen = str.length - (hlen + 1); if (dlen < 6) throw new Error('Invalid bech32 data length.'); if (lower && upper) throw new Error('Invalid bech32 casing.'); let chk = 1; let hrp = ''; for (let i = 0; i < hlen; i++) { let ch = str.charCodeAt(i); if (ch >= 65 && ch <= 90) ch += 32; chk = polymod(chk) ^ (ch >> 5); hrp += String.fromCharCode(ch); } chk = polymod(chk); for (let i = 0; i < hlen; i++) chk = polymod(chk) ^ (str.charCodeAt(i) & 0x1f); const data = Buffer.alloc(dlen - 6); let j = 0; for (let i = hlen + 1; i < str.length; i++) { const val = TABLE[str.charCodeAt(i)]; if (val === -1) throw new Error('Invalid bech32 character.'); chk = polymod(chk) ^ val; if (i < str.length - 6) data[j++] = val; } if (chk !== 1) throw new Error('Invalid bech32 checksum.'); assert(j === data.length); return [hrp, data]; } /** * Test whether a string is a bech32 string. * @param {String} str * @returns {Boolean} */ function is(str) { assert(typeof str === 'string'); try { deserialize(str); return true; } catch (e) { return false; } } /** * Convert serialized data to another base. * @param {Buffer} dst * @param {Number} dstoff * @param {Number} dstbits * @param {Buffer} src * @param {Number} srcoff * @param {Number} srcbits * @param {Boolean} pad * @returns {Buffer} */ function convert(dst, dstoff, dstbits, src, srcoff, srcbits, pad) { assert(Buffer.isBuffer(dst)); assert((dstoff >>> 0) === dstoff); assert((dstbits >>> 0) === dstbits); assert(Buffer.isBuffer(src)); assert((srcoff >>> 0) === srcoff); assert((srcbits >>> 0) === srcbits); assert(typeof pad === 'boolean'); assert(dstbits >= 1 && dstbits <= 8); assert(srcbits >= 1 && srcbits <= 8); const mask = (1 << dstbits) - 1; let acc = 0; let bits = 0; let i = srcoff; let j = dstoff; for (; i < src.length; i++) { acc = (acc << srcbits) | src[i]; bits += srcbits; while (bits >= dstbits) { bits -= dstbits; dst[j++] = (acc >>> bits) & mask; } } const left = dstbits - bits; if (pad) { if (bits) dst[j++] = (acc << left) & mask; } else { if (((acc << left) & mask) || bits >= srcbits) throw new Error('Invalid bits.'); } assert(j <= dst.length); return dst.slice(0, j); } /** * Calculate size required for bit conversion. * @param {Number} len * @param {Number} srcbits * @param {Number} dstbits * @param {Boolean} pad * @returns {Number} */ function convertSize(len, srcbits, dstbits, pad) { assert((len >>> 0) === len); assert((srcbits >>> 0) === srcbits); assert((dstbits >>> 0) === dstbits); assert(typeof pad === 'boolean'); assert(srcbits >= 1 && srcbits <= 8); assert(dstbits >= 1 && dstbits <= 8); return ((len * srcbits + (dstbits - 1) * (pad | 0)) / dstbits) >>> 0; } /** * Convert serialized data to another base. * @param {Buffer} data * @param {Number} srcbits * @param {Number} dstbits * @param {Boolean} pad * @returns {Buffer} */ function convertBits(data, srcbits, dstbits, pad) { assert(Buffer.isBuffer(data)); const size = convertSize(data.length, srcbits, dstbits, pad); const out = Buffer.alloc(size); return convert(out, 0, dstbits, data, 0, srcbits, pad); } /** * Serialize data to bech32 address. * @param {String} hrp * @param {Number} version * @param {Buffer} hash * @returns {String} */ function encode(hrp, version, hash) { assert(typeof hrp === 'string'); assert((version >>> 0) === version); assert(Buffer.isBuffer(hash)); if (version > 31) throw new Error('Invalid bech32 version.'); if (hash.length < 2 || hash.length > 40) throw new Error('Invalid bech32 data length.'); const out = POOL65; out[0] = version; const data = convert(out, 1, 5, hash, 0, 8, true); return serialize(hrp, data); } /** * Deserialize data from bech32 address. * @param {String} addr * @returns {Array} */ function decode(addr) { const [hrp, data] = deserialize(addr); if (data.length === 0 || data.length > 65) throw new Error('Invalid bech32 data length.'); const version = data[0]; if (version > 31) throw new Error('Invalid bech32 version.'); const output = data; // Works because dstbits > srcbits. const hash = convert(output, 0, 8, data, 1, 5, false); if (hash.length < 2 || hash.length > 40) throw new Error('Invalid bech32 data length.'); return [hrp, version, hash]; } /** * Test whether a string is a bech32 string. * @param {String} addr * @returns {Boolean} */ function test(addr) { assert(typeof addr === 'string'); try { decode(addr); return true; } catch (e) { return false; } } /* * Expose */ exports.native = 0; exports.serialize = serialize; exports.deserialize = deserialize; exports.is = is; exports.convertBits = convertBits; exports.encode = encode; exports.decode = decode; exports.test = test; }], [/* 58 */ 'bcrypto', '/lib/blake2b-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * blake2b.js - blake2b for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; module.exports = __node_require__(59 /* './js/blake2b' */); }], [/* 59 */ 'bcrypto', '/lib/js/blake2b.js', function(exports, module, __filename, __dirname, __meta) { /*! * blake2b.js - BLAKE2b implementation for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Parts of this software are based on dcposch/blakejs: * Daniel Clemens Posch (CC0) * https://github.com/dcposch/blakejs/blob/master/blake2b.js * * Resources: * https://en.wikipedia.org/wiki/BLAKE_(hash_function) * https://tools.ietf.org/html/rfc7693 */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); const HMAC = __node_require__(17 /* '../internal/hmac' */); /* * Constants */ const FINALIZED = 0x80000000; const IV = new Uint32Array([ 0xf3bcc908, 0x6a09e667, 0x84caa73b, 0xbb67ae85, 0xfe94f82b, 0x3c6ef372, 0x5f1d36f1, 0xa54ff53a, 0xade682d1, 0x510e527f, 0x2b3e6c1f, 0x9b05688c, 0xfb41bd6b, 0x1f83d9ab, 0x137e2179, 0x5be0cd19 ]); const SIGMA = new Uint8Array([ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x1c, 0x14, 0x08, 0x10, 0x12, 0x1e, 0x1a, 0x0c, 0x02, 0x18, 0x00, 0x04, 0x16, 0x0e, 0x0a, 0x06, 0x16, 0x10, 0x18, 0x00, 0x0a, 0x04, 0x1e, 0x1a, 0x14, 0x1c, 0x06, 0x0c, 0x0e, 0x02, 0x12, 0x08, 0x0e, 0x12, 0x06, 0x02, 0x1a, 0x18, 0x16, 0x1c, 0x04, 0x0c, 0x0a, 0x14, 0x08, 0x00, 0x1e, 0x10, 0x12, 0x00, 0x0a, 0x0e, 0x04, 0x08, 0x14, 0x1e, 0x1c, 0x02, 0x16, 0x18, 0x0c, 0x10, 0x06, 0x1a, 0x04, 0x18, 0x0c, 0x14, 0x00, 0x16, 0x10, 0x06, 0x08, 0x1a, 0x0e, 0x0a, 0x1e, 0x1c, 0x02, 0x12, 0x18, 0x0a, 0x02, 0x1e, 0x1c, 0x1a, 0x08, 0x14, 0x00, 0x0e, 0x0c, 0x06, 0x12, 0x04, 0x10, 0x16, 0x1a, 0x16, 0x0e, 0x1c, 0x18, 0x02, 0x06, 0x12, 0x0a, 0x00, 0x1e, 0x08, 0x10, 0x0c, 0x04, 0x14, 0x0c, 0x1e, 0x1c, 0x12, 0x16, 0x06, 0x00, 0x10, 0x18, 0x04, 0x1a, 0x0e, 0x02, 0x08, 0x14, 0x0a, 0x14, 0x04, 0x10, 0x08, 0x0e, 0x0c, 0x02, 0x0a, 0x1e, 0x16, 0x12, 0x1c, 0x06, 0x18, 0x1a, 0x00, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x1c, 0x14, 0x08, 0x10, 0x12, 0x1e, 0x1a, 0x0c, 0x02, 0x18, 0x00, 0x04, 0x16, 0x0e, 0x0a, 0x06 ]); /** * BLAKE2b */ class BLAKE2b { constructor() { this.state = new Uint32Array(16); this.V = new Uint32Array(32); this.M = new Uint32Array(32); this.block = Buffer.alloc(128); this.size = 32; this.count = 0; this.pos = FINALIZED; } init(size, key) { if (size == null) size = 32; assert((size >>> 0) === size); assert(key == null || Buffer.isBuffer(key)); if (size === 0 || size > 64) throw new Error('Bad output length.'); if (key && key.length > 64) throw new Error('Bad key length.'); const klen = key ? key.length : 0; for (let i = 0; i < 16; i++) this.state[i] = IV[i]; this.size = size; this.count = 0; this.pos = 0; this.state[0] ^= 0x01010000 ^ (klen << 8) ^ this.size; if (klen > 0) { const block = Buffer.alloc(128, 0x00); key.copy(block, 0); this.update(block); } return this; } update(data) { assert(Buffer.isBuffer(data)); assert(!(this.pos & FINALIZED), 'Context is not initialized.'); let off = 0; let len = data.length; if (len > 0) { const left = this.pos; const fill = 128 - left; if (len > fill) { this.pos = 0; data.copy(this.block, left, off, off + fill); this.count += 128; this._compress(this.block, 0, false); off += fill; len -= fill; while (len > 128) { this.count += 128; this._compress(data, off, false); off += 128; len -= 128; } } data.copy(this.block, this.pos, off, off + len); this.pos += len; } return this; } final() { assert(!(this.pos & FINALIZED), 'Context is not initialized.'); this.count += this.pos; this.block.fill(0, this.pos, 128); this._compress(this.block, 0, true); this.pos = FINALIZED; const out = Buffer.alloc(this.size); for (let i = 0; i < this.size; i++) out[i] = this.state[i >>> 2] >>> (8 * (i & 3)); for (let i = 0; i < 16; i++) this.state[i] = 0; for (let i = 0; i < 32; i++) { this.V[i] = 0; this.M[i] = 0; } for (let i = 0; i < 128; i++) this.block[i] = 0; return out; } _compress(block, off, last) { const {V, M} = this; for (let i = 0; i < 16; i++) { V[i] = this.state[i]; V[i + 16] = IV[i]; } // uint128 V[24] ^= this.count; V[25] ^= this.count * (1 / 0x100000000); V[26] ^= 0; V[27] ^= 0; if (last) { // last block V[28] ^= -1; V[29] ^= -1; // last node V[29] ^= 0; V[30] ^= 0; } for (let i = 0; i < 32; i++) { M[i] = readU32(block, off); off += 4; } for (let i = 0; i < 12; i++) { G(V, M, 0, 8, 16, 24, SIGMA[i * 16 + 0], SIGMA[i * 16 + 1]); G(V, M, 2, 10, 18, 26, SIGMA[i * 16 + 2], SIGMA[i * 16 + 3]); G(V, M, 4, 12, 20, 28, SIGMA[i * 16 + 4], SIGMA[i * 16 + 5]); G(V, M, 6, 14, 22, 30, SIGMA[i * 16 + 6], SIGMA[i * 16 + 7]); G(V, M, 0, 10, 20, 30, SIGMA[i * 16 + 8], SIGMA[i * 16 + 9]); G(V, M, 2, 12, 22, 24, SIGMA[i * 16 + 10], SIGMA[i * 16 + 11]); G(V, M, 4, 14, 16, 26, SIGMA[i * 16 + 12], SIGMA[i * 16 + 13]); G(V, M, 6, 8, 18, 28, SIGMA[i * 16 + 14], SIGMA[i * 16 + 15]); } for (let i = 0; i < 16; i++) this.state[i] ^= V[i] ^ V[i + 16]; } static hash() { return new BLAKE2b(); } static hmac(size) { return new HMAC(BLAKE2b, 128, [size]); } static digest(data, size, key) { const {ctx} = BLAKE2b; ctx.init(size, key); ctx.update(data); return ctx.final(); } static root(left, right, size, key) { if (size == null) size = 32; assert(Buffer.isBuffer(left) && left.length === size); assert(Buffer.isBuffer(right) && right.length === size); const {ctx} = BLAKE2b; ctx.init(size, key); ctx.update(left); ctx.update(right); return ctx.final(); } static multi(x, y, z, size, key) { const {ctx} = BLAKE2b; ctx.init(size, key); ctx.update(x); ctx.update(y); if (z) ctx.update(z); return ctx.final(); } static mac(data, key, size) { return BLAKE2b.hmac(size).init(key).update(data).final(); } } /* * Static */ BLAKE2b.native = 0; BLAKE2b.id = 'BLAKE2B256'; BLAKE2b.size = 32; BLAKE2b.bits = 256; BLAKE2b.blockSize = 128; BLAKE2b.zero = Buffer.alloc(32, 0x00); BLAKE2b.ctx = new BLAKE2b(); /* * Helpers */ function sum64i(v, a, b) { const o0 = v[a + 0] + v[b + 0]; const o1 = v[a + 1] + v[b + 1]; const c = (o0 >= 0x100000000) | 0; v[a + 0] = o0; v[a + 1] = o1 + c; } function sum64w(v, a, b0, b1) { const o0 = v[a + 0] + b0; const o1 = v[a + 1] + b1; const c = (o0 >= 0x100000000) | 0; v[a + 0] = o0; v[a + 1] = o1 + c; } function G(v, m, a, b, c, d, ix, iy) { const x0 = m[ix + 0]; const x1 = m[ix + 1]; const y0 = m[iy + 0]; const y1 = m[iy + 1]; sum64i(v, a, b); sum64w(v, a, x0, x1); const xor0 = v[d + 0] ^ v[a + 0]; const xor1 = v[d + 1] ^ v[a + 1]; v[d + 0] = xor1; v[d + 1] = xor0; sum64i(v, c, d); const xor2 = v[b + 0] ^ v[c + 0]; const xor3 = v[b + 1] ^ v[c + 1]; v[b + 0] = (xor2 >>> 24) ^ (xor3 << 8); v[b + 1] = (xor3 >>> 24) ^ (xor2 << 8); sum64i(v, a, b); sum64w(v, a, y0, y1); const xor4 = v[d + 0] ^ v[a + 0]; const xor5 = v[d + 1] ^ v[a + 1]; v[d + 0] = (xor4 >>> 16) ^ (xor5 << 16); v[d + 1] = (xor5 >>> 16) ^ (xor4 << 16); sum64i(v, c, d); const xor6 = v[b + 0] ^ v[c + 0]; const xor7 = v[b + 1] ^ v[c + 1]; v[b + 0] = (xor7 >>> 31) ^ (xor6 << 1); v[b + 1] = (xor6 >>> 31) ^ (xor7 << 1); } function readU32(data, off) { return (data[off++] + data[off++] * 0x100 + data[off++] * 0x10000 + data[off] * 0x1000000); } /* * Expose */ module.exports = BLAKE2b; }], [/* 60 */ 'bcrypto', '/lib/sha3-browser.js', function(exports, module, __filename, __dirname, __meta) { /*! * sha3.js - sha3 for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto */ 'use strict'; module.exports = __node_require__(61 /* './js/sha3' */); }], [/* 61 */ 'bcrypto', '/lib/js/sha3.js', function(exports, module, __filename, __dirname, __meta) { /*! * sha3.js - SHA3 implementation for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Resources: * https://en.wikipedia.org/wiki/SHA-3 * https://keccak.team/specifications.html * https://csrc.nist.gov/projects/hash-functions/sha-3-project/sha-3-standardization * http://dx.doi.org/10.6028/NIST.FIPS.202 */ 'use strict'; const Keccak = __node_require__(62 /* './keccak' */); /** * SHA3 */ class SHA3 extends Keccak { constructor() { super(); } final() { return super.final(0x06, null); } static hash() { return new SHA3(); } static hmac(bits) { return super.hmac(bits, 0x06, null); } static digest(data, bits) { return super.digest(data, bits, 0x06, null); } static root(left, right, bits) { return super.root(left, right, bits, 0x06, null); } static multi(x, y, z, bits) { return super.multi(x, y, z, bits, 0x06, null); } static mac(data, key, bits) { return super.mac(data, key, bits, 0x06, null); } } /* * Static */ SHA3.native = 0; SHA3.id = 'SHA3_256'; SHA3.size = 32; SHA3.bits = 256; SHA3.blockSize = 136; SHA3.zero = Buffer.alloc(32, 0x00); SHA3.ctx = new SHA3(); /* * Expose */ module.exports = SHA3; }], [/* 62 */ 'bcrypto', '/lib/js/keccak.js', function(exports, module, __filename, __dirname, __meta) { /*! * keccak.js - Keccak/SHA3 implementation for bcrypto * Copyright (c) 2017-2019, Christopher Jeffrey (MIT License). * https://github.com/bcoin-org/bcrypto * * Parts of this software are based on emn178/js-sha3: * Copyright (c) 2015-2017, Chen, Yi-Cyuan (MIT License). * https://github.com/emn178/js-sha3 * * Parts of this software are based on rhash/RHash: * Copyright (c) 2005-2014, Aleksey Kravchenko * https://github.com/rhash/RHash * * Resources: * https://en.wikipedia.org/wiki/SHA-3 * https://keccak.team/specifications.html * https://csrc.nist.gov/projects/hash-functions/sha-3-project/sha-3-standardization * http://dx.doi.org/10.6028/NIST.FIPS.202 * https://github.com/rhash/RHash/blob/master/librhash/sha3.c * https://github.com/emn178/js-sha3/blob/master/src/sha3.js */ 'use strict'; const assert = __node_require__(14 /* '../internal/assert' */); const HMAC = __node_require__(17 /* '../internal/hmac' */); /* * Constants */ const FINALIZED = 0x80000000; const ROUND_CONST = new Uint32Array([ 0x00000001, 0x00000000, 0x00008082, 0x00000000, 0x0000808a, 0x80000000, 0x80008000, 0x80000000, 0x0000808b, 0x00000000, 0x80000001, 0x00000000, 0x80008081, 0x80000000, 0x00008009, 0x80000000, 0x0000008a, 0x00000000, 0x00000088, 0x00000000, 0x80008009, 0x00000000, 0x8000000a, 0x00000000, 0x8000808b, 0x00000000, 0x0000008b, 0x80000000, 0x00008089, 0x80000000, 0x00008003, 0x80000000, 0x00008002, 0x80000000, 0x00000080, 0x80000000, 0x0000800a, 0x00000000, 0x8000000a, 0x80000000, 0x80008081, 0x80000000, 0x00008080, 0x80000000, 0x80000001, 0x00000000, 0x80008008, 0x80000000 ]); /** * Keccak */ class Keccak { constructor() { this.state = new Uint32Array(50); this.block = Buffer.alloc(200); this.bs = 136; this.pos = FINALIZED; } init(bits) { if (bits == null) bits = 256; assert((bits >>> 0) === bits); assert(bits >= 128); assert(bits <= 512); const rate = 1600 - bits * 2; assert(rate >= 0 && (rate & 63) === 0); this.bs = rate >>> 3; this.pos = 0; return this; } update(data) { assert(Buffer.isBuffer(data)); assert(!(this.pos & FINALIZED), 'Context is not initialized.'); let len = data.length; let pos = this.pos; let off = 0; this.pos = (this.pos + len) % this.bs; if (pos > 0) { let want = this.bs - pos; if (want > len) want = len; data.copy(this.block, pos, off, off + want); pos += want; len -= want; off += want; if (pos < this.bs) return this; this._transform(this.block, 0); } while (len >= this.bs) { this._transform(data, off); off += this.bs; len -= this.bs; } if (len > 0) data.copy(this.block, 0, off, off + len); return this; } final(pad, len) { if (pad == null) pad = 0x01; if (len == null || len === 0) len = 100 - (this.bs >>> 1); assert((pad & 0xff) === pad); assert((len >>> 0) === len); assert(!(this.pos & FINALIZED), 'Context is not initialized.'); this.block.fill(0, this.pos, this.bs); this.block[this.pos] |= pad; this.block[this.bs - 1] |= 0x80; this._transform(this.block, 0); this.pos = FINALIZED; assert(len <= this.bs); const out = Buffer.alloc(len); for (let i = 0; i < len; i++) out[i] = this.state[i >>> 2] >>> (8 * (i & 3)); for (let i = 0; i < 50; i++) this.state[i] = 0; for (let i = 0; i < this.bs; i++) this.block[i] = 0; return out; } _transform(block, off) { const count = this.bs >>> 2; const s = this.state; for (let i = 0; i < count; i++) s[i] ^= readU32(block, off + i * 4); for (let n = 0; n < 48; n += 2) { const c0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40]; const c1 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41]; const c2 = s[2] ^ s[12] ^ s[22] ^ s[32] ^ s[42]; const c3 = s[3] ^ s[13] ^ s[23] ^ s[33] ^ s[43]; const c4 = s[4] ^ s[14] ^ s[24] ^ s[34] ^ s[44]; const c5 = s[5] ^ s[15] ^ s[25] ^ s[35] ^ s[45]; const c6 = s[6] ^ s[16] ^ s[26] ^ s[36] ^ s[46]; const c7 = s[7] ^ s[17] ^ s[27] ^ s[37] ^ s[47]; const c8 = s[8] ^ s[18] ^ s[28] ^ s[38] ^ s[48]; const c9 = s[9] ^ s[19] ^ s[29] ^ s[39] ^ s[49]; const h0 = c8 ^ ((c2 << 1) | (c3 >>> 31)); const l0 = c9 ^ ((c3 << 1) | (c2 >>> 31)); const h1 = c0 ^ ((c4 << 1) | (c5 >>> 31)); const l1 = c1 ^ ((c5 << 1) | (c4 >>> 31)); const h2 = c2 ^ ((c6 << 1) | (c7 >>> 31)); const l2 = c3 ^ ((c7 << 1) | (c6 >>> 31)); const h3 = c4 ^ ((c8 << 1) | (c9 >>> 31)); const l3 = c5 ^ ((c9 << 1) | (c8 >>> 31)); const h4 = c6 ^ ((c0 << 1) | (c1 >>> 31)); const l4 = c7 ^ ((c1 << 1) | (c0 >>> 31)); s[0] ^= h0; s[1] ^= l0; s[10] ^= h0; s[11] ^= l0; s[20] ^= h0; s[21] ^= l0; s[30] ^= h0; s[31] ^= l0; s[40] ^= h0; s[41] ^= l0; s[2] ^= h1; s[3] ^= l1; s[12] ^= h1; s[13] ^= l1; s[22] ^= h1; s[23] ^= l1; s[32] ^= h1; s[33] ^= l1; s[42] ^= h1; s[43] ^= l1; s[4] ^= h2; s[5] ^= l2; s[14] ^= h2; s[15] ^= l2; s[24] ^= h2; s[25] ^= l2; s[34] ^= h2; s[35] ^= l2; s[44] ^= h2; s[45] ^= l2; s[6] ^= h3; s[7] ^= l3; s[16] ^= h3; s[17] ^= l3; s[26] ^= h3; s[27] ^= l3; s[36] ^= h3; s[37] ^= l3; s[46] ^= h3; s[47] ^= l3; s[8] ^= h4; s[9] ^= l4; s[18] ^= h4; s[19] ^= l4; s[28] ^= h4; s[29] ^= l4; s[38] ^= h4; s[39] ^= l4; s[48] ^= h4; s[49] ^= l4; const b0 = s[0]; const b1 = s[1]; const b32 = (s[11] << 4) | (s[10] >>> 28); const b33 = (s[10] << 4) | (s[11] >>> 28); const b14 = (s[20] << 3) | (s[21] >>> 29); const b15 = (s[21] << 3) | (s[20] >>> 29); const b46 = (s[31] << 9) | (s[30] >>> 23); const b47 = (s[30] << 9) | (s[31] >>> 23); const b28 = (s[40] << 18) | (s[41] >>> 14); const b29 = (s[41] << 18) | (s[40] >>> 14); const b20 = (s[2] << 1) | (s[3] >>> 31); const b21 = (s[3] << 1) | (s[2] >>> 31); const b2 = (s[13] << 12) | (s[12] >>> 20); const b3 = (s[12] << 12) | (s[13] >>> 20); const b34 = (s[22] << 10) | (s[23] >>> 22); const b35 = (s[23] << 10) | (s[22] >>> 22); const b16 = (s[33] << 13) | (s[32] >>> 19); const b17 = (s[32] << 13) | (s[33] >>> 19); const b48 = (s[42] << 2) | (s[43] >>> 30); const b49 = (s[43] << 2) | (s[42] >>> 30); const b40 = (s[5] << 30) | (s[4] >>> 2); const b41 = (s[4] << 30) | (s[5] >>> 2); const b22 = (s[14] << 6) | (s[15] >>> 26); const b23 = (s[15] << 6) | (s[14] >>> 26); const b4 = (s[25] << 11) | (s[24] >>> 21); const b5 = (s[24] << 11) | (s[25] >>> 21); const b36 = (s[34] << 15) | (s[35] >>> 17); const b37 = (s[35] << 15) | (s[34] >>> 17); const b18 = (s[45] << 29) | (s[44] >>> 3); const b19 = (s[44] << 29) | (s[45] >>> 3); const b10 = (s[6] << 28) | (s[7] >>> 4); const b11 = (s[7] << 28) | (s[6] >>> 4); const b42 = (s[17] << 23) | (s[16] >>> 9); const b43 = (s[16] << 23) | (s[17] >>> 9); const b24 = (s[26] << 25) | (s[27] >>> 7); const b25 = (s[27] << 25) | (s[26] >>> 7); const b6 = (s[36] << 21) | (s[37] >>> 11); const b7 = (s[37] << 21) | (s[36] >>> 11); const b38 = (s[47] << 24) | (s[46] >>> 8); const b39 = (s[46] << 24) | (s[47] >>> 8); const b30 = (s[8] << 27) | (s[9] >>> 5); const b31 = (s[9] << 27) | (s[8] >>> 5); const b12 = (s[18] << 20) | (s[19] >>> 12); const b13 = (s[19] << 20) | (s[18] >>> 12); const b44 = (s[29] << 7) | (s[28] >>> 25); const b45 = (s[28] << 7) | (s[29] >>> 25); const b26 = (s[38] << 8) | (s[39] >>> 24); const b27 = (s[39] << 8) | (s[38] >>> 24); const b8 = (s[48] << 14) | (s[49] >>> 18); const b9 = (s[49] << 14) | (s[48] >>> 18); s[0] = b0 ^ (~b2 & b4); s[1] = b1 ^ (~b3 & b5); s[10] = b10 ^ (~b12 & b14); s[11] = b11 ^ (~b13 & b15); s[20] = b20 ^ (~b22 & b24); s[21] = b21 ^ (~b23 & b25); s[30] = b30 ^ (~b32 & b34); s[31] = b31 ^ (~b33 & b35); s[40] = b40 ^ (~b42 & b44); s[41] = b41 ^ (~b43 & b45); s[2] = b2 ^ (~b4 & b6); s[3] = b3 ^ (~b5 & b7); s[12] = b12 ^ (~b14 & b16); s[13] = b13 ^ (~b15 & b17); s[22] = b22 ^ (~b24 & b26); s[23] = b23 ^ (~b25 & b27); s[32] = b32 ^ (~b34 & b36); s[33] = b33 ^ (~b35 & b37); s[42] = b42 ^ (~b44 & b46); s[43] = b43 ^ (~b45 & b47); s[4] = b4 ^ (~b6 & b8); s[5] = b5 ^ (~b7 & b9); s[14] = b14 ^ (~b16 & b18); s[15] = b15 ^ (~b17 & b19); s[24] = b24 ^ (~b26 & b28); s[25] = b25 ^ (~b27 & b29); s[34] = b34 ^ (~b36 & b38); s[35] = b35 ^ (~b37 & b39); s[44] = b44 ^ (~b46 & b48); s[45] = b45 ^ (~b47 & b49); s[6] = b6 ^ (~b8 & b0); s[7] = b7 ^ (~b9 & b1); s[16] = b16 ^ (~b18 & b10); s[17] = b17 ^ (~b19 & b11); s[26] = b26 ^ (~b28 & b20); s[27] = b27 ^ (~b29 & b21); s[36] = b36 ^ (~b38 & b30); s[37] = b37 ^ (~b39 & b31); s[46] = b46 ^ (~b48 & b40); s[47] = b47 ^ (~b49 & b41); s[8] = b8 ^ (~b0 & b2); s[9] = b9 ^ (~b1 & b3); s[18] = b18 ^ (~b10 & b12); s[19] = b19 ^ (~b11 & b13); s[28] = b28 ^ (~b20 & b22); s[29] = b29 ^ (~b21 & b23); s[38] = b38 ^ (~b30 & b32); s[39] = b39 ^ (~b31 & b33); s[48] = b48 ^ (~b40 & b42); s[49] = b49 ^ (~b41 & b43); s[0] ^= ROUND_CONST[n + 0]; s[1] ^= ROUND_CONST[n + 1]; } } static hash() { return new Keccak(); } static hmac(bits, pad, len) { if (bits == null) bits = 256; assert((bits >>> 0) === bits); const rate = 1600 - bits * 2; assert(rate >= 0 && (rate & 63) === 0); return new HMAC(Keccak, rate >>> 3, [bits], [pad, len]); } static digest(data, bits, pad, len) { return Keccak.ctx.init(bits).update(data).final(pad, len); } static root(left, right, bits, pad, len) { if (bits == null) bits = 256; if (len == null) len = 0; if (len === 0) len = bits >>> 3; assert((bits >>> 0) === bits); assert((bits & 7) === 0); assert((len >>> 0) === len); assert(Buffer.isBuffer(left) && left.length === len); assert(Buffer.isBuffer(right) && right.length === len); return Keccak.ctx.init(bits).update(left).update(right).final(pad, len); } static multi(x, y, z, bits, pad, len) { const {ctx} = Keccak; ctx.init(bits); ctx.update(x); ctx.update(y); if (z) ctx.update(z); return ctx.final(pad, len); } static mac(data, key, bits, pad, len) { return Keccak.hmac(bits, pad, len).init(key).update(data).final(); } } /* * Static */ Keccak.native = 0; Keccak.id = 'KECCAK256'; Keccak.size = 32; Keccak.bits = 256; Keccak.blockSize = 136; Keccak.zero = Buffer.alloc(32, 0x00); Keccak.ctx = new Keccak(); /* * Helpers */ function readU32(data, off) { return (data[off++] + data[off++] * 0x100 + data[off++] * 0x10000 + data[off] * 0x1000000); } /* * Expose */ module.exports = Keccak; }] ]; var __node_cache__ = []; function __node_error__(location) { var err = new Error('Cannot find module \'' + location + '\''); err.code = 'MODULE_NOT_FOUND'; throw err; } function __node_require__(id) { if ((id >>> 0) !== id || id > __node_modules__.length) return __node_error__(id); while (__node_cache__.length <= id) __node_cache__.push(null); var cache = __node_cache__[id]; if (cache) return cache.exports; var mod = __node_modules__[id]; var name = mod[0]; var path = mod[1]; var func = mod[2]; var meta; var _exports = exports; var _module = module; if (id !== 0) { _exports = {}; _module = { id: '/' + name + path, exports: _exports, parent: module.parent, filename: module.filename, loaded: false, children: module.children, paths: module.paths }; } __node_cache__[id] = _module; try { func.call(_exports, _exports, _module, __filename, __dirname, meta); } catch (e) { __node_cache__[id] = null; throw e; } __node_modules__[id] = null; if (id !== 0) _module.loaded = true; return _module.exports; } __node_require__(0);