UNPKG

@okxweb3/crypto-lib

Version:

A base package for @okxweb3/coin-*

300 lines 11.2 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.fromSeed = exports.fromPublicKey = exports.fromPrivateKey = exports.fromBase58 = exports.tinySecp256k1Interface = void 0; const base = __importStar(require("../base")); const base_1 = require("@scure/base"); const hash_1 = require("../base/hash"); const bytesCoder = (0, base_1.base58check)(hash_1.sha256); const api = require('./api'); const typeforce = require('typeforce'); const wif = require('wif'); function createApi(secp256k1) { return { isPoint: (p) => secp256k1.publicKeyVerify(p), isPrivate: (d) => secp256k1.privateKeyVerify(d), pointAddScalar: (p, tweak, compress) => secp256k1.publicKeyTweakAdd(p, tweak, compress), pointFromScalar: (d, compress) => secp256k1.publicKeyCreate(d, compress), privateAdd: (d, tweak) => secp256k1.privateKeyTweakAdd(new Uint8Array(d), tweak), sign: (h, d) => secp256k1.ecdsaSign(h, d), verify: (h, Q, signature) => secp256k1.ecdsaVerify(signature, h, Q), }; } function createTinySecp256k1Interface(secp256k1) { return { isPoint: (p) => secp256k1.publicKeyVerify(p), pointCompress: (p, compressed) => Uint8Array.from(secp256k1.publicKeyConvert(p, compressed != null ? compressed : true)), isPrivate: (d) => secp256k1.privateKeyVerify(d), pointFromScalar: (d, compressed) => { const r = secp256k1.publicKeyCreate(d, compressed != null ? compressed : true); if (r == null) { return null; } return Uint8Array.from(r); }, sign: (h, d, e) => Uint8Array.from(secp256k1.ecdsaSign(h, d)), verify: (h, Q, signature, strict) => secp256k1.ecdsaVerify(signature, h, Q), }; } const ecc = createApi(api); exports.tinySecp256k1Interface = createTinySecp256k1Interface(api); const UINT256_TYPE = typeforce.BufferN(32); const NETWORK_TYPE = typeforce.compile({ wif: typeforce.UInt8, bip32: { public: typeforce.UInt32, private: typeforce.UInt32, }, }); const BITCOIN = { messagePrefix: '\x18Bitcoin Signed Message:\n', bech32: 'bc', bip32: { public: 0x0488b21e, private: 0x0488ade4, }, pubKeyHash: 0x00, scriptHash: 0x05, wif: 0x80, }; const HIGHEST_BIT = 0x80000000; const UINT31_MAX = Math.pow(2, 31) - 1; function BIP32Path(value) { return (typeforce.String(value) && value.match(/^(m\/)?(\d+'?\/)*\d+'?$/) !== null); } function UInt31(value) { return typeforce.UInt32(value) && value <= UINT31_MAX; } class BIP32 { constructor(__D, __Q, chainCode, network, __DEPTH = 0, __INDEX = 0, __PARENT_FINGERPRINT = 0x00000000) { this.__D = __D; this.__Q = __Q; this.chainCode = chainCode; this.network = network; this.__DEPTH = __DEPTH; this.__INDEX = __INDEX; this.__PARENT_FINGERPRINT = __PARENT_FINGERPRINT; typeforce(NETWORK_TYPE, network); this.lowR = false; } get depth() { return this.__DEPTH; } get index() { return this.__INDEX; } get parentFingerprint() { return this.__PARENT_FINGERPRINT; } get publicKey() { if (this.__Q === undefined) this.__Q = Buffer.from(ecc.pointFromScalar(this.__D, true)); return this.__Q; } get privateKey() { return this.__D; } get identifier() { return Buffer.from(base.hash160(this.publicKey)); } get fingerprint() { return this.identifier.slice(0, 4); } get compressed() { return true; } 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 = Buffer.allocUnsafe(78); buffer.writeUInt32BE(version, 0); buffer.writeUInt8(this.depth, 4); buffer.writeUInt32BE(this.parentFingerprint, 5); buffer.writeUInt32BE(this.index, 9); this.chainCode.copy(buffer, 13); if (!this.isNeutered()) { buffer.writeUInt8(0, 45); this.privateKey.copy(buffer, 46); } else { this.publicKey.copy(buffer, 45); } return bytesCoder.encode(buffer); } toWIF() { if (!this.privateKey) throw new TypeError('Missing private key'); return wif.encode(this.network.wif, this.privateKey, true); } derive(index) { typeforce(typeforce.UInt32, index); const isHardened = index >= HIGHEST_BIT; const data = Buffer.allocUnsafe(37); if (isHardened) { if (this.isNeutered()) throw new TypeError('Missing private key for hardened child key'); data[0] = 0x00; this.privateKey.copy(data, 1); data.writeUInt32BE(index, 33); } else { this.publicKey.copy(data, 0); data.writeUInt32BE(index, 33); } const I = base.hmacSHA512(this.chainCode, data); const IL = I.slice(0, 32); const IR = I.slice(32); if (!ecc.isPrivate(IL)) return this.derive(index + 1); let hd; if (!this.isNeutered()) { const ki = ecc.privateAdd(this.privateKey, IL); if (ki == null) return this.derive(index + 1); hd = fromPrivateKeyLocal(ki, IR, this.network, this.depth + 1, index, this.fingerprint.readUInt32BE(0)); } else { const Ki = ecc.pointAddScalar(this.publicKey, IL, true); if (Ki === null) return this.derive(index + 1); hd = fromPublicKeyLocal(Ki, IR, this.network, this.depth + 1, index, this.fingerprint.readUInt32BE(0)); } return hd; } deriveHardened(index) { typeforce(UInt31, index); return this.derive(index + HIGHEST_BIT); } derivePath(path) { typeforce(BIP32Path, 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); } sign(hash) { if (!this.privateKey) throw new Error('Missing private key'); return ecc.sign(hash, this.privateKey); } verify(hash, signature) { return ecc.verify(hash, this.publicKey, signature); } } function fromBase58(inString, network) { const buffer = Buffer.from(bytesCoder.decode(inString)); if (buffer.length !== 78) throw new TypeError('Invalid buffer length'); network = network || BITCOIN; const version = buffer.readUInt32BE(0); if (version !== network.bip32.private && version !== network.bip32.public) throw new TypeError('Invalid network version'); const depth = buffer[4]; const parentFingerprint = buffer.readUInt32BE(5); if (depth === 0) { if (parentFingerprint !== 0x00000000) throw new TypeError('Invalid parent fingerprint'); } const index = buffer.readUInt32BE(9); if (depth === 0 && index !== 0) throw new TypeError('Invalid index'); const chainCode = buffer.slice(13, 45); let hd; if (version === network.bip32.private) { if (buffer.readUInt8(45) !== 0x00) throw new TypeError('Invalid private key'); const k = buffer.slice(46, 78); hd = fromPrivateKeyLocal(k, chainCode, network, depth, index, parentFingerprint); } else { const X = buffer.slice(45, 78); hd = fromPublicKeyLocal(X, chainCode, network, depth, index, parentFingerprint); } return hd; } exports.fromBase58 = fromBase58; function fromPrivateKey(privateKey, chainCode, network) { return fromPrivateKeyLocal(privateKey, chainCode, network); } exports.fromPrivateKey = fromPrivateKey; function fromPrivateKeyLocal(privateKey, chainCode, network, depth, index, parentFingerprint) { typeforce({ privateKey: UINT256_TYPE, chainCode: UINT256_TYPE, }, { privateKey, 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); } exports.fromPublicKey = fromPublicKey; function fromPublicKeyLocal(publicKey, chainCode, network, depth, index, parentFingerprint) { typeforce({ publicKey: typeforce.BufferN(33), chainCode: UINT256_TYPE, }, { publicKey, chainCode }); network = network || BITCOIN; 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) { typeforce(typeforce.Buffer, 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 = base.hmacSHA512(Buffer.from('Bitcoin seed', 'utf8'), seed); const IL = I.slice(0, 32); const IR = I.slice(32); return fromPrivateKey(IL, IR, network); } exports.fromSeed = fromSeed; //# sourceMappingURL=bip32.js.map