From 9f0790fb831cbf2751e06d9281ef9c06e9c09743 Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Mon, 13 Nov 2023 05:11:40 -0500 Subject: [PATCH] Remove RecommendedTranscript from DKG MuSig Resolves #391. Given this code already wasn't modular/composable, this should be overall equivalent regarding functionality and security. It's much less opinionated though and has fewer dependencies. --- crypto/dkg/src/musig.rs | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/crypto/dkg/src/musig.rs b/crypto/dkg/src/musig.rs index 4b115328..b4c57537 100644 --- a/crypto/dkg/src/musig.rs +++ b/crypto/dkg/src/musig.rs @@ -7,8 +7,6 @@ use std_shims::collections::HashMap; #[cfg(feature = "std")] use zeroize::Zeroizing; -use transcript::{Transcript, RecommendedTranscript}; - #[cfg(feature = "std")] use ciphersuite::group::ff::Field; use ciphersuite::{ @@ -37,31 +35,36 @@ fn check_keys(keys: &[C::G]) -> Result> { Ok(keys_len) } +// This function panics if called with keys whose length exceed 2**16. +// This is fine since it's internal and all calls occur after calling check_keys, which does check +// the keys' length. fn binding_factor_transcript( context: &[u8], keys: &[C::G], -) -> RecommendedTranscript { - let mut transcript = RecommendedTranscript::new(b"DKG MuSig v0.5"); - transcript.append_message(b"context", context); - transcript.domain_separate(b"keys"); +) -> Result, DkgError<()>> { + let mut transcript = vec![]; + transcript.push(u8::try_from(context.len()).map_err(|_| DkgError::InvalidSigningSet)?); + transcript.extend(context); + transcript.extend(u16::try_from(keys.len()).unwrap().to_le_bytes()); for key in keys { - transcript.append_message(b"key", key.to_bytes()); + transcript.extend(key.to_bytes().as_ref()); } - transcript + Ok(transcript) } -fn binding_factor(mut transcript: RecommendedTranscript, i: u16) -> C::F { - transcript.domain_separate(b"participant"); - transcript.append_message(b"participant", i.to_le_bytes()); - C::hash_to_F(b"DKG-MuSig-binding_factor", &transcript.challenge(b"binding_factor")) +fn binding_factor(mut transcript: Vec, i: u16) -> C::F { + transcript.extend(i.to_le_bytes()); + C::hash_to_F(b"musig", &transcript) } /// The group key resulting from using this library's MuSig key gen. /// -/// Creating an aggregate key with a list containing duplicated public keys returns an error. +/// This function will return an error if the context is longer than 255 bytes. +/// +/// Creating an aggregate key with a list containing duplicated public keys will return an error. pub fn musig_key(context: &[u8], keys: &[C::G]) -> Result> { let keys_len = check_keys::(keys)?; - let transcript = binding_factor_transcript::(context, keys); + let transcript = binding_factor_transcript::(context, keys)?; let mut res = C::G::identity(); for i in 1 ..= keys_len { res += keys[usize::from(i - 1)] * binding_factor::(transcript.clone(), i); @@ -95,7 +98,7 @@ pub fn musig( )?; // Calculate the binding factor per-key - let transcript = binding_factor_transcript::(context, keys); + let transcript = binding_factor_transcript::(context, keys)?; let mut binding = Vec::with_capacity(keys.len()); for i in 1 ..= keys_len { binding.push(binding_factor::(transcript.clone(), i));