1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//! FROST(Ed25519, SHA-512) threshold signatures — RFC 9591.
//!
//! A broker-based implementation providing keygen, signing, and resharing that
//! produce signatures verifiable by any standard Ed25519 verifier, plus BIP32
//! non-hardened derivation ([`derive_chain_code`]) and threshold key images
//! ([`KeyImageParty`]) — a distributed PRF on the shared secret, the building
//! block for hardened derivation.
//!
//! FROST is a Schnorr-based threshold scheme: keygen uses a Pedersen DKG
//! (RFC 9591 Appendix D) and signing uses two preprocessing+signing rounds with
//! a binding-factor mechanism that prevents nonce-reuse attacks.
//!
//! Keys produced here are **not** interchangeable with the GG18-style
//! `eddsatss` keys of the Go library: the DKG procedure differs and signatures
//! use FROST's binding-factor aggregation.
//!
//! # Broker contract
//!
//! All transport responsibilities are delegated to the [`crate::tss::MessageBroker`]
//! supplied by the caller. The broker MUST provide confidentiality on
//! per-recipient messages, authenticity on per-sender messages (peer
//! authentication is out of scope here), and reliable ordered delivery within
//! a single protocol instance. Round-2 DKG (keygen) shares are additionally
//! encrypted at the application layer (X25519 + ChaCha20-Poly1305).
//!
//! ## Resharing shares rely on broker confidentiality
//!
//! Unlike keygen, [`Resharing`] transmits each new party's secret sub-share in
//! **cleartext** (round 3), so its confidentiality depends *entirely* on the
//! broker's per-recipient confidentiality guarantee above — there is no
//! application-layer AEAD on the resharing path. An observer able to collect
//! `new_threshold + 1` sub-shares for a single old dealer recovers that dealer's
//! Lagrange-weighted share. This matches the Go `frosttss` resharing on the wire
//! (`frosttss/resharing.go`, `round3Old`), so it is a *symmetric* gap, not a Rust
//! divergence; the Go/Rust `frostristretto255tss` resharing is the outlier that
//! does wrap shares in the same AEAD envelope. Adding the envelope here would
//! change the round-3 wire format and break interop with the Go `frosttss`, so it
//! is deferred to a coordinated Go+Rust protocol-version bump. Until then, deploy
//! `frosttss` resharing only over a transport that actually enforces the
//! per-recipient confidentiality the broker contract requires.
//!
//! References:
//! - RFC 9591: <https://www.rfc-editor.org/rfc/rfc9591.html>
//! - FROST paper: <https://eprint.iacr.org/2020/852>
pub use ;
pub use ;
pub use Keygen;
pub use ;
pub use PointError;
pub use Resharing;
pub use SignatureData;
pub use Signing;
/// Errors raised by the `frosttss` protocols.