UltrafastSecp256k1 3.50.0
Ultra high-performance secp256k1 elliptic curve cryptography library
Loading...
Searching...
No Matches
frost.hpp
Go to the documentation of this file.
1#ifndef SECP256K1_FROST_HPP
2#define SECP256K1_FROST_HPP
3#pragma once
4
5// ============================================================================
6// FROST Threshold Signatures for secp256k1
7// ============================================================================
8// Flexible Round-Optimized Schnorr Threshold signatures (FROST)
9// t-of-n distributed key generation and signing.
10//
11// Protocol overview:
12// 1. KeyGen (DKG): Each participant generates a polynomial commitment
13// and secret shares. Participants exchange commitments and shares
14// to derive the group public key and individual signing shares.
15// 2. Signing Round 1: Each signer generates nonce commitments (D_i, E_i)
16// 3. Signing Round 2: Each signer produces a partial signature s_i
17// 4. Aggregation: Coordinator combines partial signatures into final sig
18//
19// The final signature is a standard BIP-340 Schnorr signature,
20// verifiable with schnorr_verify().
21//
22// Reference: https://eprint.iacr.org/2020/852
23// ============================================================================
24
25#include <array>
26#include <cstdint>
27#include <cstddef>
28#include <vector>
29#include <utility>
30#include "secp256k1/scalar.hpp"
31#include "secp256k1/point.hpp"
32#include "secp256k1/schnorr.hpp"
33
34namespace secp256k1 {
35
36// -- Types --------------------------------------------------------------------
37
38// Participant index (1-based, as per Shamir's secret sharing)
39using ParticipantId = std::uint32_t;
40
41// Secret share for a participant
42struct FrostShare {
43 ParticipantId from; // Who generated this share
44 ParticipantId id; // Participant index (target, 1..n)
45 fast::Scalar value; // The share value f_from(id)
46};
47
48// Public polynomial commitment (Feldman VSS)
50 ParticipantId from; // Who generated this
51 std::vector<fast::Point> coeffs; // A_0 = s_i*G, A_1 = a_1*G, ...
52};
53
54// A participant's long-lived key material after DKG
56 ParticipantId id; // This participant's index
57 fast::Scalar signing_share; // Private signing share
58 fast::Point verification_share; // Public verification share (Y_i)
59 fast::Point group_public_key; // Group public key (Y)
60 std::uint32_t threshold; // t (minimum signers)
61 std::uint32_t num_participants; // n (total participants)
62};
63
64// Nonce pair for a signing round
65struct FrostNonce {
66 fast::Scalar hiding_nonce; // d_i (secret)
67 fast::Scalar binding_nonce; // e_i (secret)
68};
69
70// Public nonce commitment
76
77// Partial signature from one signer
80 fast::Scalar z_i; // Partial signature scalar
81};
82
83// -- DKG (Distributed Key Generation) -----------------------------------------
84
85// Round 1: Generate secret polynomial and commitment
86// Returns: (commitment to broadcast, shares to send privately)
87// participant_id: this participant's 1-based index
88// threshold: minimum signers required (t)
89// num_participants: total participants (n)
90std::pair<FrostCommitment, std::vector<FrostShare>>
92 std::uint32_t threshold,
93 std::uint32_t num_participants,
94 const std::array<std::uint8_t, 32>& secret_seed);
95
96// Round 2: Verify received commitments and shares, compute signing key
97// commitments: all participants' polynomial commitments (including own)
98// received_shares: shares received from other participants (one per participant)
99// own_share: this participant's share of their own polynomial
100// Returns: {key_package, success}
101std::pair<FrostKeyPackage, bool>
103 const std::vector<FrostCommitment>& commitments,
104 const std::vector<FrostShare>& received_shares,
105 std::uint32_t threshold,
106 std::uint32_t num_participants);
107
108// -- Signing ------------------------------------------------------------------
109
110// Generate nonces for a signing round
111// Returns: (secret nonce pair, public commitment)
112std::pair<FrostNonce, FrostNonceCommitment>
114 const std::array<std::uint8_t, 32>& nonce_seed);
115
116// Compute partial signature
117// key_pkg: this signer's key package
118// nonce: this signer's secret nonce — CONSUMED (both scalars are zeroized
119// before this function returns to enforce single-use)
120// msg: 32-byte message to sign
121// nonce_commitments: all participating signers' nonce commitments
124 FrostNonce& nonce,
125 const std::array<std::uint8_t, 32>& msg,
126 const std::vector<FrostNonceCommitment>& nonce_commitments);
127
128// Verify a partial signature (optional, for robustness)
129bool frost_verify_partial(const FrostPartialSig& partial_sig,
130 const FrostNonceCommitment& signer_commitment,
131 const fast::Point& verification_share,
132 const std::array<std::uint8_t, 32>& msg,
133 const std::vector<FrostNonceCommitment>& nonce_commitments,
134 const fast::Point& group_public_key);
135
136// Aggregate partial signatures into final Schnorr signature
137// The result is a standard BIP-340 Schnorr signature
139frost_aggregate(const std::vector<FrostPartialSig>& partial_sigs,
140 const std::vector<FrostNonceCommitment>& nonce_commitments,
141 const fast::Point& group_public_key,
142 const std::array<std::uint8_t, 32>& msg);
143
144// -- Lagrange Coefficients ----------------------------------------------------
145
146// Compute Lagrange coefficient lambda_i for participant i in signer set S
147// lambda_i = Pi_{jinS, j!=i} (j / (j - i)) mod n
149 const std::vector<ParticipantId>& signer_ids);
150
151} // namespace secp256k1
152
153#endif // SECP256K1_FROST_HPP
SchnorrSignature frost_aggregate(const std::vector< FrostPartialSig > &partial_sigs, const std::vector< FrostNonceCommitment > &nonce_commitments, const fast::Point &group_public_key, const std::array< std::uint8_t, 32 > &msg)
std::pair< FrostKeyPackage, bool > frost_keygen_finalize(ParticipantId participant_id, const std::vector< FrostCommitment > &commitments, const std::vector< FrostShare > &received_shares, std::uint32_t threshold, std::uint32_t num_participants)
std::uint32_t ParticipantId
Definition frost.hpp:39
bool frost_verify_partial(const FrostPartialSig &partial_sig, const FrostNonceCommitment &signer_commitment, const fast::Point &verification_share, const std::array< std::uint8_t, 32 > &msg, const std::vector< FrostNonceCommitment > &nonce_commitments, const fast::Point &group_public_key)
fast::Scalar frost_lagrange_coefficient(ParticipantId i, const std::vector< ParticipantId > &signer_ids)
std::pair< FrostCommitment, std::vector< FrostShare > > frost_keygen_begin(ParticipantId participant_id, std::uint32_t threshold, std::uint32_t num_participants, const std::array< std::uint8_t, 32 > &secret_seed)
std::pair< FrostNonce, FrostNonceCommitment > frost_sign_nonce_gen(ParticipantId participant_id, const std::array< std::uint8_t, 32 > &nonce_seed)
FrostPartialSig frost_sign(const FrostKeyPackage &key_pkg, FrostNonce &nonce, const std::array< std::uint8_t, 32 > &msg, const std::vector< FrostNonceCommitment > &nonce_commitments)
std::vector< fast::Point > coeffs
Definition frost.hpp:51
std::uint32_t threshold
Definition frost.hpp:60
fast::Point verification_share
Definition frost.hpp:58
std::uint32_t num_participants
Definition frost.hpp:61
fast::Scalar signing_share
Definition frost.hpp:57
fast::Point group_public_key
Definition frost.hpp:59
fast::Scalar binding_nonce
Definition frost.hpp:67
fast::Scalar hiding_nonce
Definition frost.hpp:66
ParticipantId id
Definition frost.hpp:44
ParticipantId from
Definition frost.hpp:43
fast::Scalar value
Definition frost.hpp:45