| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 | "use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.HDKey = exports.HARDENED_OFFSET = void 0;/*! scure-bip32 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) */const hmac_1 = require("@noble/hashes/hmac");const ripemd160_1 = require("@noble/hashes/ripemd160");const sha256_1 = require("@noble/hashes/sha256");const sha512_1 = require("@noble/hashes/sha512");const _assert_1 = require("@noble/hashes/_assert");const utils_1 = require("@noble/hashes/utils");const secp256k1_1 = require("@noble/curves/secp256k1");const modular_1 = require("@noble/curves/abstract/modular");const base_1 = require("@scure/base");const Point = secp256k1_1.secp256k1.ProjectivePoint;const base58check = (0, base_1.createBase58check)(sha256_1.sha256);function bytesToNumber(bytes) {    return BigInt(`0x${(0, utils_1.bytesToHex)(bytes)}`);}function numberToBytes(num) {    return (0, utils_1.hexToBytes)(num.toString(16).padStart(64, '0'));}const MASTER_SECRET = (0, utils_1.utf8ToBytes)('Bitcoin seed');// Bitcoin hardcoded by defaultconst BITCOIN_VERSIONS = { private: 0x0488ade4, public: 0x0488b21e };exports.HARDENED_OFFSET = 0x80000000;const hash160 = (data) => (0, ripemd160_1.ripemd160)((0, sha256_1.sha256)(data));const fromU32 = (data) => (0, utils_1.createView)(data).getUint32(0, false);const toU32 = (n) => {    if (!Number.isSafeInteger(n) || n < 0 || n > 2 ** 32 - 1) {        throw new Error(`Invalid number=${n}. Should be from 0 to 2 ** 32 - 1`);    }    const buf = new Uint8Array(4);    (0, utils_1.createView)(buf).setUint32(0, n, false);    return buf;};class HDKey {    get fingerprint() {        if (!this.pubHash) {            throw new Error('No publicKey set!');        }        return fromU32(this.pubHash);    }    get identifier() {        return this.pubHash;    }    get pubKeyHash() {        return this.pubHash;    }    get privateKey() {        return this.privKeyBytes || null;    }    get publicKey() {        return this.pubKey || null;    }    get privateExtendedKey() {        const priv = this.privateKey;        if (!priv) {            throw new Error('No private key');        }        return base58check.encode(this.serialize(this.versions.private, (0, utils_1.concatBytes)(new Uint8Array([0]), priv)));    }    get publicExtendedKey() {        if (!this.pubKey) {            throw new Error('No public key');        }        return base58check.encode(this.serialize(this.versions.public, this.pubKey));    }    static fromMasterSeed(seed, versions = BITCOIN_VERSIONS) {        (0, _assert_1.bytes)(seed);        if (8 * seed.length < 128 || 8 * seed.length > 512) {            throw new Error(`HDKey: wrong seed length=${seed.length}. Should be between 128 and 512 bits; 256 bits is advised)`);        }        const I = (0, hmac_1.hmac)(sha512_1.sha512, MASTER_SECRET, seed);        return new HDKey({            versions,            chainCode: I.slice(32),            privateKey: I.slice(0, 32),        });    }    static fromExtendedKey(base58key, versions = BITCOIN_VERSIONS) {        // => version(4) || depth(1) || fingerprint(4) || index(4) || chain(32) || key(33)        const keyBuffer = base58check.decode(base58key);        const keyView = (0, utils_1.createView)(keyBuffer);        const version = keyView.getUint32(0, false);        const opt = {            versions,            depth: keyBuffer[4],            parentFingerprint: keyView.getUint32(5, false),            index: keyView.getUint32(9, false),            chainCode: keyBuffer.slice(13, 45),        };        const key = keyBuffer.slice(45);        const isPriv = key[0] === 0;        if (version !== versions[isPriv ? 'private' : 'public']) {            throw new Error('Version mismatch');        }        if (isPriv) {            return new HDKey({ ...opt, privateKey: key.slice(1) });        }        else {            return new HDKey({ ...opt, publicKey: key });        }    }    static fromJSON(json) {        return HDKey.fromExtendedKey(json.xpriv);    }    constructor(opt) {        this.depth = 0;        this.index = 0;        this.chainCode = null;        this.parentFingerprint = 0;        if (!opt || typeof opt !== 'object') {            throw new Error('HDKey.constructor must not be called directly');        }        this.versions = opt.versions || BITCOIN_VERSIONS;        this.depth = opt.depth || 0;        this.chainCode = opt.chainCode || null;        this.index = opt.index || 0;        this.parentFingerprint = opt.parentFingerprint || 0;        if (!this.depth) {            if (this.parentFingerprint || this.index) {                throw new Error('HDKey: zero depth with non-zero index/parent fingerprint');            }        }        if (opt.publicKey && opt.privateKey) {            throw new Error('HDKey: publicKey and privateKey at same time.');        }        if (opt.privateKey) {            if (!secp256k1_1.secp256k1.utils.isValidPrivateKey(opt.privateKey)) {                throw new Error('Invalid private key');            }            this.privKey =                typeof opt.privateKey === 'bigint' ? opt.privateKey : bytesToNumber(opt.privateKey);            this.privKeyBytes = numberToBytes(this.privKey);            this.pubKey = secp256k1_1.secp256k1.getPublicKey(opt.privateKey, true);        }        else if (opt.publicKey) {            this.pubKey = Point.fromHex(opt.publicKey).toRawBytes(true); // force compressed point        }        else {            throw new Error('HDKey: no public or private key provided');        }        this.pubHash = hash160(this.pubKey);    }    derive(path) {        if (!/^[mM]'?/.test(path)) {            throw new Error('Path must start with "m" or "M"');        }        if (/^[mM]'?$/.test(path)) {            return this;        }        const parts = path.replace(/^[mM]'?\//, '').split('/');        // tslint:disable-next-line        let child = this;        for (const c of parts) {            const m = /^(\d+)('?)$/.exec(c);            const m1 = m && m[1];            if (!m || m.length !== 3 || typeof m1 !== 'string') {                throw new Error(`Invalid child index: ${c}`);            }            let idx = +m1;            if (!Number.isSafeInteger(idx) || idx >= exports.HARDENED_OFFSET) {                throw new Error('Invalid index');            }            // hardened key            if (m[2] === "'") {                idx += exports.HARDENED_OFFSET;            }            child = child.deriveChild(idx);        }        return child;    }    deriveChild(index) {        if (!this.pubKey || !this.chainCode) {            throw new Error('No publicKey or chainCode set');        }        let data = toU32(index);        if (index >= exports.HARDENED_OFFSET) {            // Hardened            const priv = this.privateKey;            if (!priv) {                throw new Error('Could not derive hardened child key');            }            // Hardened child: 0x00 || ser256(kpar) || ser32(index)            data = (0, utils_1.concatBytes)(new Uint8Array([0]), priv, data);        }        else {            // Normal child: serP(point(kpar)) || ser32(index)            data = (0, utils_1.concatBytes)(this.pubKey, data);        }        const I = (0, hmac_1.hmac)(sha512_1.sha512, this.chainCode, data);        const childTweak = bytesToNumber(I.slice(0, 32));        const chainCode = I.slice(32);        if (!secp256k1_1.secp256k1.utils.isValidPrivateKey(childTweak)) {            throw new Error('Tweak bigger than curve order');        }        const opt = {            versions: this.versions,            chainCode,            depth: this.depth + 1,            parentFingerprint: this.fingerprint,            index,        };        try {            // Private parent key -> private child key            if (this.privateKey) {                const added = (0, modular_1.mod)(this.privKey + childTweak, secp256k1_1.secp256k1.CURVE.n);                if (!secp256k1_1.secp256k1.utils.isValidPrivateKey(added)) {                    throw new Error('The tweak was out of range or the resulted private key is invalid');                }                opt.privateKey = added;            }            else {                const added = Point.fromHex(this.pubKey).add(Point.fromPrivateKey(childTweak));                // Cryptographically impossible: hmac-sha512 preimage would need to be found                if (added.equals(Point.ZERO)) {                    throw new Error('The tweak was equal to negative P, which made the result key invalid');                }                opt.publicKey = added.toRawBytes(true);            }            return new HDKey(opt);        }        catch (err) {            return this.deriveChild(index + 1);        }    }    sign(hash) {        if (!this.privateKey) {            throw new Error('No privateKey set!');        }        (0, _assert_1.bytes)(hash, 32);        return secp256k1_1.secp256k1.sign(hash, this.privKey).toCompactRawBytes();    }    verify(hash, signature) {        (0, _assert_1.bytes)(hash, 32);        (0, _assert_1.bytes)(signature, 64);        if (!this.publicKey) {            throw new Error('No publicKey set!');        }        let sig;        try {            sig = secp256k1_1.secp256k1.Signature.fromCompact(signature);        }        catch (error) {            return false;        }        return secp256k1_1.secp256k1.verify(sig, hash, this.publicKey);    }    wipePrivateData() {        this.privKey = undefined;        if (this.privKeyBytes) {            this.privKeyBytes.fill(0);            this.privKeyBytes = undefined;        }        return this;    }    toJSON() {        return {            xpriv: this.privateExtendedKey,            xpub: this.publicExtendedKey,        };    }    serialize(version, key) {        if (!this.chainCode) {            throw new Error('No chainCode set');        }        (0, _assert_1.bytes)(key, 33);        // version(4) || depth(1) || fingerprint(4) || index(4) || chain(32) || key(33)        return (0, utils_1.concatBytes)(toU32(version), new Uint8Array([this.depth]), toU32(this.parentFingerprint), toU32(this.index), this.chainCode, key);    }}exports.HDKey = HDKey;//# sourceMappingURL=index.js.map
 |