|
| 1 | +Notes on the frost module API |
| 2 | +=========================== |
| 3 | + |
| 4 | +The following sections contain additional notes on the API of the frost module |
| 5 | +(`include/secp256k1_frost.h`). A usage example can be found in |
| 6 | +`examples/frost.c`. |
| 7 | + |
| 8 | +# API misuse |
| 9 | + |
| 10 | +Users of the frost module must take great care to make sure of the following: |
| 11 | + |
| 12 | +1. Each participant exchanges public keys for identification and authentication |
| 13 | + purposes. Partipants must provide the same public key to each other |
| 14 | + participant. |
| 15 | +2. Each participant establishes a secure communications channel with each other |
| 16 | + participant and uses that channel to transmit shares and commitments during |
| 17 | + key generation. |
| 18 | +3. A unique set of coefficients per key generation session is generated in |
| 19 | + `secp256k1_frost_shares_gen`. See the corresponding comment in |
| 20 | + `include/secp256k1_frost.h` for how to ensure that. |
| 21 | +4. The `pubnonces` provided to `secp256k1_frost_nonce_process` are sorted by |
| 22 | + the corresponding lexicographic ordering of the x-only pubkey of each |
| 23 | + participant, and the `ids33` provided to `secp256k1_frost_nonce_process` |
| 24 | + are sorted lexicographically. |
| 25 | +5. A unique nonce per signing session is generated in `secp256k1_frost_nonce_gen`. |
| 26 | + See the corresponding comment in `include/secp256k1_frost.h` for how to ensure that. |
| 27 | +6. The `secp256k1_frost_secnonce` structure is never copied or serialized. |
| 28 | + See also the comment on `secp256k1_frost_secnonce` in `include/secp256k1_frost.h`. |
| 29 | +7. Opaque data structures are never written to or read from directly. |
| 30 | + Instead, only the provided accessor functions are used. |
| 31 | +8. If adaptor signatures are used, all partial signatures are verified. |
| 32 | + |
| 33 | +# Key Generation |
| 34 | + |
| 35 | +1. Generate a keypair with `secp256k1_keypair_create` and obtain the x-only |
| 36 | + public key with `secp256k1_keypair_xonly_pub`, and distribute it to each |
| 37 | + other participant to be used as an authentication key and identifier. |
| 38 | +2. Generate a VSS commitment, proof-of-knowledge, and shares with |
| 39 | + `secp256k1_frost_shares_gen`. The VSS commitment and proof-of-knowledge must |
| 40 | + be broadcast to all participants. Assign each participant a share according |
| 41 | + to the order of `ids33` and distribute the shares to the participants using |
| 42 | + a secure channel. |
| 43 | +3. After receiving a share and commitment set from each participant, call |
| 44 | + `secp256k1_frost_share_agg` to compute the aggregate share, group public |
| 45 | + key, and VSS hash. If this function returns an error, |
| 46 | + `secp256k1_frost_share_verify` is called on each share to determine which |
| 47 | + participants submitted faulty shares. |
| 48 | +4. Optionally compute the public verification share by calling |
| 49 | + `secp256k1_frost_compute_pubshare` with the x-only public key of each |
| 50 | + participant. This share is required by `secp256k1_frost_partial_sig_verify` |
| 51 | + to verify partial signatures generated by `secp256k1_frost_partial_sign`. |
| 52 | + |
| 53 | +# Tweaking |
| 54 | + |
| 55 | + |
| 56 | +A (Taproot) tweak can be added to the resulting public key with |
| 57 | +`secp256k1_xonly_pubkey_tweak_add`, after converting it to an xonly pubkey if |
| 58 | +necessary with `secp256k1_xonly_pubkey_from_pubkey`. |
| 59 | + |
| 60 | +An ordinary tweak can be added to the resulting public key with |
| 61 | +`secp256k1_ec_pubkey_tweak_add`, after converting it to an ordinary pubkey if |
| 62 | +necessary with `secp256k1_frost_pubkey_get`. |
| 63 | + |
| 64 | +Tweaks can also be chained together by tweaking an already tweaked key. |
| 65 | + |
| 66 | +# Signing |
| 67 | + |
| 68 | +1. Optionally add a tweak by calling `secp256k1_frost_pubkey_tweak` and then |
| 69 | + `secp256k1_frost_pubkey_xonly_tweak_add` for a Taproot tweak and |
| 70 | + `secp256k1_frost_pubkey_ec_tweak_add` for an ordinary tweak. |
| 71 | +2. Generate a pair of secret and public nonce with `secp256k1_frost_nonce_gen` |
| 72 | + and send the public nonce to the other signers. |
| 73 | +3. Process the aggregate nonce with `secp256k1_frost_nonce_process`. |
| 74 | +4. Create a partial signature with `secp256k1_frost_partial_sign`. |
| 75 | +5. Verify the partial signatures (optional in some scenarios) with |
| 76 | + `secp256k1_frost_partial_sig_verify`. |
| 77 | +6. Someone (not necessarily the signer) obtains all partial signatures and |
| 78 | + aggregates them into the final Schnorr signature using |
| 79 | + `secp256k1_frost_partial_sig_agg`. |
| 80 | + |
| 81 | +The aggregate signature can be verified with `secp256k1_schnorrsig_verify`. |
| 82 | + |
| 83 | +Note that steps 1 to 3 can happen before the message to be signed is known to |
| 84 | +the signers. Therefore, the communication round to exchange nonces can be |
| 85 | +viewed as a pre-processing step that is run whenever convenient to the signers. |
| 86 | +This disables some of the defense-in-depth measures that may protect against |
| 87 | +API misuse in some cases. Similarly, the API supports an alternative protocol |
| 88 | +flow where generating the key (see Key Generation above) is allowed to happen |
| 89 | +after exchanging nonces (step 2). |
| 90 | + |
| 91 | +# Verification |
| 92 | + |
| 93 | +A participant who wants to verify the partial signatures, but does not sign |
| 94 | +itself may do so using the above instructions except that the verifier skips |
| 95 | +steps 2 and 4. |
0 commit comments