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