mirror of
https://github.com/bitcoinbook/bitcoinbook
synced 2025-02-02 02:41:42 +00:00
CH08: edits for feedback from Murch
- Drop box with Wikipedia definition of digital signatures. It didn't add anything and its accuracy was debatable. - Use "commitment hash" earlier and more often. - Fix some variable-name errors in the math - Correct info about worst-case signature verification cost
This commit is contained in:
parent
4165d6e113
commit
644867fd92
@ -1377,7 +1377,7 @@ would have to include a signature within the transaction input:
|
||||
----
|
||||
[...]
|
||||
"vin" : [
|
||||
"txid": "0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2",
|
||||
"txid": "abcdef12345...",
|
||||
"vout": 0,
|
||||
"scriptSig": “<Bob’s scriptSig>”,
|
||||
]
|
||||
@ -1392,7 +1392,7 @@ input script and includes a witness structure:
|
||||
----
|
||||
[...]
|
||||
"vin" : [
|
||||
"txid": "0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2",
|
||||
"txid": "abcdef12345...",
|
||||
"vout": 0,
|
||||
"scriptSig": “”,
|
||||
]
|
||||
|
@ -15,59 +15,42 @@ Any time one of those is executed, a signature must be
|
||||
provided.
|
||||
|
||||
((("digital signatures", "purposes of")))A digital signature serves
|
||||
three purposes in Bitcoin (see the following sidebar). First, the
|
||||
three purposes in Bitcoin. First, the
|
||||
signature proves that the controller of a private key, who is by
|
||||
implication the owner of the funds, has _authorized_ the spending of
|
||||
those funds. Secondly, the proof of authorization is _undeniable_
|
||||
(nonrepudiation). Thirdly, the signature proves that specific parts of
|
||||
the transaction have not and _cannot be modified_ by
|
||||
anyone besides the signer.
|
||||
|
||||
Note that each transaction input is signed independently. This is
|
||||
critical, as neither the signatures nor the inputs have to belong to or
|
||||
be applied by the same "owners." In fact, a specific transaction scheme
|
||||
called "CoinJoin" uses this fact to create multi-party transactions for
|
||||
privacy.
|
||||
(nonrepudiation). Thirdly, that the authorized transaction cannot be
|
||||
changed by unauthenticated third parties--that its _integrity_ is
|
||||
intact.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Each transaction input and any signatures it may contain is _completely_
|
||||
independent of any other input or signature. Multiple parties can
|
||||
collaborate to construct transactions and sign only one input each.
|
||||
Several protocols uses this fact to create multi-party transactions for
|
||||
privacy.
|
||||
====
|
||||
|
||||
[[digital_signature_definition]]
|
||||
.Wikipedia's Definition of a "Digital Signature"
|
||||
****
|
||||
((("digital signatures", "defined")))A digital signature is a
|
||||
mathematical scheme for demonstrating the authenticity of a digital
|
||||
message or documents. A valid digital signature gives a recipient reason
|
||||
to believe that the message was created by a known sender
|
||||
(authentication), that the sender cannot deny having sent the message
|
||||
(nonrepudiation), and that the message was not altered in transit
|
||||
(integrity).
|
||||
|
||||
_Source: https://en.wikipedia.org/wiki/Digital_signature_
|
||||
****
|
||||
|
||||
In this chapter we look at how digital signatures work and how they can
|
||||
present proof of control of a private key without revealing that private
|
||||
key.
|
||||
|
||||
=== How Digital Signatures Work
|
||||
|
||||
((("digital signatures", "how they work")))A digital signature is a
|
||||
_mathematical scheme_ that consists of two parts. The first part is an
|
||||
algorithm for creating a signature, using a private key (the signing
|
||||
key), from a message (the transaction). The second part is an algorithm
|
||||
((("digital signatures", "how they work")))A digital signature
|
||||
consists of two parts. The first part is an algorithm for creating a
|
||||
signature for a message (the transaction) using a private key (the
|
||||
signing key). The second part is an algorithm
|
||||
that allows anyone to verify the signature, given also the message and a
|
||||
public key.
|
||||
|
||||
==== Creating a digital signature
|
||||
|
||||
In Bitcoin's implementation of digital signature algorithms, the "message" being
|
||||
In Bitcoin's use of digital signature algorithms, the "message" being
|
||||
signed is the transaction, or more accurately a hash of a specific
|
||||
subset of the data in the transaction (see <<sighash_types>>). The
|
||||
subset of the data in the transaction, called the _commitment hash_ (see
|
||||
<<sighash_types>>). The
|
||||
signing key is the user's private key. The result is the signature:
|
||||
|
||||
latexmath:[\(Sig = F_{sig}(F_{hash}(m), x)\)]
|
||||
@ -75,7 +58,7 @@ latexmath:[\(Sig = F_{sig}(F_{hash}(m), x)\)]
|
||||
where:
|
||||
|
||||
* _x_ is the signing private key
|
||||
* _m_ is the message to sign (such as parts of a transaction)
|
||||
* _m_ is the message to sign, the commitment hash (such as parts of a transaction)
|
||||
* _F_~_hash_~ is the hashing function
|
||||
* _F_~_sig_~ is the signing algorithm
|
||||
* _Sig_ is the resulting signature
|
||||
@ -96,27 +79,27 @@ simpler serialization format is used.
|
||||
|
||||
==== Verifying the Signature
|
||||
|
||||
((("digital signatures", "verifying")))To verify the signature, one must
|
||||
have the signature, the serialized transaction, some data about the
|
||||
output being spent, and the public key that corresponds to the private key used to create the
|
||||
signature. Essentially, verification of a signature means "Only the
|
||||
controller of the private key that generated this public key could have
|
||||
produced this signature on this transaction."
|
||||
((("digital signatures", "verifying"))) The signature verification
|
||||
algorithm takes the message (a hash of parts of the transaction and
|
||||
related data), the signer's public key and the signature, and returns
|
||||
TRUE if the signature is valid for this message and public key.
|
||||
|
||||
The signature verification algorithm takes the message (a hash of
|
||||
parts of the transaction and related data), the signer's public key and the signature,
|
||||
and returns TRUE if the signature is valid for
|
||||
this message and public key.
|
||||
To verify the signature, one must have the signature, the serialized
|
||||
transaction, some data about the output being spent, and the public key
|
||||
that corresponds to the private key used to create the signature.
|
||||
Essentially, verification of a signature means "Only the controller of
|
||||
the private key that generated this public key could have produced this
|
||||
signature on this transaction."
|
||||
|
||||
[[sighash_types]]
|
||||
==== Signature Hash Types (SIGHASH)
|
||||
|
||||
((("digital signatures", "signature hash
|
||||
types")))((("commitment")))Digital signatures are applied to messages,
|
||||
types")))((("commitment")))Digital signatures apply to messages,
|
||||
which in the case of Bitcoin, are the transactions themselves. The
|
||||
signature implies a _commitment_ by the signer to specific transaction
|
||||
signature prove a _commitment_ by the signer to specific transaction
|
||||
data. In the simplest form, the signature applies to almost the entire
|
||||
transaction, thereby committing all the inputs, outputs, and other
|
||||
transaction, thereby committing to all the inputs, outputs, and other
|
||||
transaction fields. However, a signature can commit to only a subset of
|
||||
the data in a transaction, which is useful for a number of scenarios as
|
||||
we will see in this section.
|
||||
@ -133,7 +116,7 @@ transaction.
|
||||
|
||||
Remember, each input may contain one or more signatures. As
|
||||
a result, an input may have signatures
|
||||
with different +SIGHASH+ flags that commit different parts of the
|
||||
with different +SIGHASH+ flags that commit to different parts of the
|
||||
transaction. Note also that Bitcoin transactions
|
||||
may contain inputs from different "owners," who may sign only one input
|
||||
in a partially constructed transaction, collaborating with
|
||||
@ -179,8 +162,8 @@ either omitted or truncated (set to zero length and emptied). The resulting tran
|
||||
serialized. The +SIGHASH+ flag is included in the serialized
|
||||
transaction data and the result is hashed. The hash digest itself is the "message"
|
||||
that is signed. Depending on which +SIGHASH+ flag is used, different
|
||||
parts of the transaction are included. The resulting hash depends on
|
||||
different subsets of the data in the transaction. By including the
|
||||
parts of the transaction are included.
|
||||
By including the
|
||||
+SIGHASH+ flag itself, the signature commits the
|
||||
+SIGHASH+ type as well, so it can't be changed (e.g., by a miner).
|
||||
|
||||
@ -217,10 +200,10 @@ someone who lends them funds), allowing them to collect the donations
|
||||
even if they haven't reached the specified value.
|
||||
|
||||
+NONE+ :: This construction can be used to create a "bearer check" or
|
||||
"blank check" of a specific amount. It commits to the input, but allows
|
||||
the output script to be changed. Anyone can write their own
|
||||
Bitcoin address into the output script. However, the output value
|
||||
itself cannot be changed. By itself, this allows any miner to change
|
||||
"blank check" of a specific amount. It commits to all inputs, but allows
|
||||
the outputs to be changed. Anyone can write their own
|
||||
Bitcoin address into the output script.
|
||||
By itself, this allows any miner to change
|
||||
the output destination and claim the funds for themselves, but if other
|
||||
required signatures in the transaction use +SIGHASH_ALL+ or another type
|
||||
that commits to the output, it allows those spenders to change the
|
||||
@ -248,7 +231,7 @@ destination.
|
||||
|
||||
A signature using +SIGHASH_ANYPREVOUTANYSCRIPT+ would not
|
||||
commit to the outpoint, the amount, the witness program, or the
|
||||
tapleaf_hash used, allowing it to spend any previous output
|
||||
specific leaf in the taproot merkle tree (script tree), allowing it to spend any previous output
|
||||
which the signature could satisfy. For example, if Alice received two
|
||||
outputs for different amounts and different witness programs (e.g. one
|
||||
requiring a single signature and another requiring her signature plus some
|
||||
@ -394,7 +377,7 @@ Of course, this is an oversimplified example. When working with simple
|
||||
integers, we can divide products by the generator +G+ to get the
|
||||
underlying scalar, which isn't secure. This is why a critical property
|
||||
of the Elliptic Curve Cryptography (ECC) used in Bitcoin is that
|
||||
multiplication is easy but division is impractical. Also, with numbers
|
||||
multiplication is easy but division by a point on the curve is impractical. Also, with numbers
|
||||
this small, finding underlying values (or valid substitutes) through
|
||||
brute force is easy; the numbers used in Bitcoin are much larger.
|
||||
****
|
||||
@ -405,9 +388,9 @@ identity protocol that make it secure:
|
||||
- The nonce (+k+). In step 1, Alice chooses a number that Bob doesn't
|
||||
know and can't guess and gives him the scaled form of that number,
|
||||
+kG+. At that point, Bob also already has her public key (+xG+),
|
||||
which is the scaled form of +x+. That means when Bob is working on
|
||||
which is the scaled form of +x+, her private key. That means when Bob is working on
|
||||
the final equation (+sG = kG + exG+), there are two independent
|
||||
variables that Bob doesn't know (+xG+ and +kG+). It's possible to use
|
||||
variables that Bob doesn't know (+x+ and +k+). It's possible to use
|
||||
simple algebra to solve an equation with one unknown variable but not
|
||||
two independent unknown variables, so the presence of Alice's nonce
|
||||
prevents Bob from being able to derive her private key. It's critical
|
||||
@ -417,7 +400,7 @@ identity protocol that make it secure:
|
||||
<<nonce_warning>> for more details.
|
||||
|
||||
- The challenge scalar (+e+). Bob waits to receive Alice's public nonce
|
||||
and then proceeds in step 2 to giver her a number (the challenge
|
||||
and then proceeds in step 2 to give her a number (the challenge
|
||||
scalar) that Alice didn't previously know and couldn't have guessed.
|
||||
It's critical that Bob only give her the challenge scalar after she
|
||||
commits to her public nonce. Consider what could happen if someone
|
||||
@ -478,11 +461,11 @@ explicitly, the verification equation becomes +sG == kG + hash(kG) * xG+.
|
||||
We need one other thing to finish converting the interactive schnorr
|
||||
identity protocol into a digital signature protocol useful for
|
||||
Bitcoin. We don't just want Alice to prove that she knows her private
|
||||
key; we also want to give her the to ability to commit to a message. Specifically,
|
||||
key; we also want to give her the ability to commit to a message. Specifically,
|
||||
we want her to commit to the data related to the Bitcoin transaction she
|
||||
wants to send. With the Fiat-Shamir transform in place, we already
|
||||
have a commitment, so we can simply have it additionally commit to the
|
||||
message. Instead of +hash(kG)+, we now also commit to to the message
|
||||
message. Instead of +hash(kG)+, we now also commit to the message
|
||||
+m+ using +hash(kG || m)+, where +||+ stands for concatenation.
|
||||
|
||||
We've now defined a version of the schnorr signature protocol, but
|
||||
@ -522,7 +505,7 @@ she's ready to spend, she begins generating her signature:
|
||||
are her signature. She gives this signature to everyone who wants to
|
||||
verify that signature; she also needs to ensure everyone receives her
|
||||
message +m+. In Bitcoin, this is done by including her signature in
|
||||
the witness of her spending transaction and then relaying that
|
||||
the witness structure of her spending transaction and then relaying that
|
||||
transaction to full nodes.
|
||||
|
||||
4. The verifiers (e.g. full nodes) use +s+ to derive +sG+ and then
|
||||
@ -620,7 +603,7 @@ the private key for +z+, i.e. Bob's private key. Now Bob can create a
|
||||
valid signature without any assistance from Alice. This is called a
|
||||
_key cancellation attack_.
|
||||
|
||||
There are various ways to solve to the key cancellation attack. The
|
||||
There are various ways to solve the key cancellation attack. The
|
||||
simplest scheme would be to require each participant commit to their
|
||||
part of the public key before sharing anything about that key with all
|
||||
of the other participants. For example, Alice and Bob each individually
|
||||
@ -716,7 +699,7 @@ number of shares. For example, Alice can choose a threshold (_k_) of
|
||||
+2+ if she wants any two of Bob, Carol, and Dan to be able to
|
||||
reconstruct her secret. The best known secure secret sharing algorithm
|
||||
is _Shamir's Secret Sharing Scheme_, commonly abbreviated SSSS and named
|
||||
after its discoverer, one of the same discovers of the Fiat-Shamir
|
||||
after its discoverer, one of the same discoverers of the Fiat-Shamir
|
||||
transform we saw in <<schnorr_signatures>>.
|
||||
|
||||
In some cryptographic protocols, such as the scriptless threshold signature
|
||||
@ -764,7 +747,7 @@ multisignature produced by a process that involved Carol and one that
|
||||
didn't. Even if Alice, Bob, or Carol claim that they didn't sign,
|
||||
there's no guaranteed way for them to prove that they didn't
|
||||
help produce the signature. If it's important to know which members of
|
||||
the group signed, you will need to use scripted threshold signatures.
|
||||
the group signed, you will need to use a script.
|
||||
|
||||
2. Manipulation attacks: imagine that Bob tells Alice that Carol is
|
||||
unavailable, so they work together to reconstruct Carol's partial
|
||||
@ -795,7 +778,7 @@ using the schnorr signature scheme developed an alternative construction
|
||||
called the _Digital Signature Algorithm_ (DSA), with a version adapted
|
||||
to Elliptic Curves called ECDSA.
|
||||
|
||||
The ECDSA scheme and standardized parameters for curves it could be used
|
||||
The ECDSA scheme and standardized parameters for suggested curves it could be used
|
||||
with were widely implemented in cryptographic libraries by the time
|
||||
development on Bitcoin began in 2007. This was almost certainly the
|
||||
reason why ECDSA was the only digital signature protocol that Bitcoin
|
||||
@ -837,15 +820,8 @@ values are _R_ and _S_.
|
||||
|
||||
((("public and private keys", "key pairs", "ephemeral")))The signature
|
||||
algorithm first generates a private nonce (_k_) and derives from it a public
|
||||
nonce (_K_). These are used in the calculation of the _R_ and
|
||||
_S_ values, after a transformation involving the signing private key and
|
||||
the transaction hash.
|
||||
|
||||
From _k_, we generate the corresponding
|
||||
public nonce _K_ (calculated as _K = k*G_, in the same way
|
||||
bitcoin public keys are derived; see <<public_key_derivation>>). The _R_ value of the
|
||||
digital signature is then the x coordinate of the ephemeral public key
|
||||
_K_.
|
||||
nonce (_K_). The _R_ value of the digital signature is then the x
|
||||
coordinate of the ephemeral public key _K_.
|
||||
|
||||
From there, the algorithm calculates the _S_ value of the signature,
|
||||
such that:
|
||||
@ -861,11 +837,11 @@ where:
|
||||
* _p_ is the prime order of the elliptic curve
|
||||
|
||||
Verification is the inverse of the signature generation function, using
|
||||
the _R_, _S_ values and the public key to calculate a value _P_, which
|
||||
the _R_, _S_ values and the public key to calculate a value _K_, which
|
||||
is a point on the elliptic curve (the public nonce used in
|
||||
signature creation):
|
||||
|
||||
_P_ = __S__^-1^ * __Hash__(__m__) * _G_ + __S__^-1^ * _R_ * _X_
|
||||
_K_ = __S__^-1^ * __Hash__(__m__) * _G_ + __S__^-1^ * _R_ * _X_
|
||||
|
||||
where:
|
||||
|
||||
@ -874,7 +850,7 @@ where:
|
||||
- _m_ is the message (the transaction data that was signed)
|
||||
- _G_ is the elliptic curve generator point
|
||||
|
||||
If the x coordinate of the calculated point _P_ is equal to _R_, then
|
||||
If the x coordinate of the calculated point _K_ is equal to _R_, then
|
||||
the verifier can conclude that the signature is valid.
|
||||
|
||||
Note that in verifying the signature, the private key is neither known
|
||||
@ -884,8 +860,7 @@ nor revealed.
|
||||
====
|
||||
ECDSA is necessarily a fairly complicated piece of math; a full
|
||||
explanation is beyond the scope of this book. A number of great guides
|
||||
online take you through it step by step: search for "ECDSA explained" or
|
||||
try this one: http://bit.ly/2r0HhGB[].
|
||||
online take you through it step by step: search for "ECDSA explained".
|
||||
====
|
||||
|
||||
[[serialization_of_signatures_der]]
|
||||
@ -921,10 +896,11 @@ is part of the DER encoding scheme.
|
||||
=== The Importance of Randomness in Signatures
|
||||
|
||||
((("digital signatures", "randomness in")))As we saw in <<schnorr_signatures>> and <<ecdsa_signatures>>,
|
||||
the signature generation algorithm uses a random key _k_, as the basis
|
||||
the signature generation algorithm uses a random number _k_, as the basis
|
||||
for a private/public nonce pair. The value of _k_ is not
|
||||
important, _as long as it is random_. If the same value _k_ is used to
|
||||
produce two signatures on different messages (transactions), then the
|
||||
important, _as long as it is random_. If signatures from the same
|
||||
private key use the private nonce _k_ with different messages
|
||||
(transactions), then the
|
||||
signing _private key_ can be calculated by anyone. Reuse of the same
|
||||
value for _k_ in a signature algorithm leads to exposure of the private
|
||||
key!
|
||||
@ -981,11 +957,11 @@ the data indicating the signer's commitment to those values. For
|
||||
example, in a simple +SIGHASH_ALL+ type signature, the commitment hash
|
||||
includes all inputs and outputs.
|
||||
|
||||
Unfortunately, the way the commitment hash was calculated introduced the
|
||||
possibility that a node verifying the signature can be forced to perform
|
||||
Unfortunately, the way the legacy commitment hashes were calculated introduced the
|
||||
possibility that a node verifying a signature can be forced to perform
|
||||
a significant number of hash computations. Specifically, the hash
|
||||
operations increase in O(n^2^) with respect to the number of signature
|
||||
operations in the transaction. An attacker could therefore create a
|
||||
operations increase roughly quadratically with respect to the number of
|
||||
inputs in the transaction. An attacker could therefore create a
|
||||
transaction with a very large number of signature operations, causing
|
||||
the entire Bitcoin network to have to perform hundreds or thousands of
|
||||
hash operations to verify the transaction.
|
||||
|
Loading…
Reference in New Issue
Block a user