From 6b0b22bc89cbacfdd16ae80f7d5c759a4bade2c3 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Fri, 8 Feb 2019 19:31:28 +0000 Subject: [PATCH 1/8] musig: add user documentation --- src/modules/musig/musig.md | 189 +++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 src/modules/musig/musig.md diff --git a/src/modules/musig/musig.md b/src/modules/musig/musig.md new file mode 100644 index 00000000..89b79076 --- /dev/null +++ b/src/modules/musig/musig.md @@ -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 + From 04925920100d62cf0530c6ae987c64b65a1a9815 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Tue, 12 Feb 2019 14:39:03 +0000 Subject: [PATCH 2/8] f replace C by L --- src/modules/musig/musig.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/musig/musig.md b/src/modules/musig/musig.md index 89b79076..aebe20ed 100644 --- a/src/modules/musig/musig.md +++ b/src/modules/musig/musig.md @@ -17,8 +17,8 @@ using the equation 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) + L = H(P_1 || P_2 || ... || P_n) + µ_i = H(L || i) where H is a hash function modelled as a random oracle. @@ -61,7 +61,7 @@ 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. +and hash `L` in the out-pointer `pk_hash32`, if this pointer is non-NULL. ## Signing From 8cab1c5caed5323e8b88d8a3760e43cd2919e8ec Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Tue, 12 Feb 2019 14:43:14 +0000 Subject: [PATCH 3/8] f more nits --- src/modules/musig/musig.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/modules/musig/musig.md b/src/modules/musig/musig.md index aebe20ed..854d1459 100644 --- a/src/modules/musig/musig.md +++ b/src/modules/musig/musig.md @@ -42,7 +42,9 @@ The complete signature is then the `(s, R)` where `s = sum_i s_i` and `R = sum_i # API Usage -It is essential to security that signers use a unique uniformly random none for all +The following sections describe use of our API, and are mirrored in code in `src/modules/musig/example.c`. + +It is essential to security that signers use a unique uniformly random nonce 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 @@ -70,8 +72,8 @@ 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 + 1. The signer 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` @@ -96,7 +98,8 @@ signature process, which is also a supported mode) acts as follows. 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. + return 0 in this case. The signer must also call this function with his own + nonce and his own index `i`. 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 @@ -104,7 +107,7 @@ signature process, which is also a supported mode) acts as follows. 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 + It outputs an auxilary integer `nonce_is_negated` and has an auxilary 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 @@ -125,9 +128,9 @@ signature process, which is also a supported mode) acts as follows. ### 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: +A participant who wants to verify the signing process, i.e. check that nonce commitments +are consistent and partial signatures are correct without contributing 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 @@ -170,7 +173,7 @@ as follows. 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 +Additional 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). From 0512dd2ba918157f15ead00090d6c07e58c5a479 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Tue, 12 Feb 2019 14:53:36 +0000 Subject: [PATCH 4/8] f reword adaptor signature stuf --- src/modules/musig/musig.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/modules/musig/musig.md b/src/modules/musig/musig.md index 854d1459..a8f95496 100644 --- a/src/modules/musig/musig.md +++ b/src/modules/musig/musig.md @@ -148,9 +148,13 @@ 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. +which are offset by an auxiliary secret known to one party. That is, + 1. One party generates a (secret) adaptor `t` with corresponding (public) adaptor `T = t*G`. + 2. When combining nonces, each party adds `T` to the total nonce used in the signature. + 3. The party who knows `t` must "adapt" their partial signature with `t` to complete the + signature. + 4. Any party who sees both the final signature and the original partial signatures + can compute `t`. 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 @@ -182,8 +186,8 @@ coins) and "Session B" which benefits Bob (e.g. which sends him coins). 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. + passing the complete signature along with her and Bob's partial signatures from Session B. + 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. From 9125c166229cb6271fa344f568dc2e8f736b36f3 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Tue, 12 Feb 2019 14:54:29 +0000 Subject: [PATCH 5/8] f remove markdown indentation --- src/modules/musig/musig.md | 194 ++++++++++++++++++------------------- 1 file changed, 97 insertions(+), 97 deletions(-) diff --git a/src/modules/musig/musig.md b/src/modules/musig/musig.md index a8f95496..64dde142 100644 --- a/src/modules/musig/musig.md +++ b/src/modules/musig/musig.md @@ -12,7 +12,7 @@ API in ways that could lead to accidental signatures or loss of key material. In MuSig all participants contribute key material to a single signing key, using the equation - P = sum_i µ_i * P_i + 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 @@ -25,18 +25,18 @@ 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`. +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`. @@ -72,59 +72,59 @@ signature process, which is also a supported mode) acts as follows. ### Signing Participant - 1. The signer 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. The signer must also call this function with his own - nonce and his own index `i`. - 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 auxilary integer `nonce_is_negated` and has an auxilary 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. +1. The signer 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. The signer must also call this function with his own + nonce and his own index `i`. + 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 auxilary integer `nonce_is_negated` and has an auxilary 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 @@ -132,12 +132,12 @@ A participant who wants to verify the signing process, i.e. check that nonce com are consistent and partial signatures are correct without contributing 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. +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 @@ -149,12 +149,12 @@ public key output from `secp256k1_musig_pubkey_combine`. The signing API supports the production of "adaptor signatures", modified partial signatures which are offset by an auxiliary secret known to one party. That is, - 1. One party generates a (secret) adaptor `t` with corresponding (public) adaptor `T = t*G`. - 2. When combining nonces, each party adds `T` to the total nonce used in the signature. - 3. The party who knows `t` must "adapt" their partial signature with `t` to complete the - signature. - 4. Any party who sees both the final signature and the original partial signatures - can compute `t`. +1. One party generates a (secret) adaptor `t` with corresponding (public) adaptor `T = t*G`. +2. When combining nonces, each party adds `T` to the total nonce used in the signature. +3. The party who knows `t` must "adapt" their partial signature with `t` to complete the + signature. +4. Any party who sees both the final signature and the original partial signatures + can compute `t`. 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 @@ -165,15 +165,15 @@ Such a protocol can be executed as follows. Consider two participants, Alice and 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! +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. @@ -181,16 +181,16 @@ Additional steps must be taken, and it is at this point that the two signing ses 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 from Session B. - 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. +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 from Session B. + 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 From 792d50431591b2b577c7f553a714bbb5c1b0bd19 Mon Sep 17 00:00:00 2001 From: Janus Troelsen Date: Mon, 18 Feb 2019 16:30:31 +0100 Subject: [PATCH 6/8] Update musig.md Use monospaced font for math expressions --- src/modules/musig/musig.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/musig/musig.md b/src/modules/musig/musig.md index 64dde142..4bc2c881 100644 --- a/src/modules/musig/musig.md +++ b/src/modules/musig/musig.md @@ -31,11 +31,11 @@ To produce a multisignature `(s, R)` on a message `m` using verification key 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 + `R = sum_i R_i` and shared challenge - e = H(R || P || m) + `e = H(R || P || m)` and partial signature - s_i = k_i + µ_i*x_i*e + `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`. From 89b7f5b73ba9619e651c0c2c422f7574270d2208 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Wed, 20 Feb 2019 15:25:47 +0000 Subject: [PATCH 7/8] f nits --- include/secp256k1_musig.h | 4 ++++ src/modules/musig/musig.md | 21 ++++++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/include/secp256k1_musig.h b/include/secp256k1_musig.h index ead762d2..b65f194b 100644 --- a/include/secp256k1_musig.h +++ b/include/secp256k1_musig.h @@ -7,6 +7,10 @@ * (https://eprint.iacr.org/2018/068.pdf). There's an example C source file in the * module's directory (src/modules/musig/example.c) that demonstrates how it can be * used. + * + * The documentation in this include file is for reference and may not be sufficient + * for users to begin using the library. A full description of API usage can be found + * in src/modules/musig/musig.md */ /** Data structure containing data related to a signing session resulting in a single diff --git a/src/modules/musig/musig.md b/src/modules/musig/musig.md index 4bc2c881..015ce91b 100644 --- a/src/modules/musig/musig.md +++ b/src/modules/musig/musig.md @@ -7,14 +7,16 @@ 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. +The resulting signatures are valid Schnorr signatures as described in [2]. + # Theory -In MuSig all participants contribute key material to a single signing key, +In MuSig all signers 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 +where `P_i` is the public key of the `i`th signer and `µ_i` is a so-called _MuSig coefficient_ computed according to the following equation L = H(P_1 || P_2 || ... || P_n) @@ -25,12 +27,12 @@ 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 +1. Each computes a nonce, or ephemeral keypair, `(k_i, R_i)`. Every signer + communicates `H(R_i)` to every participant (both signers and auditors). +2. Upon receipt of every `H(R_i)`, each signer communicates `R_i` to every + participant. The recipients check that each `R_i` is consistent with the + previously-communicated hash. +3. Each signer computes a combined nonce `R = sum_i R_i` and shared challenge `e = H(R || P || m)` @@ -107,7 +109,7 @@ signature process, which is also a supported mode) acts as follows. which updates in place - the session state `session` - the array of signer data `signers` - It outputs an auxilary integer `nonce_is_negated` and has an auxilary input + It outputs an auxiliary integer `nonce_is_negated` and has an auxiliary 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 @@ -193,4 +195,5 @@ coins) and "Session B" which benefits Bob (e.g. which sends him coins). producing a complete signature on blockchain A. [1] https://eprint.iacr.org/2018/068 +[2] https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr.mediawiki From f6a6bca22f1e8de255a276e06ec7be159058c26b Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Thu, 21 Feb 2019 15:02:13 +0000 Subject: [PATCH 8/8] musig: remove musig_session API docs about session ID reuse; link to Blockstream blog post --- include/secp256k1_musig.h | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/include/secp256k1_musig.h b/include/secp256k1_musig.h index b65f194b..657bacab 100644 --- a/include/secp256k1_musig.h +++ b/include/secp256k1_musig.h @@ -19,22 +19,9 @@ * This structure is not opaque, but it MUST NOT be copied or read or written to it * directly. A signer who is online throughout the whole process and can keep this * structure in memory can use the provided API functions for a safe standard - * workflow. - * - * A signer who goes offline and needs to import/export or save/load this structure - * **must** take measures prevent replay attacks wherein an old state is loaded and - * the signing protocol forked from that point. One straightforward way to accomplish - * this is to attach the output of a monotonic non-resettable counter (hardware - * support is needed for this). Increment the counter before each output and - * encrypt+sign the entire package. If a package is deserialized with an old counter - * state or bad signature it should be rejected. - * - * Observe that an independent counter is needed for each concurrent signing session - * such a device is involved in. To avoid fragility, it is therefore recommended that - * any offline signer be usable for only a single session at once. - * - * Given access to such a counter, its output should be used as (or mixed into) the - * session ID to ensure uniqueness. + * workflow. See https://blockstream.com/2019/02/18/musig-a-new-multisignature-standard/ + * for more details about the risks associated with serializing or deserializing this + * structure. * * Fields: * combined_pk: MuSig-computed combined public key