Module schnorr_fun::musig

source ·
Expand description

The MuSig2 multisignature scheme.

§Synopsis

use rand_chacha::ChaCha20Rng;
use schnorr_fun::{musig, nonce::Deterministic, Message, Schnorr};
use sha2::Sha256;
// use sha256 with deterministic nonce generation -- be careful!
let musig = musig::new_with_deterministic_nonces::<sha2::Sha256>();
// use synthetic nonces with randomness from ThredRng -- harder to make a mistake.
let musig = musig::new_with_synthetic_nonces::<sha2::Sha256, rand::rngs::ThreadRng>();
// create a keypair
use schnorr_fun::fun::Scalar;
let my_keypair = musig.new_keypair(Scalar::random(&mut rand::thread_rng()));
let public_key1 = my_keypair.public_key();
// recieve the public keys of all other participants to form the aggregate key.
let agg_key = musig
    .new_agg_key(vec![public_key1, public_key2, public_key3])
    .into_xonly_key();

// create a unique nonce, and send the public nonce to other parties.
// ⚠ session_id must be different for every signing attempt
let session_id = b"signing-ominous-message-about-banks-attempt-1".as_slice();
let mut nonce_rng: ChaCha20Rng =
    musig.seed_nonce_rng(&agg_key, &my_keypair.secret_key(), session_id);
let my_nonce = musig.gen_nonce(&mut nonce_rng);
let my_public_nonce = my_nonce.public();
// collect the public nonces from the other two parties
let nonces = vec![my_public_nonce, p2_public_nonce, p3_public_nonce];
let message = Message::plain("my-app", b"chancellor on brink of second bailout for banks");
// start the signing session
let session = musig.start_sign_session(&agg_key, nonces, message);
// sign with our single local keypair
let my_sig = musig.sign(&agg_key, &session, 0, &my_keypair, my_nonce);
// receive p2_sig and p3_sig from somewhere and check they're valid
assert!(musig.verify_partial_signature(&agg_key, &session, 1, p2_sig));
assert!(musig.verify_partial_signature(&agg_key, &session, 2, p3_sig));
// combine them with ours into the final signature
let sig = musig.combine_partial_signatures(&agg_key, &session, [my_sig, p2_sig, p3_sig]);
// check it's a valid normal Schnorr signature
musig
    .schnorr
    .verify(&agg_key.agg_public_key(), message, &sig);

§Description

The MuSig2 multisignature scheme lets you aggregate multiple public keys into a single public key that requires all of the corresponding secret keys to authorize a signature under the aggregate key.

See the excellent paper for the abstract details of the protocol and security proofs. ⚠ THIS IS EXPERIMENTAL⚠ it is currently compatible with this version of the specification.

⚠ THIS IS EXPERIMENTAL⚠ it is currently compatible with this PR to the specification. However, we go “off-spec” in a few places especially with regards to nonce generation where we provide our own APIs (that at the time of writing are subject to change).

Re-exports§

Structs§

  • Marks the SignSession as being used to create an adaptor (a.k.a. one-time encrypted) signature.
  • A list of keys aggregated into a single key.
  • The MuSig context.
  • Marker type for indicating the SignSession is being used to create an ordinary Schnorr signature.
  • A signing session.

Functions§