musig: add user documentation
This commit is contained in:
parent
d5e22a59f6
commit
6b0b22bc89
189
src/modules/musig/musig.md
Normal file
189
src/modules/musig/musig.md
Normal file
@ -0,0 +1,189 @@
|
||||
MuSig - Rogue-Key-Resistant Multisignatures Module
|
||||
===========================
|
||||
|
||||
This module implements the MuSig [1] multisignature scheme. The majority of
|
||||
the module is an API designed to be used by signing or auditing participants
|
||||
in a multisignature scheme. This involves a somewhat complex state machine
|
||||
and significant effort has been taken to prevent accidental misuse of the
|
||||
API in ways that could lead to accidental signatures or loss of key material.
|
||||
|
||||
# Theory
|
||||
|
||||
In MuSig all participants contribute key material to a single signing key,
|
||||
using the equation
|
||||
|
||||
P = sum_i µ_i * P_i
|
||||
|
||||
where `P_i` is the public key of the `i`th participant and `µ_i` is a so-called
|
||||
_MuSig coefficient_ computed according to the following equation
|
||||
|
||||
C = H(P_1 || P_2 || ... || P_n)
|
||||
µ_i = H(C || i)
|
||||
|
||||
where H is a hash function modelled as a random oracle.
|
||||
|
||||
To produce a multisignature `(s, R)` on a message `m` using verification key
|
||||
`P`, signers act as follows:
|
||||
|
||||
1. Each computes a nonce, or ephemeral keypair, `(k_i, R_i)`. Every participant
|
||||
communinicates `H(R_i)` to every other participant.
|
||||
2. Upon receipt of every `H(R_i)`, each participant communicates `R_i` to every
|
||||
other participant. The recipients check that each `R_i` is consistent with
|
||||
the previously-communicated hash.
|
||||
3. Each participant computes a combined nonce
|
||||
R = sum_i R_i
|
||||
and shared challenge
|
||||
e = H(R || P || m)
|
||||
and partial signature
|
||||
s_i = k_i + µ_i*x_i*e
|
||||
where `x_i` is the secret key corresponding to `P_i`.
|
||||
|
||||
The complete signature is then the `(s, R)` where `s = sum_i s_i` and `R = sum_i R_i`.
|
||||
|
||||
# API Usage
|
||||
|
||||
It is essential to security that signers use a unique uniformly random none for all
|
||||
signing sessions, and that they do not reuse these nonces even in the case that a
|
||||
signing session fails to complete. To that end, all signing state is encapsulated
|
||||
in the data structure `secp256k1_musig_session`. The API does not expose any
|
||||
functionality to serialize or deserialize this structure; it is designed to exist
|
||||
only in memory.
|
||||
|
||||
Users who need to persist this structure must take additional security measures
|
||||
which cannot be enforced by a C API. Some guidance is provided in the documentation
|
||||
for this data structure in `include/secp256k1_musig.h`.
|
||||
|
||||
## Key Generation
|
||||
|
||||
To use MuSig, users must first compute their combined public key `P`, which is
|
||||
suitable for use on a blockchain or other public key repository. They do this
|
||||
by calling `secp256k1_musig_pubkey_combine`.
|
||||
|
||||
This function takes as input a list of public keys `P_i` in the argument
|
||||
`pubkeys`. It outputs the combined public key `P` in the out-pointer `combined_pk`
|
||||
and hash `C` in the out-pointer `pk_hash32`, if this pointer is non-NULL.
|
||||
|
||||
## Signing
|
||||
|
||||
A participant who wishes to sign a message (as opposed to observing/auditing the
|
||||
signature process, which is also a supported mode) acts as follows.
|
||||
|
||||
### Signing Participant
|
||||
|
||||
1. Starts the session by calling `secp256k1_musig_session_initialize`. This
|
||||
function outputs
|
||||
* an initialized session state in the out-pointer `session`
|
||||
* an array of initialized signer data in the out-pointer `signers`
|
||||
* a commitment `H(R_i)` to a nonce in the out-pointer `nonce_commitment32`
|
||||
It takes as input
|
||||
* a unique session ID `session_id32`
|
||||
* (optionally) a message to be signed `msg32`
|
||||
* the combined public key output from `secp256k1_musig_pubkey_combine`
|
||||
* the public key hash output from `secp256k1_musig_pubkey_combine`
|
||||
* the signer's index `i` `my_index`
|
||||
* the signer's secret key `seckey`
|
||||
2. The signer then communicates `H(R_i)` to all other signers, and receives
|
||||
commitments `H(R_j)` from all other signers `j`. These hashes are simply
|
||||
length-32 byte arrays which can be communicated however is communicated.
|
||||
3. Once all signers nonce commitments have been received, the signer records
|
||||
these commitments with the function `secp256k1_musig_session_get_public_nonce`.
|
||||
This function updates in place
|
||||
* the session state `session`
|
||||
* the array of signer data `signers`
|
||||
taking in as input the list of commitments `commitments` and outputting the
|
||||
signer's public nonce `R_i` in the out-pointer `nonce`.
|
||||
4. The signer then communicates `R_i` to all other signers, and receives `R_j`
|
||||
from each signer `j`. On receipt of a nonce `R_j` he calls the function
|
||||
`secp256k1_musig_set_nonce` to record this fact. This function checks that
|
||||
the received nonce is consistent with the previously-received nonce and will
|
||||
return 0 in this case.
|
||||
These nonces `R_i` are secp256k1 public keys; they should be serialized using
|
||||
`secp256k1_ec_pubkey_serialize` and parsed with `secp256k1_ec_pubkey_parse`.
|
||||
5. Once all nonces have been exchanged in this way, signers are able to compute
|
||||
their partial signatures. They do so by calling `secp256k1_musig_session_combine_nonces`
|
||||
which updates in place
|
||||
* the session state `session`
|
||||
* the array of signer data `signers`
|
||||
It outputs an auxillary integer `nonce_is_negated` and has an auxillary input
|
||||
`adaptor`. Both of these may be set to NULL for ordinary signing purposes.
|
||||
If the signer did not provide a message to `secp256k1_musig_session_initialize`,
|
||||
a message must be provided now by calling `secp256k1_musig_session_set_msg` which
|
||||
updates the session state in place.
|
||||
6. The signer computes a partial signature `s_i` using the function
|
||||
`secp256k1_musig_partial_sign` which takes the session state as input and
|
||||
partial signature as output.
|
||||
7. The signer then communicates the partial signature `s_i` to all other signers, or
|
||||
to a central coordinator. These partial signatures should be serialized using
|
||||
`musig_partial_signature_serialize` and parsed using `musig_partial_signature_parse`.
|
||||
8. Each signer calls `secp256k1_musig_partial_sig_verify` on the other signers' partial
|
||||
signatures to verify their correctness. If only the validity of the final signature
|
||||
is important, not assigning blame, this step can be skipped.
|
||||
9. Any signer, or central coordinator, may combine the partial signatures to obtain
|
||||
a complete signature using `secp256k1_musig_partial_sig_combine`. This function takes
|
||||
a signing session and array of MuSig partial signatures, and outputs a single
|
||||
Schnorr signature.
|
||||
|
||||
### Non-signing Participant
|
||||
|
||||
A participant who wants to verify the signing process but not actually contribute a
|
||||
partial signature, may do so using the above instructions except for the following
|
||||
changes:
|
||||
|
||||
1. A signing session should be produced using `musig_session_initialize_verifier`
|
||||
rather than `musig_session_initialize`; this function takes no secret data or
|
||||
signer index.
|
||||
2. The participant receives nonce commitments, public nonces and partial signatures,
|
||||
but does not produce these values. Therefore `secp256k1_musig_session_get_public_nonce`
|
||||
and `secp256k1_musig_partial_sign` are not called.
|
||||
|
||||
### Verifier
|
||||
|
||||
The final signature is simply a valid Schnorr signature using the combined public key. It
|
||||
can be verified using the `secp256k1_schnorrsig_verify` with the correct message and
|
||||
public key output from `secp256k1_musig_pubkey_combine`.
|
||||
|
||||
## Atomic Swaps
|
||||
|
||||
The signing API supports the production of "adaptor signatures", modified partial signatures
|
||||
which have an auxiliary secret encrypted to them. A partial signature is revealed to a party
|
||||
who learns the secret; conversely, a party with the corresponding secret will learn the
|
||||
secret.
|
||||
|
||||
Using these adaptor signatures, two 2-of-2 MuSig signing protocols can be executed in
|
||||
parallel such that one party's partial signatures are made atomic. That is, when the other
|
||||
party learns one partial signature, she automatically learns the other. This has applications
|
||||
in cross-chain atomic swaps.
|
||||
|
||||
Such a protocol can be executed as follows. Consider two participants, Alice and Bob, who
|
||||
are simultaneously producing 2-of-2 multisignatures for two blockchains A and B. They act
|
||||
as follows.
|
||||
|
||||
1. Before the protocol begins, Bob chooses a 32-byte auxiliary secret `t` at random and
|
||||
computes a corresponding public point `T` by calling `secp256k1_ec_pubkey_create`.
|
||||
He communicates `T` to Alice.
|
||||
2. Together, the parties execute steps 1-4 of the signing protocol above.
|
||||
3. At step 5, when combining the two parties' public nonces, both parties call
|
||||
`secp256k1_musig_session_combine_nonces` with `adaptor` set to `T` and `nonce_is_negated`
|
||||
set to a non-NULL pointer to int.
|
||||
4. Steps 6 and 7 proceed as before. Step 8, verifying the partial signatures, is now
|
||||
essential to the security of the protocol and must not be omitted!
|
||||
|
||||
The above steps are executed identically for both signing sessions. However, step 9 will
|
||||
not work as before, since the partial signatures will not add up to a valid total signature.
|
||||
Additonal steps must be taken, and it is at this point that the two signing sessions
|
||||
diverge. From here on we consider "Session A" which benefits Alice (e.g. which sends her
|
||||
coins) and "Session B" which benefits Bob (e.g. which sends him coins).
|
||||
|
||||
5. In Session B, Bob calls `secp256k1_musig_partial_sig_adapt` with his partial signature
|
||||
and `t`, to produce an adaptor signature. He can then call `secp256k1_musig_partial_sig_combine`
|
||||
with this adaptor signature and Alice's partial signature, to produce a complete
|
||||
signature for blockchain B.
|
||||
6. Alice reads this signature from blockchain B. She calls `secp256k1_musig_extract_secret_adaptor`,
|
||||
passing the complete signature along with her and Bob's partial signatures. This function
|
||||
outputs `t`, which until this point was only known to Bob.
|
||||
7. In Session A, Alice is now able to replicate Bob's action, calling
|
||||
`secp256k1_musig_partial_sig_adapt` with her own partial signature and `t`, ultimately
|
||||
producing a complete signature on blockchain A.
|
||||
|
||||
[1] https://eprint.iacr.org/2018/068
|
||||
|
Loading…
x
Reference in New Issue
Block a user