UNPKG

@covenance/dlc

Version:

Crypto and Bitcoin functions for Covenance DLC implementation

94 lines 3.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.verifySig = verifySig; exports.verifySigStrict = verifySigStrict; exports.encodeXOnlyPubkey = encodeXOnlyPubkey; exports.mod = mod; const secp256k1_1 = require("./secp256k1"); const utils_1 = require("../utils"); /** * Function to verify a general signature * @param sig - The signature to verify * @param pubKey - The public key to verify against * @param message - The message that was signed * @param tag - The tag to use for hashing (defaults to BIP0340/challenge) * @returns Boolean indicating whether the signature is valid */ async function verifySig(sig, pubKey, message, tag = Uint8Array.from(Buffer.from('7bb52d7a9fef58323eb1bf7a407db382d2f3f2d81bb1224f49fe518f6d48d37c', 'hex')) // SHA256('BIP0340/challenge') ) { // Compute H(tag||tag||R||P||m) const hashInput = new Uint8Array([ ...tag, ...tag, ...sig.R.toRawBytes(true).slice(1), ...pubKey.toRawBytes(true).slice(1), ...message ]); const hash = await (0, utils_1.sha256)(hashInput); const e = mod(BigInt('0x' + (0, utils_1.bytesToHex)(hash)), secp256k1_1.CURVE.n); // Compute s * G const sG = secp256k1_1.Point.BASE.multiply(sig.s); // Compute R + e * P const rightSide = sig.R.add(pubKey.multiply(e)); // Verify s * G = R + e * P return sG.equals(rightSide); } /** * Function to verify a signature with additional script interpreter like verification * @param sig - The signature to verify * @param pubKey - The public key to verify against * @param message - The message that was signed * @param tag - The tag to use for hashing (defaults to BIP0340/challenge) * @returns Boolean indicating whether the signature is valid */ async function verifySigStrict(sig, pubKey, message, tag = Uint8Array.from(Buffer.from('7bb52d7a9fef58323eb1bf7a407db382d2f3f2d81bb1224f49fe518f6d48d37c', 'hex')) // SHA256('BIP0340/challenge') ) { // First do basic signature verification const basicVerification = await verifySig(sig, pubKey, message, tag); if (!basicVerification) return false; // Perform additional script interpreter like verification const r = sig.R.x; const s = sig.s; if (r >= secp256k1_1.CURVE.P || s >= secp256k1_1.CURVE.n) { return false; } const hashInput = new Uint8Array([ ...tag, ...tag, ...sig.R.toRawBytes(true).slice(1), ...pubKey.toRawBytes(true).slice(1), ...message ]); const hash = await (0, utils_1.sha256)(hashInput); const e = mod(BigInt('0x' + (0, utils_1.bytesToHex)(hash)), secp256k1_1.CURVE.n); const sG = secp256k1_1.Point.BASE.multiply(sig.s); const R = sG.add(pubKey.multiply(e).negate()); if (!(R.y % 2n === 0n) || !(R.x === r)) { return false; } return true; } /** * Encodes a point as a BIP-340 x-only key * @param point - The point to encode * @returns The encoded point as a 32-byte Buffer */ function encodeXOnlyPubkey({ x, y }) { if (y & 1n) y = secp256k1_1.CURVE.P - y; // even-y representative if (x < 0n || x >= secp256k1_1.CURVE.P) throw new RangeError("x out of range"); return Buffer.from(x.toString(16).padStart(64, "0"), "hex"); } /** * Modulus operation that handles negative numbers * @param k - The number to mod * @param n - The modulus * @returns The modulus of k and n */ function mod(k, n) { return ((k % n) + n) % n; } //# sourceMappingURL=general.js.map