Viewing File: /home/ubuntu/efiexchange-node-base/node_modules/bip32/src/esm/bip32.js

import * as crypto from './crypto.js';
import { testEcc } from './testecc.js';
import { base58check } from '@scure/base';
import { sha256 } from '@noble/hashes/sha256';
import * as v from 'valibot';
import { Bip32PathSchema, Buffer256Bit, Buffer33Bytes, NetworkSchema, Uint31Schema, Uint32Schema, } from './types.js';
import * as wif from 'wif';
import * as tools from 'uint8array-tools';
const _bs58check = base58check(sha256);
const bs58check = {
    encode: (data) => _bs58check.encode(data),
    decode: (str) => _bs58check.decode(str),
};
export function BIP32Factory(ecc) {
    testEcc(ecc);
    const BITCOIN = {
        messagePrefix: '\x18Bitcoin Signed Message:\n',
        bech32: 'bc',
        bip32: {
            public: 0x0488b21e,
            private: 0x0488ade4,
        },
        pubKeyHash: 0x00,
        scriptHash: 0x05,
        wif: 0x80,
    };
    const HIGHEST_BIT = 0x80000000;
    function toXOnly(pubKey) {
        return pubKey.length === 32 ? pubKey : pubKey.slice(1, 33);
    }
    class Bip32Signer {
        __D;
        __Q;
        lowR = false;
        constructor(__D, __Q) {
            this.__D = __D;
            this.__Q = __Q;
        }
        get publicKey() {
            if (this.__Q === undefined)
                this.__Q = ecc.pointFromScalar(this.__D, true);
            return this.__Q;
        }
        get privateKey() {
            return this.__D;
        }
        sign(hash, lowR) {
            if (!this.privateKey)
                throw new Error('Missing private key');
            if (lowR === undefined)
                lowR = this.lowR;
            if (lowR === false) {
                return ecc.sign(hash, this.privateKey);
            }
            else {
                let sig = ecc.sign(hash, this.privateKey);
                const extraData = new Uint8Array(32);
                let counter = 0;
                // if first try is lowR, skip the loop
                // for second try and on, add extra entropy counting up
                while (sig[0] > 0x7f) {
                    counter++;
                    tools.writeUInt32(extraData, 0, counter, 'LE');
                    sig = ecc.sign(hash, this.privateKey, extraData);
                }
                return sig;
            }
        }
        signSchnorr(hash) {
            if (!this.privateKey)
                throw new Error('Missing private key');
            if (!ecc.signSchnorr)
                throw new Error('signSchnorr not supported by ecc library');
            return ecc.signSchnorr(hash, this.privateKey);
        }
        verify(hash, signature) {
            return ecc.verify(hash, this.publicKey, signature);
        }
        verifySchnorr(hash, signature) {
            if (!ecc.verifySchnorr)
                throw new Error('verifySchnorr not supported by ecc library');
            return ecc.verifySchnorr(hash, this.publicKey.subarray(1, 33), signature);
        }
    }
    class BIP32 extends Bip32Signer {
        chainCode;
        network;
        __DEPTH;
        __INDEX;
        __PARENT_FINGERPRINT;
        constructor(__D, __Q, chainCode, network, __DEPTH = 0, __INDEX = 0, __PARENT_FINGERPRINT = 0x00000000) {
            super(__D, __Q);
            this.chainCode = chainCode;
            this.network = network;
            this.__DEPTH = __DEPTH;
            this.__INDEX = __INDEX;
            this.__PARENT_FINGERPRINT = __PARENT_FINGERPRINT;
            v.parse(NetworkSchema, network);
        }
        get depth() {
            return this.__DEPTH;
        }
        get index() {
            return this.__INDEX;
        }
        get parentFingerprint() {
            return this.__PARENT_FINGERPRINT;
        }
        get identifier() {
            return crypto.hash160(this.publicKey);
        }
        get fingerprint() {
            return this.identifier.slice(0, 4);
        }
        get compressed() {
            return true;
        }
        // Private === not neutered
        // Public === neutered
        isNeutered() {
            return this.__D === undefined;
        }
        neutered() {
            return fromPublicKeyLocal(this.publicKey, this.chainCode, this.network, this.depth, this.index, this.parentFingerprint);
        }
        toBase58() {
            const network = this.network;
            const version = !this.isNeutered()
                ? network.bip32.private
                : network.bip32.public;
            const buffer = new Uint8Array(78);
            // 4 bytes: version bytes
            tools.writeUInt32(buffer, 0, version, 'BE');
            // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ....
            tools.writeUInt8(buffer, 4, this.depth);
            // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
            tools.writeUInt32(buffer, 5, this.parentFingerprint, 'BE');
            // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized.
            // This is encoded in big endian. (0x00000000 if master key)
            tools.writeUInt32(buffer, 9, this.index, 'BE');
            // 32 bytes: the chain code
            buffer.set(this.chainCode, 13);
            // 33 bytes: the public key or private key data
            if (!this.isNeutered()) {
                // 0x00 + k for private keys
                tools.writeUInt8(buffer, 45, 0);
                buffer.set(this.privateKey, 46);
                // 33 bytes: the public key
            }
            else {
                // X9.62 encoding for public keys
                buffer.set(this.publicKey, 45);
            }
            return bs58check.encode(buffer);
        }
        toWIF() {
            if (!this.privateKey)
                throw new TypeError('Missing private key');
            return wif.encode({
                version: this.network.wif,
                privateKey: this.privateKey,
                compressed: true,
            });
        }
        // https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#child-key-derivation-ckd-functions
        derive(index) {
            v.parse(Uint32Schema, index);
            const isHardened = index >= HIGHEST_BIT;
            const data = new Uint8Array(37);
            // Hardened child
            if (isHardened) {
                if (this.isNeutered())
                    throw new TypeError('Missing private key for hardened child key');
                // data = 0x00 || ser256(kpar) || ser32(index)
                data[0] = 0x00;
                data.set(this.privateKey, 1);
                tools.writeUInt32(data, 33, index, 'BE');
                // Normal child
            }
            else {
                // data = serP(point(kpar)) || ser32(index)
                //      = serP(Kpar) || ser32(index)
                data.set(this.publicKey, 0);
                tools.writeUInt32(data, 33, index, 'BE');
            }
            const I = crypto.hmacSHA512(this.chainCode, data);
            const IL = I.slice(0, 32);
            const IR = I.slice(32);
            // if parse256(IL) >= n, proceed with the next value for i
            if (!ecc.isPrivate(IL))
                return this.derive(index + 1);
            // Private parent key -> private child key
            let hd;
            if (!this.isNeutered()) {
                // ki = parse256(IL) + kpar (mod n)
                const ki = ecc.privateAdd(this.privateKey, IL);
                // In case ki == 0, proceed with the next value for i
                if (ki == null)
                    return this.derive(index + 1);
                hd = fromPrivateKeyLocal(ki, IR, this.network, this.depth + 1, index, tools.readUInt32(this.fingerprint, 0, 'BE'));
                // Public parent key -> public child key
            }
            else {
                // Ki = point(parse256(IL)) + Kpar
                //    = G*IL + Kpar
                const Ki = ecc.pointAddScalar(this.publicKey, IL, true);
                // In case Ki is the point at infinity, proceed with the next value for i
                if (Ki === null)
                    return this.derive(index + 1);
                hd = fromPublicKeyLocal(Ki, IR, this.network, this.depth + 1, index, tools.readUInt32(this.fingerprint, 0, 'BE'));
            }
            return hd;
        }
        deriveHardened(index) {
            if (typeof v.parse(Uint31Schema, index) === 'number')
                // Only derives hardened private keys by default
                return this.derive(index + HIGHEST_BIT);
            throw new TypeError('Expected UInt31, got ' + index);
        }
        derivePath(path) {
            v.parse(Bip32PathSchema, path);
            let splitPath = path.split('/');
            if (splitPath[0] === 'm') {
                if (this.parentFingerprint)
                    throw new TypeError('Expected master, got child');
                splitPath = splitPath.slice(1);
            }
            return splitPath.reduce((prevHd, indexStr) => {
                let index;
                if (indexStr.slice(-1) === `'`) {
                    index = parseInt(indexStr.slice(0, -1), 10);
                    return prevHd.deriveHardened(index);
                }
                else {
                    index = parseInt(indexStr, 10);
                    return prevHd.derive(index);
                }
            }, this);
        }
        tweak(t) {
            if (this.privateKey)
                return this.tweakFromPrivateKey(t);
            return this.tweakFromPublicKey(t);
        }
        tweakFromPublicKey(t) {
            const xOnlyPubKey = toXOnly(this.publicKey);
            if (!ecc.xOnlyPointAddTweak)
                throw new Error('xOnlyPointAddTweak not supported by ecc library');
            const tweakedPublicKey = ecc.xOnlyPointAddTweak(xOnlyPubKey, t);
            if (!tweakedPublicKey || tweakedPublicKey.xOnlyPubkey === null)
                throw new Error('Cannot tweak public key!');
            const parityByte = Uint8Array.from([
                tweakedPublicKey.parity === 0 ? 0x02 : 0x03,
            ]);
            const tweakedPublicKeyCompresed = tools.concat([
                parityByte,
                tweakedPublicKey.xOnlyPubkey,
            ]);
            return new Bip32Signer(undefined, tweakedPublicKeyCompresed);
        }
        tweakFromPrivateKey(t) {
            const hasOddY = this.publicKey[0] === 3 ||
                (this.publicKey[0] === 4 && (this.publicKey[64] & 1) === 1);
            const privateKey = (() => {
                if (!hasOddY)
                    return this.privateKey;
                else if (!ecc.privateNegate)
                    throw new Error('privateNegate not supported by ecc library');
                else
                    return ecc.privateNegate(this.privateKey);
            })();
            const tweakedPrivateKey = ecc.privateAdd(privateKey, t);
            if (!tweakedPrivateKey)
                throw new Error('Invalid tweaked private key!');
            return new Bip32Signer(tweakedPrivateKey, undefined);
        }
    }
    function fromBase58(inString, network) {
        const buffer = bs58check.decode(inString);
        if (buffer.length !== 78)
            throw new TypeError('Invalid buffer length');
        network = network || BITCOIN;
        // 4 bytes: version bytes
        const version = tools.readUInt32(buffer, 0, 'BE');
        if (version !== network.bip32.private && version !== network.bip32.public)
            throw new TypeError('Invalid network version');
        // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ...
        const depth = buffer[4];
        // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
        const parentFingerprint = tools.readUInt32(buffer, 5, 'BE');
        if (depth === 0) {
            if (parentFingerprint !== 0x00000000)
                throw new TypeError('Invalid parent fingerprint');
        }
        // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized.
        // This is encoded in MSB order. (0x00000000 if master key)
        const index = tools.readUInt32(buffer, 9, 'BE');
        if (depth === 0 && index !== 0)
            throw new TypeError('Invalid index');
        // 32 bytes: the chain code
        const chainCode = buffer.slice(13, 45);
        let hd;
        // 33 bytes: private key data (0x00 + k)
        if (version === network.bip32.private) {
            if (buffer[45] !== 0x00)
                throw new TypeError('Invalid private key');
            const k = buffer.slice(46, 78);
            hd = fromPrivateKeyLocal(k, chainCode, network, depth, index, parentFingerprint);
            // 33 bytes: public key data (0x02 + X or 0x03 + X)
        }
        else {
            const X = buffer.slice(45, 78);
            hd = fromPublicKeyLocal(X, chainCode, network, depth, index, parentFingerprint);
        }
        return hd;
    }
    function fromPrivateKey(privateKey, chainCode, network) {
        return fromPrivateKeyLocal(privateKey, chainCode, network);
    }
    function fromPrivateKeyLocal(privateKey, chainCode, network, depth, index, parentFingerprint) {
        v.parse(Buffer256Bit, privateKey);
        v.parse(Buffer256Bit, chainCode);
        network = network || BITCOIN;
        if (!ecc.isPrivate(privateKey))
            throw new TypeError('Private key not in range [1, n)');
        return new BIP32(privateKey, undefined, chainCode, network, depth, index, parentFingerprint);
    }
    function fromPublicKey(publicKey, chainCode, network) {
        return fromPublicKeyLocal(publicKey, chainCode, network);
    }
    function fromPublicKeyLocal(publicKey, chainCode, network, depth, index, parentFingerprint) {
        v.parse(Buffer33Bytes, publicKey);
        v.parse(Buffer256Bit, chainCode);
        network = network || BITCOIN;
        // verify the X coordinate is a point on the curve
        if (!ecc.isPoint(publicKey))
            throw new TypeError('Point is not on the curve');
        return new BIP32(undefined, publicKey, chainCode, network, depth, index, parentFingerprint);
    }
    function fromSeed(seed, network) {
        v.parse(v.instance(Uint8Array), seed);
        if (seed.length < 16)
            throw new TypeError('Seed should be at least 128 bits');
        if (seed.length > 64)
            throw new TypeError('Seed should be at most 512 bits');
        network = network || BITCOIN;
        const I = crypto.hmacSHA512(tools.fromUtf8('Bitcoin seed'), seed);
        const IL = I.slice(0, 32);
        const IR = I.slice(32);
        return fromPrivateKey(IL, IR, network);
    }
    return {
        fromSeed,
        fromBase58,
        fromPublicKey,
        fromPrivateKey,
    };
}
Back to Directory File Manager