UNPKG

j-bitcoin

Version:

Comprehensive JavaScript/TypeScript Bitcoin (BTC) wallet library with custodial and non-custodial support, hierarchical deterministic keys, threshold signatures, and advanced cryptographic features

491 lines (390 loc) 48.4 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>src/transaction/message-signing.js - J-Bitcoin - Bitcoin Wallet Library</title> <meta name="description" content="JavaScript/TypeScript Bitcoin wallet library with HD wallets, threshold signatures, and BIP compliance" /> <meta name="keywords" content="bitcoin, btc, cryptocurrency, wallet, javascript, typescript, threshold signatures, bip32, bip39" /> <meta name="keyword" content="bitcoin, btc, cryptocurrency, wallet, javascript, typescript, threshold signatures, bip32, bip39" /> <script src="scripts/prettify/prettify.js"></script> <script src="scripts/prettify/lang-css.js"></script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc.css"> <script src="scripts/nav.js" defer></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger" class="navicon-button x"> <div class="navicon"></div> </label> <label for="nav-trigger" class="overlay"></label> <nav class="wrap"> <input type="text" id="nav-search" placeholder="Search" /> <h2><a href="index.html">Home</a></h2><h2><a href="https://github.com/yfbsei/J-Bitcoin" target="_blank" class="menu-item home-link" id="home-link" >🏠 Home</a></h2><h2><a href="https://github.com/yfbsei/J-Bitcoin" target="_blank" class="menu-item github-link" id="github-link" >📚 GitHub</a></h2><h2><a href="https://www.npmjs.com/package/j-bitcoin" target="_blank" class="menu-item npm-link" id="npm-link" >📦 NPM</a></h2><h2><a href="https://github.com/yfbsei/J-Bitcoin/tree/main/examples" target="_blank" class="menu-item examples-link" id="examples-link" >🔧 Examples</a></h2><h2><a href="https://github.com/yfbsei/J-Bitcoin/blob/main/CHANGELOG.md" target="_blank" class="menu-item changelog-link" id="changelog-link" >📊 Changelog</a></h2><h3>Classes</h3><ul><li><a href="BIP143.html">BIP143</a><ul class='methods'><li data-type='method' style='display: none;'><a href="BIP143.html#.calculate">calculate</a></li><li data-type='method' style='display: none;'><a href="BIP143.html#.forP2WPKH">forP2WPKH</a></li><li data-type='method' style='display: none;'><a href="BIP143.html#.hashOutputs">hashOutputs</a></li><li data-type='method' style='display: none;'><a href="BIP143.html#.hashPrevouts">hashPrevouts</a></li><li data-type='method' style='display: none;'><a href="BIP143.html#.hashSequence">hashSequence</a></li></ul></li><li><a href="BIP322.html">BIP322</a><ul class='methods'><li data-type='method' style='display: none;'><a href="BIP322.html#.createToSign">createToSign</a></li><li data-type='method' style='display: none;'><a href="BIP322.html#.createToSpend">createToSpend</a></li><li data-type='method' style='display: none;'><a href="BIP322.html#.hashMessage">hashMessage</a></li><li data-type='method' style='display: none;'><a href="BIP322.html#.sign">sign</a></li><li data-type='method' style='display: none;'><a href="BIP322.html#.signLegacy">signLegacy</a></li><li data-type='method' style='display: none;'><a href="BIP322.html#.verify">verify</a></li><li data-type='method' style='display: none;'><a href="BIP322.html#.verifyLegacy">verifyLegacy</a></li></ul></li><li><a href="BIP322Error.html">BIP322Error</a></li><li><a href="BIP341.html">BIP341</a><ul class='methods'><li data-type='method' style='display: none;'><a href="BIP341.html#.calculate">calculate</a></li><li data-type='method' style='display: none;'><a href="BIP341.html#.forScriptPath">forScriptPath</a></li><li data-type='method' style='display: none;'><a href="BIP341.html#.shaAmounts">shaAmounts</a></li><li data-type='method' style='display: none;'><a href="BIP341.html#.shaOutputs">shaOutputs</a></li><li data-type='method' style='display: none;'><a href="BIP341.html#.shaPrevouts">shaPrevouts</a></li><li data-type='method' style='display: none;'><a href="BIP341.html#.shaScriptPubkeys">shaScriptPubkeys</a></li><li data-type='method' style='display: none;'><a href="BIP341.html#.shaSequences">shaSequences</a></li></ul></li><li><a href="BIP49.html">BIP49</a><ul class='methods'><li data-type='method' style='display: none;'><a href="BIP49.html#.createRedeemScript">createRedeemScript</a></li><li data-type='method' style='display: none;'><a href="BIP49.html#.createScriptPubKey">createScriptPubKey</a></li><li data-type='method' style='display: none;'><a href="BIP49.html#.getAccountPath">getAccountPath</a></li><li data-type='method' style='display: none;'><a href="BIP49.html#.getDerivationPath">getDerivationPath</a></li><li data-type='method' style='display: none;'><a href="BIP49.html#.toAddress">toAddress</a></li></ul></li><li><a href="CustodialWallet.html">CustodialWallet</a><ul class='methods'><li data-type='method' style='display: none;'><a href="CustodialWallet.html#canSign">canSign</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#clearCache">clearCache</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#createTransaction">createTransaction</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#deriveAddress">deriveAddress</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#destroy">destroy</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#exportWIF">exportWIF</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#getAddresses">getAddresses</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#getChangeAddress">getChangeAddress</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#getExtendedPrivateKey">getExtendedPrivateKey</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#getExtendedPublicKey">getExtendedPublicKey</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#getMnemonic">getMnemonic</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#getNetwork">getNetwork</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#getReceivingAddress">getReceivingAddress</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#signMessage">signMessage</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#signMessageBIP322">signMessageBIP322</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#signTransaction">signTransaction</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#toJSON">toJSON</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#verifyMessage">verifyMessage</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#.createNew">createNew</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#.fromExtendedKey">fromExtendedKey</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#.fromMnemonic">fromMnemonic</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#.fromSeed">fromSeed</a></li><li data-type='method' style='display: none;'><a href="CustodialWallet.html#.fromWIF">fromWIF</a></li></ul></li><li></li><li><a href="CustodialWalletError.html">CustodialWalletError</a></li><li></li><li><a href="DecodingError.html">DecodingError</a></li><li><a href="ECDSAError.html">ECDSAError</a></li><li></li><li><a href="EncodingError.html">EncodingError</a></li><li><a href="JVRSS.html">JVRSS</a><ul class='methods'><li data-type='method' style='display: none;'><a href="JVRSS.html#broadcastObfuscatedCoefficients">broadcastObfuscatedCoefficients</a></li><li data-type='method' style='display: none;'><a href="JVRSS.html#calculateSharedPublicKey">calculateSharedPublicKey</a></li><li data-type='method' style='display: none;'><a href="JVRSS.html#calculateShares">calculateShares</a></li><li data-type='method' style='display: none;'><a href="JVRSS.html#clear">clear</a></li><li data-type='method' style='display: none;'><a href="JVRSS.html#distributePolynomialPoints">distributePolynomialPoints</a></li><li data-type='method' style='display: none;'><a href="JVRSS.html#generatePolynomials">generatePolynomials</a></li><li data-type='method' style='display: none;'><a href="JVRSS.html#getParticipant">getParticipant</a></li><li data-type='method' style='display: none;'><a href="JVRSS.html#getSharesForInterpolation">getSharesForInterpolation</a></li><li data-type='method' style='display: none;'><a href="JVRSS.html#reconstructSecret">reconstructSecret</a></li><li data-type='method' style='display: none;'><a href="JVRSS.html#runProtocol">runProtocol</a></li><li data-type='method' style='display: none;'><a href="JVRSS.html#verifyAllShares">verifyAllShares</a></li></ul></li><li><a href="JVRSSError.html">JVRSSError</a></li><li><a href="LegacySighash.html">LegacySighash</a><ul class='methods'><li data-type='method' style='display: none;'><a href="LegacySighash.html#.calculate">calculate</a></li></ul></li><li><a href="MPCError.html">MPCError</a></li><li><a href="NonCustodialWallet.html">NonCustodialWallet</a><ul class='methods'><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#_exportShares">_exportShares</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#_reconstructPublicKey">_reconstructPublicKey</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#canSign">canSign</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#canSignHD">canSignHD</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#clear">clear</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#clearAddressCache">clearAddressCache</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#createTransaction">createTransaction</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#deriveAddress">deriveAddress</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#destroy">destroy</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#exportShares">exportShares</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#exportWIF">exportWIF</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#generateEphemeralKeys">generateEphemeralKeys</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#getAddress">getAddress</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#getAddressCount">getAddressCount</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#getAddresses">getAddresses</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#getChangeAddress">getChangeAddress</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#getExtendedPrivateKey">getExtendedPrivateKey</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#getExtendedPublicKey">getExtendedPublicKey</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#getMnemonic">getMnemonic</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#getNetwork">getNetwork</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#getPublicKey">getPublicKey</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#getReceivingAddress">getReceivingAddress</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#getShare">getShare</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#getShares">getShares</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#getThresholdConfig">getThresholdConfig</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#hasHD">hasHD</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#initialize">initialize</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#listAddresses">listAddresses</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#sign">sign</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#signMessage">signMessage</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#signMessageBIP322">signMessageBIP322</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#signMessageHD">signMessageHD</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#signTransaction">signTransaction</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#toJSON">toJSON</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#verify">verify</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#verifyMessageHD">verifyMessageHD</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#.createNew">createNew</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#.createNewHD">createNewHD</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#.fromExtendedKey">fromExtendedKey</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#.fromMnemonic">fromMnemonic</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#.fromSeed">fromSeed</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#.fromShares">fromShares</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#.fromWIF">fromWIF</a></li><li data-type='method' style='display: none;'><a href="NonCustodialWallet.html#.importShares">importShares</a></li></ul></li><li><a href="Participant.html">Participant</a><ul class='methods'><li data-type='method' style='display: none;'><a href="Participant.html#calculateKeyShare">calculateKeyShare</a></li><li data-type='method' style='display: none;'><a href="Participant.html#clear">clear</a></li><li data-type='method' style='display: none;'><a href="Participant.html#evaluateAt">evaluateAt</a></li><li data-type='method' style='display: none;'><a href="Participant.html#generatePolynomial">generatePolynomial</a></li><li data-type='method' style='display: none;'><a href="Participant.html#generateSignatureShare">generateSignatureShare</a></li><li data-type='method' style='display: none;'><a href="Participant.html#getBlindingShare">getBlindingShare</a></li><li data-type='method' style='display: none;'><a href="Participant.html#getKeyShare">getKeyShare</a></li><li data-type='method' style='display: none;'><a href="Participant.html#getKeySharePublicKey">getKeySharePublicKey</a></li><li data-type='method' style='display: none;'><a href="Participant.html#getNextEphemeralKey">getNextEphemeralKey</a></li><li data-type='method' style='display: none;'><a href="Participant.html#getObfuscatedCoefficients">getObfuscatedCoefficients</a></li><li data-type='method' style='display: none;'><a href="Participant.html#getPolynomialPointFor">getPolynomialPointFor</a></li><li data-type='method' style='display: none;'><a href="Participant.html#receivePolynomialPoint">receivePolynomialPoint</a></li><li data-type='method' style='display: none;'><a href="Participant.html#setBlindingShare">setBlindingShare</a></li><li data-type='method' style='display: none;'><a href="Participant.html#storeEphemeralKey">storeEphemeralKey</a></li><li data-type='method' style='display: none;'><a href="Participant.html#verifyPolynomialPoint">verifyPolynomialPoint</a></li></ul></li><li><a href="ParticipantError.html">ParticipantError</a></li><li><a href="ParticipantShare.html">ParticipantShare</a></li><li><a href="Polynomial.html">Polynomial</a><ul class='methods'><li data-type='method' style='display: none;'><a href="Polynomial.html#clear">clear</a></li><li data-type='method' style='display: none;'><a href="Polynomial.html#evaluate">evaluate</a></li><li data-type='method' style='display: none;'><a href="Polynomial.html#generateShares">generateShares</a></li><li data-type='method' style='display: none;'><a href="Polynomial.html#getCoefficients">getCoefficients</a></li><li data-type='method' style='display: none;'><a href="Polynomial.html#getSecret">getSecret</a></li><li data-type='method' style='display: none;'><a href="Polynomial.html#.interpolate">interpolate</a></li><li data-type='method' style='display: none;'><a href="Polynomial.html#.lagrangeCoefficient">lagrangeCoefficient</a></li><li data-type='method' style='display: none;'><a href="Polynomial.html#.reconstructSecret">reconstructSecret</a></li></ul></li><li><a href="PolynomialError.html">PolynomialError</a></li><li><a href="Schnorr.html">Schnorr</a><ul class='methods'><li data-type='method' style='display: none;'><a href="Schnorr.html#sign">sign</a></li></ul></li><li><a href="SchnorrError.html">SchnorrError</a></li><li></li><li><a href="ScriptBuilder.html">ScriptBuilder</a><ul class='methods'><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#addOp">addOp</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#build">build</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#pushData">pushData</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#pushNumber">pushNumber</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#reset">reset</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.createCLTV">createCLTV</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.createCSV">createCSV</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.createMultisig">createMultisig</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.createOpReturn">createOpReturn</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.createP2PKH">createP2PKH</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.createP2PKHFromPubkey">createP2PKHFromPubkey</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.createP2PKHScriptSig">createP2PKHScriptSig</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.createP2SH">createP2SH</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.createP2SHScriptSig">createP2SHScriptSig</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.createP2TR">createP2TR</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.createP2WPKH">createP2WPKH</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.createP2WPKHFromPubkey">createP2WPKHFromPubkey</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.createP2WSH">createP2WSH</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.detectType">detectType</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.disassemble">disassemble</a></li><li data-type='method' style='display: none;'><a href="ScriptBuilder.html#.parse">parse</a></li></ul></li><li><a href="ScriptError.html">ScriptError</a></li><li><a href="SighashCalculator.html">SighashCalculator</a><ul class='methods'><li data-type='method' style='display: none;'><a href="SighashCalculator.html#.calculate">calculate</a></li></ul></li><li><a href="SighashError.html">SighashError</a></li><li><a href="TaggedHash.html">TaggedHash</a><ul class='methods'><li data-type='method' style='display: none;'><a href="TaggedHash.html#.create">create</a></li></ul></li><li><a href="ThresholdSignatureError.html">ThresholdSignatureError</a></li><li><a href="ThresholdSignatureScheme.html">ThresholdSignatureScheme</a><ul class='methods'><li data-type='method' style='display: none;'><a href="ThresholdSignatureScheme.html#clear">clear</a></li><li data-type='method' style='display: none;'><a href="ThresholdSignatureScheme.html#generateEphemeralKeys">generateEphemeralKeys</a></li><li data-type='method' style='display: none;'><a href="ThresholdSignatureScheme.html#generateSharedPrivateKey">generateSharedPrivateKey</a></li><li data-type='method' style='display: none;'><a href="ThresholdSignatureScheme.html#getConfig">getConfig</a></li><li data-type='method' style='display: none;'><a href="ThresholdSignatureScheme.html#getNextEphemeralKey">getNextEphemeralKey</a></li><li data-type='method' style='display: none;'><a href="ThresholdSignatureScheme.html#getPublicKey">getPublicKey</a></li><li data-type='method' style='display: none;'><a href="ThresholdSignatureScheme.html#sign">sign</a></li><li data-type='method' style='display: none;'><a href="ThresholdSignatureScheme.html#signMessage">signMessage</a></li><li data-type='method' style='display: none;'><a href="ThresholdSignatureScheme.html#verify">verify</a></li></ul></li><li><a href="TransactionBuilder.html">TransactionBuilder</a><ul class='methods'><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#addInput">addInput</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#addOpReturn">addOpReturn</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#addOutput">addOutput</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#addWitness">addWitness</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#build">build</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#calculateFee">calculateFee</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#clone">clone</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#enableRBF">enableRBF</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#getTxid">getTxid</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#getVirtualSize">getVirtualSize</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#getWeight">getWeight</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#getWtxid">getWtxid</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#isFullySigned">isFullySigned</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#reset">reset</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#serialize">serialize</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#setInputSequence">setInputSequence</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#setLocktime">setLocktime</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#setVersion">setVersion</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#signAllInputs">signAllInputs</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#signInput">signInput</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#signInputs">signInputs</a></li><li data-type='method' style='display: none;'><a href="TransactionBuilder.html#toHex">toHex</a></li></ul></li><li></li><li><a href="TransactionBuilderError.html">TransactionBuilderError</a></li><li><a href="TransactionParseError.html">TransactionParseError</a></li><li><a href="TransactionParser.html">TransactionParser</a><ul class='methods'><li data-type='method' style='display: none;'><a href="TransactionParser.html#.fromBuffer">fromBuffer</a></li><li data-type='method' style='display: none;'><a href="TransactionParser.html#.fromHex">fromHex</a></li><li data-type='method' style='display: none;'><a href="TransactionParser.html#.getTxid">getTxid</a></li><li data-type='method' style='display: none;'><a href="TransactionParser.html#.serializeWithoutWitness">serializeWithoutWitness</a></li></ul></li><li><a href="ValidationError.html">ValidationError</a></li><li><a href="WitnessBuilder.html">WitnessBuilder</a><ul class='methods'><li data-type='method' style='display: none;'><a href="WitnessBuilder.html#.buildControlBlock">buildControlBlock</a></li><li data-type='method' style='display: none;'><a href="WitnessBuilder.html#.buildP2TRKeyPath">buildP2TRKeyPath</a></li><li data-type='method' style='display: none;'><a href="WitnessBuilder.html#.buildP2TRScriptPath">buildP2TRScriptPath</a></li><li data-type='method' style='display: none;'><a href="WitnessBuilder.html#.buildP2WPKH">buildP2WPKH</a></li><li data-type='method' style='display: none;'><a href="WitnessBuilder.html#.buildP2WSH">buildP2WSH</a></li><li data-type='method' style='display: none;'><a href="WitnessBuilder.html#.buildP2WSHMultisig">buildP2WSHMultisig</a></li><li data-type='method' style='display: none;'><a href="WitnessBuilder.html#.calculateTapbranchHash">calculateTapbranchHash</a></li><li data-type='method' style='display: none;'><a href="WitnessBuilder.html#.calculateTapleafHash">calculateTapleafHash</a></li><li data-type='method' style='display: none;'><a href="WitnessBuilder.html#.calculateTaptweak">calculateTaptweak</a></li><li data-type='method' style='display: none;'><a href="WitnessBuilder.html#.parse">parse</a></li><li data-type='method' style='display: none;'><a href="WitnessBuilder.html#.serialize">serialize</a></li><li data-type='method' style='display: none;'><a href="WitnessBuilder.html#.validate">validate</a></li></ul></li><li><a href="WitnessError.html">WitnessError</a></li></ul><h3>Namespaces</h3><ul><li><a href="BECH32.html">BECH32</a><ul class='methods'><li data-type='method' style='display: none;'><a href="BECH32.html#.decode">decode</a></li><li data-type='method' style='display: none;'><a href="BECH32.html#.getAddressType">getAddressType</a></li><li data-type='method' style='display: none;'><a href="BECH32.html#.getPrefix">getPrefix</a></li><li data-type='method' style='display: none;'><a href="BECH32.html#.to_P2TR">to_P2TR</a></li><li data-type='method' style='display: none;'><a href="BECH32.html#.to_P2WPKH">to_P2WPKH</a></li><li data-type='method' style='display: none;'><a href="BECH32.html#.to_P2WSH">to_P2WSH</a></li><li data-type='method' style='display: none;'><a href="BECH32.html#.validate">validate</a></li></ul></li><li><a href="BIP39.html">BIP39</a><ul class='methods'><li data-type='method' style='display: none;'><a href="BIP39.html#.deriveSeed">deriveSeed</a></li><li data-type='method' style='display: none;'><a href="BIP39.html#.generateMnemonic">generateMnemonic</a></li><li data-type='method' style='display: none;'><a href="BIP39.html#.getWordList">getWordList</a></li><li data-type='method' style='display: none;'><a href="BIP39.html#.mnemonicToEntropy">mnemonicToEntropy</a></li><li data-type='method' style='display: none;'><a href="BIP39.html#.validateChecksum">validateChecksum</a></li><li data-type='method' style='display: none;'><a href="BIP39.html#.validateMnemonic">validateMnemonic</a></li></ul></li><li><a href="ECDSA.html">ECDSA</a><ul class='methods'><li data-type='method' style='display: none;'><a href="ECDSA.html#.getPublicKey">getPublicKey</a></li><li data-type='method' style='display: none;'><a href="ECDSA.html#.recoverPublicKey">recoverPublicKey</a></li><li data-type='method' style='display: none;'><a href="ECDSA.html#.sign">sign</a></li><li data-type='method' style='display: none;'><a href="ECDSA.html#.signMessage">signMessage</a></li><li data-type='method' style='display: none;'><a href="ECDSA.html#.verify">verify</a></li><li data-type='method' style='display: none;'><a href="ECDSA.html#.verifyMessage">verifyMessage</a></li></ul></li></ul><h3>Global</h3><ul><li><a href="global.html#ADDRESS_FORMATS">ADDRESS_FORMATS</a></li><li><a href="global.html#ADDRESS_TYPE_PURPOSE">ADDRESS_TYPE_PURPOSE</a></li><li><a href="global.html#ADDSS">ADDSS</a></li><li><a href="global.html#BECH32_PREFIXES">BECH32_PREFIXES</a></li><li><a href="global.html#BIP322_CONSTANTS">BIP322_CONSTANTS</a></li><li><a href="global.html#BIP32_CONSTANTS">BIP32_CONSTANTS</a></li><li><a href="global.html#BIP340_CONSTANTS">BIP340_CONSTANTS</a></li><li><a href="global.html#BIP39_CONSTANTS">BIP39_CONSTANTS</a></li><li><a href="global.html#BIP44_CONSTANTS">BIP44_CONSTANTS</a></li><li><a href="global.html#BIP49_CONSTANTS">BIP49_CONSTANTS</a></li><li><a href="global.html#BIP_COMPLIANCE">BIP_COMPLIANCE</a></li><li><a href="global.html#BIP_PURPOSES">BIP_PURPOSES</a></li><li><a href="global.html#CRYPTO_CONSTANTS">CRYPTO_CONSTANTS</a></li><li><a href="global.html#CURVE_ORDER">CURVE_ORDER</a></li><li><a href="global.html#ENCODING_CONSTANTS">ENCODING_CONSTANTS</a></li><li><a href="global.html#FEATURES">FEATURES</a></li><li><a href="global.html#G">G</a></li><li><a href="global.html#HARDENED_OFFSET">HARDENED_OFFSET</a></li><li><a href="global.html#INVSS">INVSS</a></li><li><a href="global.html#LIBRARY_INFO">LIBRARY_INFO</a></li><li><a href="global.html#NETWORKS">NETWORKS</a></li><li><a href="global.html#NETWORK_VERSIONS">NETWORK_VERSIONS</a></li><li><a href="global.html#OPCODES">OPCODES</a></li><li><a href="global.html#PROSS">PROSS</a></li><li><a href="global.html#SECURITY_CONSTANTS">SECURITY_CONSTANTS</a></li><li><a href="global.html#SIGHASH">SIGHASH</a></li><li><a href="global.html#TAPROOT_CONSTANTS">TAPROOT_CONSTANTS</a></li><li><a href="global.html#THRESHOLD_CONSTANTS">THRESHOLD_CONSTANTS</a></li><li><a href="global.html#TRANSACTION_CONSTANTS">TRANSACTION_CONSTANTS</a></li><li><a href="global.html#TX_CONSTANTS">TX_CONSTANTS</a></li><li><a href="global.html#b58decode">b58decode</a></li><li><a href="global.html#b58encode">b58encode</a></li><li><a href="global.html#computeAdditiveShares">computeAdditiveShares</a></li><li><a href="global.html#computeMultiplicativeShares">computeMultiplicativeShares</a></li><li><a href="global.html#convertBits">convertBits</a></li><li><a href="global.html#createP2WPKHScriptCode">createP2WPKHScriptCode</a></li><li><a href="global.html#createThresholdScheme">createThresholdScheme</a></li><li><a href="global.html#decode">decode</a></li><li><a href="global.html#decodeAddress">decodeAddress</a></li><li><a href="global.html#decodeExtendedKey">decodeExtendedKey</a></li><li><a href="global.html#decodeLegacyAddress">decodeLegacyAddress</a></li><li><a href="global.html#decodeSegwit">decodeSegwit</a></li><li><a href="global.html#decodeSegwitAddress">decodeSegwitAddress</a></li><li><a href="global.html#decodeWIFPrivateKey">decodeWIFPrivateKey</a></li><li><a href="global.html#derive">derive</a></li><li><a href="global.html#deriveChildKey">deriveChildKey</a></li><li><a href="global.html#doubleHash256">doubleHash256</a></li><li><a href="global.html#encode">encode</a></li><li><a href="global.html#encodeAddress">encodeAddress</a></li><li><a href="global.html#encodeExtendedKey">encodeExtendedKey</a></li><li><a href="global.html#encodeP2PKH">encodeP2PKH</a></li><li><a href="global.html#encodeP2SH">encodeP2SH</a></li><li><a href="global.html#encodePush">encodePush</a></li><li><a href="global.html#encodeSegwit">encodeSegwit</a></li><li><a href="global.html#encodeVarInt">encodeVarInt</a></li><li><a href="global.html#encodeWIF">encodeWIF</a></li><li><a href="global.html#generateDerivationPath">generateDerivationPath</a></li><li><a href="global.html#generateEphemeralKeyShares">generateEphemeralKeyShares</a></li><li><a href="global.html#generateMasterKey">generateMasterKey</a></li><li><a href="global.html#generateSecureRandom">generateSecureRandom</a></li><li><a href="global.html#getFingerprint">getFingerprint</a></li><li><a href="global.html#hash160">hash160</a></li><li><a href="global.html#hash256">hash256</a></li><li><a href="global.html#normalizeUnicode">normalizeUnicode</a></li><li><a href="global.html#polymod">polymod</a></li><li><a href="global.html#rmd160">rmd160</a></li><li><a href="global.html#rotl">rotl</a></li><li><a href="global.html#runJVRSS">runJVRSS</a></li><li><a href="global.html#secureClear">secureClear</a></li><li><a href="global.html#sha256">sha256</a></li><li><a href="global.html#taggedHash">taggedHash</a></li><li><a href="global.html#validateAddress">validateAddress</a></li><li><a href="global.html#validateAndGetNetwork">validateAndGetNetwork</a></li><li><a href="global.html#validateBuffer">validateBuffer</a></li><li><a href="global.html#validateBufferLength">validateBufferLength</a></li><li><a href="global.html#validateChildKey">validateChildKey</a></li><li><a href="global.html#validateDerivationPath">validateDerivationPath</a></li><li><a href="global.html#validateEntropyQuality">validateEntropyQuality</a></li><li><a href="global.html#validateExtendedKey">validateExtendedKey</a></li><li><a href="global.html#validateHexString">validateHexString</a></li><li><a href="global.html#validateNumberRange">validateNumberRange</a></li><li><a href="global.html#validatePrivateKey">validatePrivateKey</a></li><li><a href="global.html#validatePublicKey">validatePublicKey</a></li><li><a href="global.html#validateSeed">validateSeed</a></li></ul> </nav> <div id="main"> <h1 class="page-title">src/transaction/message-signing.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/** * @fileoverview BIP322 Generic Message Signing * @description Implements BIP322 message signing for all address types * @version 1.0.0 * @author yfbsei * @license ISC */ import { createHash } from 'node:crypto'; import { ECDSA } from '../core/crypto/signatures/ecdsa.js'; import { Schnorr } from '../core/crypto/signatures/schnorr-BIP340.js'; import { ScriptBuilder } from './script-builder.js'; import { WitnessBuilder } from './witness-builder.js'; import { BIP143 } from './sighash.js'; /** * BIP322 message signing constants * @constant {Object} */ const BIP322_CONSTANTS = { // Message tag for BIP322 MESSAGE_TAG: 'BIP0322-signed-message', // Virtual transaction version TX_VERSION: 0, // Sequence for signing SEQUENCE: 0, // Empty prevout EMPTY_TXID: Buffer.alloc(32, 0), // OP_RETURN script for to_spend TO_SPEND_SCRIPT: Buffer.from([0x6a, 0x24, 0x62, 0x69, 0x70, 0x30, 0x33, 0x32, 0x32]) }; /** * Custom error for BIP322 operations * @class BIP322Error * @extends Error */ class BIP322Error extends Error { constructor(message, code, details = {}) { super(message); this.name = 'BIP322Error'; this.code = code; this.details = details; } } /** * Tagged hash for BIP322 * @param {string} tag - Hash tag * @param {Buffer} data - Data to hash * @returns {Buffer} 32-byte tagged hash */ function taggedHash(tag, data) { const tagHash = createHash('sha256').update(tag).digest(); return createHash('sha256').update(Buffer.concat([tagHash, tagHash, data])).digest(); } /** * BIP322 Message Signing * @class BIP322 */ class BIP322 { /** * Create message hash for signing * @param {string|Buffer} message - Message to sign * @returns {Buffer} 32-byte message hash */ static hashMessage(message) { const msgBuf = Buffer.isBuffer(message) ? message : Buffer.from(message, 'utf8'); return taggedHash(BIP322_CONSTANTS.MESSAGE_TAG, msgBuf); } /** * Create "to_spend" virtual transaction * @param {Buffer} scriptPubKey - Script of the signing address * @param {Buffer} messageHash - Hashed message * @returns {Object} Virtual transaction */ static createToSpend(scriptPubKey, messageHash) { // OP_0 PUSH32 &lt;message_hash> const scriptSig = Buffer.concat([ Buffer.from([0x00, 0x20]), messageHash ]); return { version: 0, inputs: [{ txid: BIP322_CONSTANTS.EMPTY_TXID.toString('hex'), vout: 0xffffffff, scriptSig: scriptSig, sequence: 0 }], outputs: [{ value: 0, scriptPubKey: scriptPubKey }], locktime: 0 }; } /** * Create "to_sign" virtual transaction * @param {Buffer} toSpendTxid - Txid of to_spend transaction * @param {Buffer} scriptPubKey - Script of signing address * @returns {Object} Virtual transaction to sign */ static createToSign(toSpendTxid, scriptPubKey) { return { version: 0, inputs: [{ txid: toSpendTxid, vout: 0, scriptSig: Buffer.alloc(0), sequence: 0 }], outputs: [{ value: 0, scriptPubKey: Buffer.from([0x6a]) // OP_RETURN }], locktime: 0 }; } /** * Sign a message using BIP322 (simple format) * @param {string|Buffer} message - Message to sign * @param {Buffer|string} privateKey - Private key * @param {string} addressType - Address type (p2wpkh, p2tr) * @returns {Promise&lt;Buffer>} BIP322 signature (witness serialized) */ static async sign(message, privateKey, addressType = 'p2wpkh') { const keyBuffer = Buffer.isBuffer(privateKey) ? privateKey : Buffer.from(privateKey, 'hex'); const messageHash = this.hashMessage(message); const publicKey = ECDSA.getPublicKey(keyBuffer, true); // Create scriptPubKey based on address type let scriptPubKey; if (addressType === 'p2wpkh') { const hash160Fn = (await import('../utils/address-helpers.js')).hash160; const pubkeyHash = hash160Fn(publicKey); scriptPubKey = ScriptBuilder.createP2WPKH(pubkeyHash); } else if (addressType === 'p2tr') { // For Taproot, use x-only pubkey const xOnlyPubkey = publicKey.slice(1); // Remove prefix byte scriptPubKey = ScriptBuilder.createP2TR(xOnlyPubkey); } else { throw new BIP322Error(`Unsupported address type: ${addressType}`, 'UNSUPPORTED_TYPE'); } // Create to_spend transaction const toSpend = this.createToSpend(scriptPubKey, messageHash); // Calculate to_spend txid const toSpendTxid = this._getTxid(toSpend); // Create to_sign transaction const toSign = this.createToSign(toSpendTxid, scriptPubKey); // Sign based on address type let witness; if (addressType === 'p2wpkh') { const hash160Fn = (await import('../utils/address-helpers.js')).hash160; const pubkeyHash = hash160Fn(publicKey); const sighash = BIP143.forP2WPKH(toSign, 0, pubkeyHash, 0, 0x01); const sigResult = ECDSA.sign(keyBuffer, sighash); const signature = Buffer.concat([sigResult.der, Buffer.from([0x01])]); witness = WitnessBuilder.buildP2WPKH(signature, publicKey); } else if (addressType === 'p2tr') { const schnorr = new Schnorr(); // For Taproot, we need proper BIP341 sighash, simplified here const sigResult = await schnorr.sign(keyBuffer, messageHash); witness = [sigResult.signature]; } // Serialize witness return WitnessBuilder.serialize(witness); } /** * Verify a BIP322 signature * @param {string|Buffer} message - Original message * @param {Buffer} signature - BIP322 signature (serialized witness) * @param {Buffer} scriptPubKey - Address scriptPubKey * @returns {Promise&lt;boolean>} True if valid */ static async verify(message, signature, scriptPubKey) { try { const messageHash = this.hashMessage(message); const witness = WitnessBuilder.parse(signature); if (witness.length &lt; 1) { return false; } // Detect address type from scriptPubKey const scriptType = ScriptBuilder.detectType(scriptPubKey); if (scriptType.type === 'p2wpkh') { if (witness.length !== 2) return false; const sig = witness[0]; const publicKey = witness[1]; // Verify pubkey matches scriptPubKey const hash160Fn = (await import('../utils/address-helpers.js')).hash160; const pubkeyHash = hash160Fn(publicKey); if (!pubkeyHash.equals(scriptType.program)) { return false; } // Recreate and verify sighash const toSpend = this.createToSpend(scriptPubKey, messageHash); const toSpendTxid = this._getTxid(toSpend); const toSign = this.createToSign(toSpendTxid, scriptPubKey); const sigWithoutType = sig.slice(0, -1); const sighash = BIP143.forP2WPKH(toSign, 0, pubkeyHash, 0, 0x01); // Parse DER signature const { r, s } = this._parseDER(sigWithoutType); return ECDSA.verify({ r, s }, sighash, publicKey); } else if (scriptType.type === 'p2tr') { if (witness.length !== 1) return false; const schnorrSig = witness[0]; const xOnlyPubkey = scriptType.program; const schnorr = new Schnorr(); return await schnorr.verify(schnorrSig, messageHash, xOnlyPubkey); } return false; } catch { return false; } } /** * Calculate txid for virtual transaction * @private */ static _getTxid(tx) { const parts = []; // Version const version = Buffer.alloc(4); version.writeInt32LE(tx.version, 0); parts.push(version); // Input count parts.push(Buffer.from([tx.inputs.length])); // Inputs for (const input of tx.inputs) { const txid = typeof input.txid === 'string' ? Buffer.from(input.txid, 'hex').reverse() : input.txid; parts.push(txid); const vout = Buffer.alloc(4); vout.writeUInt32LE(input.vout, 0); parts.push(vout); const scriptSig = Buffer.isBuffer(input.scriptSig) ? input.scriptSig : Buffer.alloc(0); parts.push(Buffer.from([scriptSig.length])); parts.push(scriptSig); const seq = Buffer.alloc(4); seq.writeUInt32LE(input.sequence, 0); parts.push(seq); } // Output count parts.push(Buffer.from([tx.outputs.length])); // Outputs for (const output of tx.outputs) { const value = Buffer.alloc(8); value.writeBigUInt64LE(BigInt(output.value), 0); parts.push(value); const script = output.scriptPubKey; parts.push(Buffer.from([script.length])); parts.push(script); } // Locktime const locktime = Buffer.alloc(4); locktime.writeUInt32LE(tx.locktime, 0); parts.push(locktime); const serialized = Buffer.concat(parts); const hash = createHash('sha256') .update(createHash('sha256').update(serialized).digest()) .digest(); return hash.reverse().toString('hex'); } /** * Parse DER signature * @private */ static _parseDER(sig) { let offset = 0; if (sig[offset++] !== 0x30) throw new Error('Invalid DER'); const totalLen = sig[offset++]; if (sig[offset++] !== 0x02) throw new Error('Invalid DER'); const rLen = sig[offset++]; let r = sig.slice(offset, offset + rLen); offset += rLen; if (sig[offset++] !== 0x02) throw new Error('Invalid DER'); const sLen = sig[offset++]; let s = sig.slice(offset, offset + sLen); // Remove leading zeros while (r.length > 1 &amp;&amp; r[0] === 0) r = r.slice(1); while (s.length > 1 &amp;&amp; s[0] === 0) s = s.slice(1); return { r: BigInt('0x' + r.toString('hex')), s: BigInt('0x' + s.toString('hex')) }; } /** * Legacy Bitcoin message signing (for compatibility) * @param {string|Buffer} message - Message to sign * @param {Buffer|string} privateKey - Private key * @returns {Object} Signature {signature, recovery} */ static signLegacy(message, privateKey) { const keyBuffer = Buffer.isBuffer(privateKey) ? privateKey : Buffer.from(privateKey, 'hex'); // Bitcoin message prefix const prefix = '\x18Bitcoin Signed Message:\n'; const msgBuf = Buffer.isBuffer(message) ? message : Buffer.from(message, 'utf8'); const prefixBuf = Buffer.from(prefix, 'utf8'); const fullMsg = Buffer.concat([ Buffer.from([prefixBuf.length]), prefixBuf, Buffer.from([msgBuf.length]), msgBuf ]); const hash = createHash('sha256') .update(createHash('sha256').update(fullMsg).digest()) .digest(); const sigResult = ECDSA.sign(keyBuffer, hash); return { signature: sigResult.signature, recovery: sigResult.recovery, messageHash: hash }; } /** * Verify legacy Bitcoin message signature * @param {string|Buffer} message - Original message * @param {Object} signature - Signature object * @param {Buffer|string} publicKey - Public key * @returns {boolean} True if valid */ static verifyLegacy(message, signature, publicKey) { const prefix = '\x18Bitcoin Signed Message:\n'; const msgBuf = Buffer.isBuffer(message) ? message : Buffer.from(message, 'utf8'); const prefixBuf = Buffer.from(prefix, 'utf8'); const fullMsg = Buffer.concat([ Buffer.from([prefixBuf.length]), prefixBuf, Buffer.from([msgBuf.length]), msgBuf ]); const hash = createHash('sha256') .update(createHash('sha256').update(fullMsg).digest()) .digest(); return ECDSA.verify(signature, hash, publicKey); } } export { BIP322, BIP322Error, BIP322_CONSTANTS }; export default BIP322; </code></pre> </article> </section> </div> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Dec 31 2025 22:27:40 GMT-0500 (Eastern Standard Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme. </footer> <script>prettyPrint();</script> <script src="scripts/polyfill.js"></script> <script src="scripts/linenumber.js"></script> <script src="scripts/search.js" defer></script> <script src="scripts/collapse.js" defer></script> </body> </html>