|
1 | 1 | 'use strict';
|
2 | 2 | Object.defineProperty(exports, '__esModule', { value: true });
|
3 |
| -exports.taggedHash = exports.hash256 = exports.hash160 = exports.sha256 = exports.sha1 = exports.ripemd160 = void 0; |
| 3 | +exports.taggedHash = exports.hash256 = exports.hash160 = exports.sha256 = exports.sha1 = exports.ripemd160 = exports.isXOnlyPoint = exports.isPoint = void 0; |
4 | 4 | const createHash = require('create-hash');
|
| 5 | +const EC_P = BigInt( |
| 6 | + `0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f`, |
| 7 | +); |
| 8 | +const EC_B = BigInt(7); |
| 9 | +const BN_ZERO = BigInt(0); |
| 10 | +function weierstrass(x) { |
| 11 | + const x2 = (x * x) % EC_P; |
| 12 | + const x3 = (x2 * x) % EC_P; |
| 13 | + return (x3 /* + a=0 a*x */ + EC_B) % EC_P; |
| 14 | +} |
| 15 | +// For prime P, the Jacobi symbol is 1 iff a is a quadratic residue mod P |
| 16 | +function jacobiSymbol(a) { |
| 17 | + // Idea from noble-secp256k1, to be nice to bad JS parsers |
| 18 | + const _1n = BigInt(1); |
| 19 | + const _2n = BigInt(2); |
| 20 | + const _3n = BigInt(3); |
| 21 | + const _5n = BigInt(5); |
| 22 | + const _7n = BigInt(7); |
| 23 | + if (a === BN_ZERO) return 0; |
| 24 | + let p = EC_P; |
| 25 | + let sign = 1; |
| 26 | + for (;;) { |
| 27 | + let and3; |
| 28 | + // Handle runs of zeros efficiently w/o flipping sign each time |
| 29 | + for (and3 = a & _3n; and3 === BN_ZERO; a >>= _2n, and3 = a & _3n); |
| 30 | + // If there's one more zero, shift it off and flip the sign |
| 31 | + if (and3 === _2n) { |
| 32 | + a >>= _1n; |
| 33 | + const pand7 = p & _7n; |
| 34 | + if (pand7 === _3n || pand7 === _5n) sign = -sign; |
| 35 | + } |
| 36 | + if (a === _1n) break; |
| 37 | + if ((_3n & a) === _3n && (_3n & p) === _3n) sign = -sign; |
| 38 | + [a, p] = [p % a, a]; |
| 39 | + } |
| 40 | + return sign > 0 ? 1 : -1; |
| 41 | +} |
| 42 | +function isPoint(p) { |
| 43 | + if (p.length < 33) return false; |
| 44 | + const t = p[0]; |
| 45 | + if (p.length === 33) { |
| 46 | + return (t === 0x02 || t === 0x03) && isXOnlyPoint(p.slice(1)); |
| 47 | + } |
| 48 | + if (t !== 0x04 || p.length !== 65) return false; |
| 49 | + const x = BigInt(`0x${p.slice(1, 33).toString('hex')}`); |
| 50 | + if (x === BN_ZERO) return false; |
| 51 | + if (x >= EC_P) return false; |
| 52 | + const y = BigInt(`0x${p.slice(33).toString('hex')}`); |
| 53 | + if (y === BN_ZERO) return false; |
| 54 | + if (y >= EC_P) return false; |
| 55 | + const left = (y * y) % EC_P; |
| 56 | + const right = weierstrass(x); |
| 57 | + return (left - right) % EC_P === BN_ZERO; |
| 58 | +} |
| 59 | +exports.isPoint = isPoint; |
| 60 | +function isXOnlyPoint(p) { |
| 61 | + if (p.length !== 32) return false; |
| 62 | + const x = BigInt(`0x${p.toString('hex')}`); |
| 63 | + if (x === BN_ZERO) return false; |
| 64 | + if (x >= EC_P) return false; |
| 65 | + const y2 = weierstrass(x); |
| 66 | + return jacobiSymbol(y2) === 1; |
| 67 | +} |
| 68 | +exports.isXOnlyPoint = isXOnlyPoint; |
5 | 69 | function ripemd160(buffer) {
|
6 | 70 | try {
|
7 | 71 | return createHash('rmd160')
|
|
0 commit comments