mirror of
https://github.com/bitcoin/bips.git
synced 2026-05-18 16:59:30 +00:00
Merge pull request #2155 from guggero/bip-0322-follow-up
BIP-0322: polishing follow-up
This commit is contained in:
@@ -1076,7 +1076,7 @@ users (see also: [https://en.bitcoin.it/wiki/Economic_majority economic majority
|
||||
| [[bip-0322.mediawiki|322]]
|
||||
| Applications
|
||||
| Generic Signed Message Format
|
||||
| Karl-Johan Alm
|
||||
| Karl-Johan Alm, Oliver Gugger
|
||||
| Specification
|
||||
| Complete
|
||||
|-
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Layer: Applications
|
||||
Title: Generic Signed Message Format
|
||||
Authors: Karl-Johan Alm <karljohan-alm@garage.co.jp>
|
||||
Deputies: guggero <gugger@gmail.com>
|
||||
Oliver Gugger <gugger@gmail.com>
|
||||
Status: Complete
|
||||
Type: Specification
|
||||
Assigned: 2018-09-10
|
||||
@@ -16,35 +16,29 @@
|
||||
2025-05-10: https://bitcoin.stackexchange.com/questions/126277/where-can-i-use-bip322-to-sign-a-message-to-verify-a-multisig-address
|
||||
2026-04-20: https://groups.google.com/g/bitcoindev/c/qd6BNz9gxCk/m/k1fHq4RKAQAJ
|
||||
Version: 1.0.0
|
||||
Requires: 174, 340, 341
|
||||
</pre>
|
||||
|
||||
== Abstract ==
|
||||
|
||||
A standard for interoperable signed messages based on the Bitcoin Script format, either for proving
|
||||
fund availability, or committing to a message as the intended recipient of funds sent to the invoice
|
||||
address.
|
||||
availability of funds, or for committing to a message as the intended recipient of funds sent to the
|
||||
invoice address.
|
||||
|
||||
== Motivation ==
|
||||
|
||||
The current message signing standard only works for P2PKH (1...) invoice addresses. We propose to
|
||||
extend and generalize the standard by using a Bitcoin Script based approach. This ensures that any
|
||||
coins, no matter what script they are controlled by, can in-principle be signed for. For easy
|
||||
interoperability with existing signing hardware, we also define a signature message format which
|
||||
extend and generalize the standard by using an approach based on Bitcoin Script. This ensures that
|
||||
any coins, no matter what script they are controlled by, can in principle be signed for. For easy
|
||||
interoperability with existing signing hardware, we also define a signature message format that
|
||||
resembles a Bitcoin transaction (except that it contains an invalid input, so it cannot be spent on
|
||||
any real network).
|
||||
|
||||
The Proof of Funds variant allows demonstrating control of a set of UTXOs.
|
||||
The list of UTXOs may or may not be related to the address being signed with (the
|
||||
<code>message_challenge</code>).
|
||||
But in any case, the UTXO list does not aim to prove completeness (e.g. it does NOT mean:
|
||||
"these are all UTXOs that exist for an address") nor that they are unspent (e.g. a
|
||||
validator must consult the blockchain to verify that).
|
||||
|
||||
Additionally, the current message signature format uses ECDSA signatures which do not commit to the
|
||||
Additionally, the current message signature format uses ECDSA signatures that do not commit to the
|
||||
public key, meaning that they do not actually prove knowledge of any secret keys. (Indeed, valid
|
||||
signatures can be tweaked by 3rd parties to become valid signatures on certain related keys.)
|
||||
signatures can be tweaked by third parties to become valid signatures on certain related keys.)
|
||||
|
||||
Ultimately no message signing protocol can actually prove control of funds, both because a signature
|
||||
Ultimately, no message signing protocol can actually prove control of funds, both because a signature
|
||||
is obsolete as soon as it is created, and because the possessor of a secret key may be willing to
|
||||
sign messages on others' behalf even if it would not sign actual transactions. No message signing
|
||||
protocol can fix these limitations.
|
||||
@@ -56,7 +50,7 @@ using this BIP.
|
||||
== Terminology ==
|
||||
|
||||
In the context of this BIP, whenever the word "signature" or similar is used, it refers to the
|
||||
output of the signing process described below and, depending on the script type of the
|
||||
output of the signing process described below, and, depending on the script type of the
|
||||
<code>message_challenge</code>, is either a full transaction input witness stack, a full
|
||||
transaction, or a PSBT packet that can be validated against a Bitcoin Script Interpreter. Such a
|
||||
"signature" may or may not contain an actual cryptographic (ECDSA or Schnorr) signature, depending
|
||||
@@ -83,32 +77,32 @@ UTXOs.
|
||||
| Simple
|
||||
| <code>P2WPKH</code>, <code>P2WSH</code><sup>2</sup>, <code>P2TR</code><sup>2</sup> <br/>
|
||||
| <code>smp</code>
|
||||
| witness stack, consensus encoded and base64-encoded
|
||||
| witness stack, consensus-encoded and base64-encoded
|
||||
|-
|
||||
| Full
|
||||
| <code>all</code>
|
||||
| <code>ful</code>
|
||||
| full <code>to_sign</code> transaction, consensus and base64-encoded
|
||||
| full <code>to_sign</code> transaction, consensus-encoded and base64-encoded
|
||||
|-
|
||||
| Full (Proof of Funds)
|
||||
| <code>all</code>
|
||||
| <code>pof</code>
|
||||
| full finalized PSBT of the <code>to_sign</code> transaction, consensus and base64-encoded
|
||||
| full finalized PSBT of the <code>to_sign</code> transaction, consensus-encoded and base64-encoded
|
||||
|}
|
||||
|
||||
<sup>1</sup>: Possible on a technical level but should NOT be used anymore in the context of this
|
||||
BIP.<br/>
|
||||
<sup>1</sup>: Possible on a technical level but SHOULD NOT be used anymore in the context of this
|
||||
BIP, see section [[#legacy|Legacy]] below.<br/>
|
||||
<sup>2</sup>: Excluding time lock scripts.
|
||||
|
||||
Signers must prefix the signature with the variant that was used to create the signature.
|
||||
Signers MUST prefix the signature with the variant that was used to create the signature.
|
||||
To support backward compatibility with implementations of this BIP before it was finalized, a
|
||||
verifier might assume the ''simple'' variant in the absence of a prefix.
|
||||
|
||||
=== Legacy ===
|
||||
|
||||
New proofs should use the new format for all invoice address formats, including P2PKH.
|
||||
New proofs SHOULD use the new format for all invoice address formats, including P2PKH.
|
||||
|
||||
The legacy format MAY be used, but must be restricted to the legacy P2PKH invoice address format.
|
||||
The legacy format MAY be used, but MUST be restricted to the legacy P2PKH invoice address format.
|
||||
|
||||
=== Simple ===
|
||||
|
||||
@@ -134,7 +128,7 @@ and then proceed as they would for a full signature.
|
||||
|
||||
=== Full ===
|
||||
|
||||
Full signatures follow an analogous specification to the BIP-325 challenges and solutions used by
|
||||
Full signatures follow an analogous specification to the BIP325 challenges and solutions used by
|
||||
Signet.
|
||||
|
||||
Let there be two virtual transactions <code>to_spend</code> and <code>to_sign</code>.
|
||||
@@ -151,14 +145,14 @@ The <code>to_spend</code> transaction is:
|
||||
vout[0].nValue = 0
|
||||
vout[0].scriptPubKey = message_challenge
|
||||
|
||||
where <code>message_hash</code> is a BIP340-tagged hash of the message, i.e. sha256_tag(m), where
|
||||
tag = <code>BIP0322-signed-message</code> and <code>m</code> is the message as is without length
|
||||
prefix or null terminator, and <code>message_challenge</code> is the to be proven (public) key
|
||||
script.
|
||||
where <code>message_hash</code> is a BIP340-tagged hash of the message, i.e., sha256_tag(m), where
|
||||
tag = <code>BIP0322-signed-message</code> and <code>m</code> is the message as-is without length
|
||||
prefix or null terminator, and <code>message_challenge</code> is the (public) key script to be
|
||||
proven.
|
||||
|
||||
The <code>to_sign</code> transaction is:
|
||||
|
||||
nVersion = 0 or (FULL format only) as appropriate (e.g. 2, for time locks)
|
||||
nVersion = 0 or (FULL format only) as appropriate (e.g., 2 for time locks)
|
||||
nLockTime = 0 or (FULL format only) as appropriate (for time locks)
|
||||
vin[0].prevout.hash = to_spend.txid
|
||||
vin[0].prevout.n = 0
|
||||
@@ -173,13 +167,22 @@ A ''full'' signature consists of the variant-prefixed (<code>ful</code>) base64-
|
||||
|
||||
=== Full (Proof of Funds) ===
|
||||
|
||||
The [[#full-proof-of-funds|Proof of Funds]] variant extends the basic scheme: in addition to signing
|
||||
a message under a single address's key, the signer proves control over an arbitrary set of UTXOs.
|
||||
This UTXO set is chosen freely by the signer and MAY be associated with the signing address
|
||||
(the <code>message_challenge</code>). For example, it may consist of outputs paid to that address,
|
||||
but any UTXOs the signer wants to show control over are permitted.
|
||||
In any case, however, the UTXO list does not aim to prove completeness (e.g., it does NOT mean:
|
||||
"these are all UTXOs that exist for an address"), nor that they are unspent (e.g., a validator must
|
||||
consult the blockchain to verify that).
|
||||
|
||||
A signer may construct a proof of funds, demonstrating control of a set of UTXOs, by constructing a
|
||||
full signature as above, with the following modifications.
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
The <code>to_spend</code> transaction is represented as a finalized PSBT instead of a raw
|
||||
transaction (see [[bip-0174.mediawiki#input-finalizer|BIP-0174]] for details on the finalization
|
||||
transaction (see [[bip-0174.mediawiki#input-finalizer|BIP174]] for details on the finalization
|
||||
process).
|
||||
</li>
|
||||
<li>
|
||||
@@ -205,7 +208,7 @@ Unlike an ordinary signature, validators of a proof of funds need access to the
|
||||
learn that the claimed inputs exist on the blockchain and remain unspent.
|
||||
An offline validator therefore can only attest to the cryptographic validity of the additional
|
||||
inputs' witness stack, but not its blockchain state.
|
||||
An attested list of UTXOs can also never prove that there don't exist more UTXOs for a certain
|
||||
An attested list of UTXOs can also never prove that there do not exist more UTXOs for a certain
|
||||
address.
|
||||
|
||||
== Detailed Specification ==
|
||||
@@ -217,7 +220,7 @@ output with prevout <code>000...000:FFFFFFFF</code> does not exist.
|
||||
=== Verification ===
|
||||
|
||||
A validator is given as input an address ''A'' (which may be omitted in a proof-of-funds), signature
|
||||
''s'' and message ''m'', and outputs one of three states
|
||||
''s'' and message ''m'', and outputs one of three states:
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
@@ -240,14 +243,14 @@ Validation consists of the following steps:
|
||||
## Compute the transaction <code>to_spend</code> from ''m'' and ''A''
|
||||
## Decode ''s'' as the transaction <code>to_sign</code>
|
||||
## If ''s'' was a full transaction or PSBT, confirm all fields are set as specified above; in particular that
|
||||
##* <code>to_sign</code> has at least one input and its first input spends the output of </code>to_spend</code>
|
||||
##* <code>to_sign</code> has at least one input and its first input spends the output of <code>to_spend</code>
|
||||
##* <code>to_sign</code> with more than one input has an appropriate Witness UTXO or Non-Witness UTXO for each input
|
||||
##** If (based on the input type) a Non-Witness UTXO is required but not provided, check if the first input with the same transaction ID has a Non-Witness UTXO set and use that; fail validation if no such Non-Witness UTXO can be found
|
||||
##* <code>to_sign</code> has exactly one output, as specified above
|
||||
## Confirm that the two transactions together satisfy all consensus rules, except for <code>to_spend</code>'s missing input, and except that ''nSequence'' of <code>to_sign</code>'s first input and ''nLockTime'' of <code>to_sign</code> are not checked.
|
||||
# (Optional) If the validator does not have a full script interpreter, it should check that it understands all scripts being satisfied. If not, it should stop here and output ''inconclusive''.
|
||||
# Check the '''required rules''':
|
||||
## All signatures must use the SIGHASH_ALL flag.
|
||||
## All signatures MUST use the <code>SIGHASH_ALL</code> flag, unless the output type supports <code>SIGHASH_DEFAULT</code>, which then MAY be used alternatively (e.g., [[bip-0341.mediawiki|BIP341 P2TR]]).
|
||||
## The use of <code>CODESEPARATOR</code> or <code>FindAndDelete</code> is forbidden.
|
||||
## <code>LOW_S</code>, <code>STRICTENC</code> and <code>NULLFAIL</code>: valid ECDSA signatures must be strictly DER-encoded and have a low-S value; invalid ECDSA signature must be the empty push
|
||||
## <code>MINIMALDATA</code>: all pushes must be minimally encoded
|
||||
@@ -259,7 +262,7 @@ Validation consists of the following steps:
|
||||
## The use of NOPs reserved for upgrades is forbidden.
|
||||
## The use of Segwit versions greater than 1 are forbidden.
|
||||
## If any of the above steps failed, the validator should stop and output the ''inconclusive'' state.
|
||||
# Let ''T'' by the nLockTime of <code>to_sign</code> and ''S'' be the nSequence of the first input of <code>to_sign</code>. Output the state ''valid at time T and age S''.
|
||||
# Let ''T'' be the nLockTime of <code>to_sign</code> and ''S'' be the nSequence of the first input of <code>to_sign</code>. Output the state ''valid at time T and age S''.
|
||||
|
||||
=== Signing ===
|
||||
|
||||
@@ -290,7 +293,7 @@ They then encode their signature, choosing either ''simple'', ''full'' or ''full
|
||||
<li>
|
||||
If they added no inputs to <code>to_sign</code>, left nVersion, nSequence and nLockTime at 0, and
|
||||
''A'' is a "native" Segwit address (P2WPKH, P2WSH, P2TR), then they may base64-encode
|
||||
<code>message_signature</code> with <code>smp</code> as prefix.
|
||||
<code>message_signature</code> with <code>smp</code> as prefix.
|
||||
</li>
|
||||
<li>
|
||||
If they added no inputs to <code>to_sign</code>, they may base64-encode <code>to_sign</code> with
|
||||
@@ -336,7 +339,7 @@ request to the user. The new global type is defined as follows:
|
||||
|
||||
=== PSBT creator ===
|
||||
|
||||
The '''transaction creator''' of a BIP-0322 PSBT must follow these steps:
|
||||
The '''transaction creator''' of a BIP322 PSBT must follow these steps:
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
@@ -366,12 +369,12 @@ The '''transaction creator''' of a BIP-0322 PSBT must follow these steps:
|
||||
partial signature.
|
||||
</li>
|
||||
<li>
|
||||
They set the <code>PSBT_GLOBAL_GENERIC_SIGNED_MESSAGE</code> field, using the full UTF-8 encoded
|
||||
They set the <code>PSBT_GLOBAL_GENERIC_SIGNED_MESSAGE</code> field, using the full UTF-8-encoded
|
||||
message as the <code>valuedata</code>.
|
||||
<ol>
|
||||
<li>
|
||||
There is no specified maximum length of an input's <code>valuedata</code> or a PSBT as a whole in
|
||||
[[bip-0174.mediawiki|BIP-0174]], but different signers might impose safety limits. It is
|
||||
[[bip-0174.mediawiki|BIP174]], but different signers might impose safety limits. It is
|
||||
recommended to use a maximum length of a few kilobytes to maximize compatibility. Very large
|
||||
messages should be committed to by hash instead.
|
||||
</li>
|
||||
@@ -381,14 +384,14 @@ The '''transaction creator''' of a BIP-0322 PSBT must follow these steps:
|
||||
|
||||
=== PSBT signer ===
|
||||
|
||||
A '''transaction signer''' of a BIP-0322 PSBT must follow these steps:
|
||||
A '''transaction signer''' of a BIP322 PSBT must follow these steps:
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
They decode the base64-encoded PSBT as specified in [[bip-0174.mediawiki|BIP-0174]].
|
||||
They decode the base64-encoded PSBT as specified in [[bip-0174.mediawiki|BIP174]].
|
||||
</li>
|
||||
<li>
|
||||
If they detect the following properties (all must be true, otherwise this is NOT a BIP-0322 PSBT
|
||||
If they detect the following properties (all must be true, otherwise this is NOT a BIP322 PSBT
|
||||
and they should treat it as an ordinary PSBT):
|
||||
<ol>
|
||||
<li>
|
||||
@@ -397,7 +400,7 @@ A '''transaction signer''' of a BIP-0322 PSBT must follow these steps:
|
||||
</li>
|
||||
<li>
|
||||
The first PSBT input has either a <code>witness_utxo</code> or a <code>non_witness_utxo</code>
|
||||
field set and the <code>scriptPubKey</code> can be extracted, then use as
|
||||
field set and the <code>scriptPubKey</code> can be extracted. Use that as
|
||||
<code>message_challenge</code> in the next steps.
|
||||
</li>
|
||||
<li>
|
||||
@@ -419,7 +422,7 @@ A '''transaction signer''' of a BIP-0322 PSBT must follow these steps:
|
||||
signing and the address they are signing for.
|
||||
<ol>
|
||||
<li>
|
||||
Even though the message being signed is a transaction, the user interaction (e.g. the steps and
|
||||
Even though the message being signed is a transaction, the user interaction (e.g., the steps and
|
||||
messages shown on a hardware signing device's screen) should resemble the steps to sign a legacy
|
||||
message, not the steps for signing a transaction.
|
||||
</li>
|
||||
@@ -436,25 +439,25 @@ A '''transaction signer''' of a BIP-0322 PSBT must follow these steps:
|
||||
|
||||
=== PSBT finalizer ===
|
||||
|
||||
A '''transaction finalizer''' of a BIP-0322 PSBT must follow these steps:
|
||||
A '''transaction finalizer''' of a BIP322 PSBT must follow these steps:
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
They decode the base64-encoded PSBT as specified in [[bip-0174.mediawiki|BIP-0174]].
|
||||
They decode the base64-encoded PSBT as specified in [[bip-0174.mediawiki|BIP174]].
|
||||
</li>
|
||||
<li>
|
||||
They finalize the PSBT as specified in [[bip-0174.mediawiki#input-finalizer|BIP-0174]].
|
||||
They finalize the PSBT as specified in [[bip-0174.mediawiki#input-finalizer|BIP174]].
|
||||
</li>
|
||||
<li>
|
||||
They then encode the signature following the same steps as described in
|
||||
[[bip-0322.mediawiki#signing|Signing]] above.
|
||||
They then encode the signature following the same steps as described in [[#signing|Signing]]
|
||||
above.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
== Compatibility ==
|
||||
|
||||
This specification is backwards compatible with the legacy signmessage/verifymessage specification
|
||||
through the special case as described above.
|
||||
This specification is backwards-compatible with the legacy signmessage/verifymessage specification
|
||||
through the special case [[#legacy|as described above]].
|
||||
To support backward compatibility with implementations of this BIP before it was finalized, a
|
||||
verifier might assume the ''simple' variant in the absence of a prefix.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user