diff --git a/README.md b/README.md index 76bc0e10c..f7b3b0468 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Added features: * Experimental module for Confidential Assets (Pedersen commitments, range proofs, and [surjection proofs](src/modules/surjection/surjection.md)). * Experimental module for Bulletproofs++ range proofs. * Experimental module for [address whitelisting](src/modules/whitelist/whitelist.md). -* Experimental module for FROST. +* Experimental module for [FROST](src/modules/frost/frost.md). Experimental features are made available for testing and review by the community. The APIs of these features should not be considered stable. diff --git a/include/secp256k1_frost.h b/include/secp256k1_frost.h index d0d01d36e..f083ce4d6 100644 --- a/include/secp256k1_frost.h +++ b/include/secp256k1_frost.h @@ -21,6 +21,9 @@ extern "C" { * The module also supports BIP-341 ("Taproot") and BIP-32 ("ordinary") public * key tweaking, and adaptor signatures. * + * It is recommended to read the documentation in this include file carefully. + * Further notes on API usage can be found in src/modules/frost/frost.md + * * Following the convention used in the MuSig module, the API uses the singular * term "nonce" to refer to the two "nonces" used by the FROST scheme. */ diff --git a/src/modules/frost/frost.md b/src/modules/frost/frost.md new file mode 100644 index 000000000..62e23d0c5 --- /dev/null +++ b/src/modules/frost/frost.md @@ -0,0 +1,100 @@ +Notes on the frost module API +=========================== + +The following sections contain additional notes on the API of the frost module +(`include/secp256k1_frost.h`). A usage example can be found in +`examples/frost.c`. + +# API misuse + + + + +Users of the frost module must take great care to make sure of the following: + +1. Each participant exchanges public keys for identification and authentication + purposes. Partipants must provide the same public key to each other + participant. +2. The dealer establishes a secure communications channel with each participant + and uses that channel to transmit shares during key generation. +3. A unique set of coefficients per key generation session is generated in + `secp256k1_frost_shares_gen`. See the corresponding comment in + `include/secp256k1_frost.h` for how to ensure that. +4. The `pubnonces` provided to `secp256k1_frost_nonce_process` are sorted by + the corresponding lexicographic ordering of the x-only pubkey of each + participant, and the `ids33` provided to `secp256k1_frost_nonce_process` + are sorted lexicographically. +5. A unique nonce per signing session is generated in `secp256k1_frost_nonce_gen`. + See the corresponding comment in `include/secp256k1_frost.h` for how to ensure that. +6. The `secp256k1_frost_secnonce` structure is never copied or serialized. + See also the comment on `secp256k1_frost_secnonce` in `include/secp256k1_frost.h`. +7. Opaque data structures are never written to or read from directly. + Instead, only the provided accessor functions are used. +8. If adaptor signatures are used, all partial signatures are verified. + +# Key Generation + +1. Generate a keypair with `secp256k1_keypair_create` and obtain the public key + with `secp256k1_keypair_pub`, and distribute it to each other participant to + be used as an authentication key and identifier. +2. The trusted dealer generate a VSS commitment and shares with + `secp256k1_frost_shares_gen`. The VSS commitment must be broadcast to all + participants. Assign each participant a share according to the order of + `ids33` and distribute the shares to the participants using a secure + channel. +3. After receiving a share and VSS commitment from the dealer, call + `secp256k1_frost_share_verify` to verify the share. +4. Compute the public verification shares for each participant by calling + `secp256k1_frost_compute_pubshare` with the public key of the participant. + This share is required by `secp256k1_frost_partial_sig_verify` to verify + partial signatures generated by `secp256k1_frost_partial_sign`, and public + shares are required by `secp256k1_frost_pubkey_gen` to generate the group + public key. +5. Generate the group key by passing the public shares of all participants to + `secp256k1_frost_pubkey_gen`, which will initialize a key generation + context. The context can be passed to `secp256k1_frost_pubkey_get` to obtain + the group public key. + +# Tweaking + +A (Taproot) tweak can be added to the resulting public key with +`secp256k1_xonly_pubkey_tweak_add`, after converting it to an xonly pubkey if +necessary with `secp256k1_xonly_pubkey_from_pubkey`. + +An ordinary tweak can be added to the resulting public key with +`secp256k1_ec_pubkey_tweak_add`, after converting it to an ordinary pubkey if +necessary with `secp256k1_frost_pubkey_get`. + +Tweaks can also be chained together by tweaking an already tweaked key. + +# Signing + +1. Initialize the key generation context with `secp256k1_frost_pubkey_gen`. +2. Optionally add a tweak by calling `secp256k1_frost_pubkey_tweak` and then + `secp256k1_frost_pubkey_xonly_tweak_add` for a Taproot tweak and + `secp256k1_frost_pubkey_ec_tweak_add` for an ordinary tweak. +3. Generate a pair of secret and public nonce with `secp256k1_frost_nonce_gen` + and send the public nonce to the other signers. +4. Process the aggregate nonce with `secp256k1_frost_nonce_process`. +5. Create a partial signature with `secp256k1_frost_partial_sign`. +6. Verify the partial signatures (optional in some scenarios) with + `secp256k1_frost_partial_sig_verify`. +7. Someone (not necessarily the signer) obtains all partial signatures and + aggregates them into the final Schnorr signature using + `secp256k1_frost_partial_sig_agg`. + +The aggregate signature can be verified with `secp256k1_schnorrsig_verify`. + +Note that steps 1 to 3 can happen before the message to be signed is known to +the signers. Therefore, the communication round to exchange nonces can be +viewed as a pre-processing step that is run whenever convenient to the signers. +This disables some of the defense-in-depth measures that may protect against +API misuse in some cases. Similarly, the API supports an alternative protocol +flow where generating the key (see Key Generation above) is allowed to happen +after exchanging nonces (step 3). + +# Verification + +A participant who wants to verify the partial signatures, but does not sign +itself may do so using the above instructions except that the verifier skips +steps 3 and 5.