Module frost

Source
Expand description

The FROST threshold multisignature scheme.

§Synopsis

use schnorr_fun::binonce::NonceKeyPair;
use schnorr_fun::fun::{s, poly};
use schnorr_fun::{
    frost::{self, chilldkg::simplepedpop},
    Message,
};
use std::collections::BTreeMap;
use rand_chacha::ChaCha20Rng;
use sha2::Sha256;

let frost = frost::new_with_deterministic_nonces::<Sha256>();

// This runs a 2-of-3 key generation on a single computer which means it's a trusted party.
// See the documentation/API of the protocols in `chilldkg` to see how to distrubute the key generation properly.
let (shared_key, secret_shares) = simplepedpop::simulate_keygen(&frost.schnorr, 2, 3,3, &mut rand::thread_rng());
let my_secret_share = secret_shares[0];
let my_index = my_secret_share.index();


// With signing we'll have at least one party be the "coordinator" (steps marked with 🐙)
// In this example we'll be the coordinator (but it doesn't have to be one of the signing parties)
let xonly_shared_key = shared_key.into_xonly(); // this is the key signatures will be valid under
let xonly_my_secret_share = my_secret_share.into_xonly();
let message =  Message::plain("my-app", b"chancellor on brink of second bailout for banks");
// Generate nonces for this signing session (and send them to coordinator somehow)
// ⚠ session_id MUST be different for every signing attempt to avoid nonce reuse (if using deterministic nonces).
let session_id = b"signing-ominous-message-about-banks-attempt-1".as_slice();
let mut nonce_rng: ChaCha20Rng = frost.seed_nonce_rng(my_secret_share, session_id);
let my_nonce = frost.gen_nonce(&mut nonce_rng);
// share your public nonce with the other signing participant(s) receive public nonces
// 🐙 the coordinator has received the nonces
let nonces = BTreeMap::from_iter([(my_index, my_nonce.public()), (party_index3, received_nonce3)]);
let coord_session = frost.coordinator_sign_session(&xonly_shared_key, nonces, message);
// Parties receive the agg_nonce from the coordiantor and the list of perties
let agg_binonce = coord_session.agg_binonce();
let parties = coord_session.parties();
// start a sign session with these nonces for a message
let sign_session = frost.party_sign_session(xonly_my_secret_share.public_key(),parties, agg_binonce, message);
// create a partial signature using our secret share and secret nonce
let my_sig_share = sign_session.sign(&xonly_my_secret_share, my_nonce);
// 🐙 receive the partial signature(s) from the other participant(s).
// 🐙 combine signature shares into a single signature that is valid under the FROST key
let combined_sig = coord_session.verify_and_combine_signature_shares(
    &xonly_shared_key,
    [(my_index, my_sig_share), (party_index3, sig_share3)].into()
)?;
assert!(frost.schnorr.verify(
    &xonly_shared_key.public_key(),
    message,
    &combined_sig
));

§Description

In FROST, multiple parties cooperatively generate a single joint public key (SharedKey) for creating Schnorr signatures. Unlike in musig, only some threshold t of the n signers are required to generate a signature under the key (rather than all n).

This implementation is not yet compatible with other existing FROST implementations (notably secp256k1-zkp).

The original scheme was introduced in FROST: Flexible Round-Optimized Schnorr Threshold Signatures. A more satisfying security proof was provided in Security of Multi- and Threshold Signatures. This implementation follows most closely Practical Schnorr Threshold Signatures Without the Algebraic Group Model.

⚠ CAUTION ⚠: We think that this follows the scheme in the “Practical” paper which is proven secure but we haven’t put a lot of effort into verifying this yet.

Re-exports§

pub use crate::binonce::Nonce;
pub use crate::binonce::NonceKeyPair;

Modules§

chilldkg
Our take on the WIP ChillDKG: Distributed Key Generation for FROST spec

Structs§

CoordinatorSignSession
A FROST signing session used to verify signatures.
Frost
The FROST context.
PairedSecretShare
A secret share paired with the image of the secret for which it is a share of.
PartySignSession
The session that is used to sign a message.
SecretShare
A Shamir secret share.
SharedKey
A polynomial where the first coefficient (constant term) is the image of a secret Scalar that has been shared in a Shamir’s secret sharing structure.
SignatureShareInvalid
Error for a signature share being invalid
VerificationShare
This is the public image of a SecretShare. You can’t sign with it but you can verify signature shares created by the secret share.

Enums§

BackupDecodeError
An error encountered when decoding a Frostsnap backup.
VerifySignatureSharesError
Error returned by CoordinatorSignSession::verify_and_combine_signature_shares

Functions§

new_with_deterministic_nonces
Constructor for a Frost instance using deterministic nonce generation.
new_with_synthetic_nonces
Constructor for a Frost instance using synthetic nonce generation.
new_without_nonce_generation
Create a Frost instance which does not handle nonce generation.

Type Aliases§

PartyIndex
The index of a party’s secret share.
SignatureShare
A Frost signature share.