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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
//! 
//! [](https://docs.rs/givre)
//! [](https://crates.io/crates/givre)
//! [](https://discord.com/invite/hyperledger)
//! [](https://scorecard.dev/viewer/?uri=github.com/LFDT-Lockness/givre)
//!
//! # Threshold Schnorr implementation based on [FROST IETF Draft][draft]
//!
//! [FROST][draft] is state of art protocol for Threshold Schnorr Signatures that supports 1-round signing (requires
//! signers to [commit nonces](signing::round1) ahead of time), and identifiable abort.
//!
//! This crate provides:
//! * Distributed Key Generation (DKG) \
//! FROST does not define DKG protocol to be used. We simply re-export DKG based on [CGGMP21] implementation
//! when `cggmp24-keygen` feature is enabled, which is a fairly reasonable choice as it's proven to be UC-secure.
//! Alternatively, you can use any other UC-secure DKG protocol.
//! * FROST Signing \
//! We provide API for both manual signing execution (for better flexibility and efficiency) and interactive protocol
//! (for easier usability and fool-proof design), see [mod@signing] module for details.
//! * [Trusted dealer](trusted_dealer) (importing key into TSS)
//! * [reconstruct_secret_key](key_share::reconstruct_secret_key) (exporting key from TSS)
//!
//! This crate doesn't support (currently):
//! * Identifiable abort
//!
//! The crate is wasm and no_std friendly.
//!
//! # How to use the library
//!
//! ## Distributed Key Generation (DKG)
//! First of all, you need to generate a key. For that purpose, you can use any secure
//! (preferably, UC-secure) DKG protocol. FROST IETF Draft does not define any DKG
//! protocol or requirements it needs to meet, so the choice is up to you. This library
//! re-exports CGGMP21 DKG from [`cggmp24_keygen`] crate when `cggmp24-keygen` feature
//! is enabled which is proven to be UC-secure and should be a reasonable default.
//!
//! CGGMP21 DKG is an interactive protocol built on [`round_based`] framework. In order
//! to carry it out, you need to define the transport layer (i.e. how the signers can
//! communicate with each other). It's simply a pair of stream and sink:
//!
//! ```rust,ignore
//! let incoming: impl Stream<Item = Result<Incoming<Msg>>>;
//! let outgoing: impl Sink<Outgoing<Msg>>;
//! ```
//!
//! where:
//! * `Msg` is a protocol message (e.g., [`keygen::msg::threshold::Msg`])
//! * [`round_based::Incoming`] and [`round_based::Outgoing`] wrap `Msg` and provide additional data (e.g., sender/recipient)
//! * [`futures::Stream`] and [`futures::Sink`] are well-known async primitives.
//!
//! [`futures::Stream`]: https://docs.rs/futures/latest/futures/stream/trait.Stream.html
//! [`futures::sink`]: https://docs.rs/futures/latest/futures/sink/trait.Sink.html
//!
//! Transport layer implementation needs to meet requirements:
//! * All messages must be authenticated \
//! Whenever one party receives a message from another, the receiver should cryptographically
//! verify that the message comes from the claimed sender.
//! * All p2p messages must be encrypted \
//! Only the designated recipient should be able to read the message
//!
//! Then, construct an [MpcParty](round_based::MpcParty):
//! ```rust
//! # type Msg = givre::keygen::msg::threshold::Msg<givre::generic_ec::curves::Secp256k1, givre::keygen::security_level::SecurityLevel128, sha2::Sha256>;
//! # let incoming = futures::stream::pending::<Result<round_based::Incoming<Msg>, std::convert::Infallible>>();
//! # let outgoing = futures::sink::drain::<round_based::Outgoing<Msg>>();
//! let delivery = (incoming, outgoing);
//! let party = round_based::MpcParty::connected(delivery);
//! ```
//!
//! Now, you can finally execute the DKG protocol. The protocol involves all signers
//! who will co-share a key. All signers need to agree on some basic parameters including
//! the participants’ indices, the execution ID, and the threshold value (i.e., t).
//! ```rust,no_run
//! use givre::ciphersuite::{Ciphersuite, Secp256k1};
//!
//! # async fn doc() -> Result<(), givre::keygen::KeygenError> {
//! # type Msg = givre::keygen::msg::threshold::Msg<<Secp256k1 as Ciphersuite>::Curve, givre::keygen::security_level::SecurityLevel128, sha2::Sha256>;
//! # let incoming = futures::stream::pending::<Result<round_based::Incoming<Msg>, std::convert::Infallible>>();
//! # let outgoing = futures::sink::drain::<round_based::Outgoing<Msg>>();
//! # let delivery = (incoming, outgoing);
//! # let party = round_based::MpcParty::connected(delivery);
//! #
//! # use rand_core::OsRng;
//! #
//! let eid = givre::keygen::ExecutionId::new(b"execution id, unique per protocol execution");
//! let i = /* signer index (0 <= i < n) */
//! # 0;
//! let n = /* number of signers taking part in key generation */
//! # 3;
//! let t = /* threshold */
//! # 2;
//!
//! let key_share = givre::keygen::<<Secp256k1 as Ciphersuite>::Curve>(eid, i, n)
//! .set_threshold(t)
//! .start(&mut OsRng, party)
//! .await?;
//! # Ok(()) }
//! ```
//!
//! ## Signing
//! FROST signing can be carried out either interactively with the help of [`round_based`]
//! framework, or manually.
//!
//! ### Manual Signing
//! In the manual signing, as the name suggests, you manually construct all messages
//! and drive the protocol. It gives you better control over protocol execution and
//! you can benefit from better performance (e.g. by having 1 round signing). However,
//! it also gives a greater chance of misusing the protocol and violating security.
//! When opting for manual signing, make sure you're familiar with the [FROST IETF Draft][draft].
//! Refer to [mod@signing] module docs for the instructions.
//!
//! ### Interactive Signing (requires `full-signing` feature)
//! Interactive Signing has more user-friendly interface and harder-to-misuse design.
//! It works on top of [`round_based`] framework similarly to DKG described above.
//! As before, you need to define a secure transport layer and construct [MpcParty](round_based::MpcParty).
//! Then, you need to assign each signer a unique index, in range from 0 to t-1. The
//! signers also need to know which index each of them occupied at the time of keygen.
//!
//! ```rust,no_run
//! use givre::ciphersuite::Secp256k1;
//!
//! # async fn doc() -> Result<(), givre::signing::full_signing::FullSigningError> {
//! # type Msg = givre::signing::full_signing::Msg<<Secp256k1 as givre::Ciphersuite>::Curve>;
//! # let incoming = futures::stream::pending::<Result<round_based::Incoming<Msg>, std::convert::Infallible>>();
//! # let outgoing = futures::sink::drain::<round_based::Outgoing<Msg>>();
//! # let delivery = (incoming, outgoing);
//! # let party = round_based::MpcParty::connected(delivery);
//! #
//! # use rand_core::OsRng;
//! # const MIN_SIGNERS: usize = 3;
//! #
//! #
//! let i = /* signer index (0 <= i < min_signers) */
//! # 0;
//! let parties_indexes_at_keygen: [u16; MIN_SIGNERS] =
//! /* parties_indexes_at_keygen[i] is the index the i-th party had at keygen */
//! # [0, 1, 2];
//! let key_share = /* key share */
//! # {let s: givre::KeyShare<<Secp256k1 as givre::Ciphersuite>::Curve> = unimplemented!(); s};
//!
//! let data_to_sign = b"data to be signed";
//!
//! let signature = givre::signing::<Secp256k1>(i, &key_share, &parties_indexes_at_keygen, data_to_sign)
//! .sign(&mut OsRng, party)
//! .await?;
//! # Ok(()) }
//! ```
//! ## Signer indices
//! We use indices to uniquely refer to particular signers sharing a key. Each
//! index `i` is an unsigned integer `u16` with `0 ≤ i < n` where `n` is the
//! total number of participants in the protocol.
//!
//! All signers should have the same view about each others’ indices. For instance,
//! if Signer A holds index 2, then all other signers must agree that i=2 corresponds
//! to Signer A.
//!
//! Assuming some sort of PKI (which would anyway likely be used to ensure secure
//! communication, as described above), each signer has a public key that uniquely
//! identifies that signer. It is then possible to assign unique indices to the signers
//! by lexicographically sorting the signers’ public keys, and letting the index of a
//! signer be the position of that signer’s public key in the sorted list.
//!
//! # Webassembly and `no_std` support
//! This crate is compatible with `wasm32-unknown-unknown` target and `no_std`. Requires
//! disabling `std` feature which is on by default.
//!
//! [CGGMP21]: https://github.com/dfns/cggmp21
//! [draft]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-15.html
//!
//! # Join us in Discord!
//! Feel free to reach out to us [in Discord](https://discord.com/invite/hyperledger)!
extern crate std;
extern crate alloc;
pub use generic_ec;
pub use hd_wallet;
pub use round_based;
/// Key share
///
/// This module re-exports type definitions from [`key_share`] crate.
/// Distributed Key Generation (DKG) protocol based on CGGMP21 paper
///
/// CGGMP21 DKG protocol is proven to be UC-secure, which means that it can safely be composed with
/// other protocols such as FROST signing. CGGMP21 implementation is audited and heavily used
/// in production, so it should be a reasonably secure DKG implementation.
///
/// This module just re-exports [`cggmp24_keygen`] crate when `cggmp24-keygen` feature is enabled.
pub use keygen;
/// Trusted dealer
///
/// Trusted dealer can be used to generate key shares in one place. Note
/// that in creates SPOF/T (single point of failure/trust). Trusted
/// dealer is mainly intended to be used in tests, but also could be used
/// to import a key into TSS.
///
/// ## Example
/// Import a key into 3-out-of-5 TSS:
/// ```rust,no_run
/// # use rand_core::OsRng;
/// # let mut rng = OsRng;
/// use givre::generic_ec::{curves::Secp256k1, SecretScalar, NonZero};
///
/// let secret_key_to_be_imported = NonZero::<SecretScalar<Secp256k1>>::random(&mut rng);
///
/// let key_shares = givre::trusted_dealer::builder::<Secp256k1>(5)
/// .set_threshold(Some(3))
/// .set_shared_secret_key(secret_key_to_be_imported)
/// .generate_shares(&mut rng)?;
/// # Ok::<_, key_share::trusted_dealer::TrustedDealerError>(())
/// ```
pub use ;
/// Signer index
pub type SignerIndex = u16;
/// Interactive Signing
///
/// Can be used to carry out the full signing protocol in which each signer commits nonces,
/// produces a signature share and, optionally, aggregates all signature shares into the
/// final signature.
///
/// This can be less efficient than doing signing manually, when you can commit nonces before
/// a message to be signed is known, but more secure, as using this function ensures that
/// protocol isn't misused (e.g. that nonce is never reused).
///
/// ## Inputs
/// * Signer index in *signing protocol* $0 \le i < \\text{min\\_signers}$
/// * Signer secret key share
/// * List of signer that participate in the signing, must have exactly threshold amount of signers \
/// `signers[j]` is index which j-th signer occupied at keygen
/// * `msg` to be signed
///
/// ## Example
/// ```rust,no_run
/// use givre::round_based;
/// use givre::ciphersuite::Secp256k1;
/// #
/// # fn retrieve_key_share() -> givre::KeyShare<<Secp256k1 as givre::Ciphersuite>::Curve> { unimplemented!() }
/// # fn join_network<M>() -> (u16, impl round_based::Delivery<M>) {
/// # (0, (futures::stream::pending::<Result<_, std::convert::Infallible>>(), futures::sink::drain()))
/// # }
/// # async fn __doc() -> Result<(), givre::signing::full_signing::FullSigningError> {
///
/// let key_share = retrieve_key_share();
/// let (i, delivery) = join_network();
/// let signers = [0, 1, 2];
/// let msg = b"Hello, TSS World!";
///
/// let party = round_based::MpcParty::connected(delivery);
/// let sig = givre::signing::<Secp256k1>(i, &key_share, &signers, msg)
/// .sign(&mut rand_core::OsRng, party)
/// .await?;
/// # Ok(()) }
/// ```