diff --git a/README.md b/README.md index 76bc0e10..f7b3b046 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 13c5c3e1..f6764fa7 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 00000000..c9bfa134 --- /dev/null +++ b/src/modules/frost/frost.md @@ -0,0 +1,95 @@ +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. Each participant establishes a secure communications channel with each other + participant and uses that channel to transmit shares and commitments 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 x-only + public key with `secp256k1_keypair_xonly_pub`, and distribute it to each + other participant to be used as an authentication key and identifier. +2. Generate a VSS commitment, proof-of-knowledge, and shares with + `secp256k1_frost_shares_gen`. The VSS commitment and proof-of-knowledge 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 commitment set from each participant, call + `secp256k1_frost_share_agg` to compute the aggregate share, group public + key, and VSS hash. If this function returns an error, + `secp256k1_frost_share_verify` is called on each share to determine which + participants submitted faulty shares. +4. Optionally compute the public verification share by calling + `secp256k1_frost_compute_pubshare` with the x-only public key of each + participant. This share is required by `secp256k1_frost_partial_sig_verify` + to verify partial signatures generated by `secp256k1_frost_partial_sign`. + +# 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. 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. +2. Generate a pair of secret and public nonce with `secp256k1_frost_nonce_gen` + and send the public nonce to the other signers. +3. Process the aggregate nonce with `secp256k1_frost_nonce_process`. +4. Create a partial signature with `secp256k1_frost_partial_sign`. +5. Verify the partial signatures (optional in some scenarios) with + `secp256k1_frost_partial_sig_verify`. +6. 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 2). + +# 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 2 and 4.