@covenance/dlc
Version:
Crypto and Bitcoin functions for Covenance DLC implementation
94 lines • 3.53 kB
JavaScript
;
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