diff --git a/crypto/frost/src/algorithm.rs b/crypto/frost/src/algorithm.rs index 12f48e52..ee8021f2 100644 --- a/crypto/frost/src/algorithm.rs +++ b/crypto/frost/src/algorithm.rs @@ -69,7 +69,7 @@ impl Transcript for IetfTranscript { type Challenge = Vec; fn new(_: &'static [u8]) -> IetfTranscript { - unimplemented!("IetfTranscript should not be used with multiple nonce protocols"); + IetfTranscript(vec![]) } fn domain_separate(&mut self, _: &[u8]) {} diff --git a/crypto/frost/src/sign.rs b/crypto/frost/src/sign.rs index eab8a035..4176819b 100644 --- a/crypto/frost/src/sign.rs +++ b/crypto/frost/src/sign.rs @@ -130,8 +130,7 @@ fn preprocess>( #[allow(non_snake_case)] struct Package { - B: HashMap>>, - binding: C::F, + B: HashMap>, C::F)>, Rs: Vec>, share: Vec } @@ -156,19 +155,16 @@ fn sign_with_share>( let transcript = params.algorithm.transcript(); // Domain separate FROST transcript.domain_separate(b"FROST"); - // Include the offset, if one exists - if let Some(offset) = params.keys.offset { - transcript.append_message(b"offset", offset.to_repr().as_ref()); - } } #[allow(non_snake_case)] let mut B = HashMap::::with_capacity(params.view.included.len()); - // Get the binding factor + // Get the binding factors let nonces = params.algorithm.nonces(); let mut addendums = HashMap::new(); - let binding = { + + { let transcript = params.algorithm.transcript(); // Parse the commitments for l in ¶ms.view.included { @@ -218,15 +214,34 @@ fn sign_with_share>( addendums.insert(*l, serialized[c ..].to_vec()); } - B.insert(*l, commitments); + B.insert(*l, (commitments, C::F::zero())); } - // Append the message to the transcript - transcript.append_message(b"message", &C::hash_msg(&msg)); + // Re-format into the FROST-expected rho transcript + let mut rho_transcript = A::Transcript::new(b"FROST_rho"); + rho_transcript.append_message(b"message", &C::hash_msg(&msg)); + rho_transcript.append_message( + b"commitments", + &C::hash_msg(transcript.challenge(b"commitments").as_ref()) + ); + // Include the offset, if one exists + // While this isn't part of the FROST-expected rho transcript, the offset being here coincides + // with another specification + if let Some(offset) = params.keys.offset { + rho_transcript.append_message(b"offset", offset.to_repr().as_ref()); + } - // Calculate the binding factor - C::hash_binding_factor(transcript.challenge(b"binding").as_ref()) - }; + // Generate the per-signer binding factors + for (l, commitments) in B.iter_mut() { + let mut rho_transcript = rho_transcript.clone(); + rho_transcript.append_message(b"participant", &l.to_be_bytes()); + commitments.1 = C::hash_binding_factor(rho_transcript.challenge(b"rho").as_ref()); + } + + // Merge the rho transcript back into the global one to ensure its advanced while committing to + // everything + transcript.append_message(b"rho_transcript", rho_transcript.challenge(b"merge").as_ref()); + } // Process the addendums for l in ¶ms.view.included { @@ -240,8 +255,8 @@ fn sign_with_share>( #[allow(non_snake_case)] for g in 0 .. nonces[n].len() { Rs[n][g] = { - B.values().map(|B| B[n][g][0]).sum::() + - (B.values().map(|B| B[n][g][1]).sum::() * binding) + B.values().map(|(B, _)| B[n][g][0]).sum::() + + B.values().map(|(B, binding)| B[n][g][1] * binding).sum::() }; } } @@ -250,12 +265,12 @@ fn sign_with_share>( ¶ms.view, &Rs, &our_preprocess.nonces.iter().map( - |nonces| nonces[0] + (nonces[1] * binding) + |nonces| nonces[0] + (nonces[1] * B[¶ms.keys.params.i()].1) ).collect::>(), msg ).to_repr().as_ref().to_vec(); - Ok((Package { B, binding, Rs, share: share.clone() }, share)) + Ok((Package { B, Rs, share: share.clone() }, share)) } fn complete>( @@ -287,9 +302,9 @@ fn complete>( for l in &sign_params.view.included { if !sign_params.algorithm.verify_share( sign_params.view.verification_share(*l), - &sign.B[l].iter().map( + &sign.B[l].0.iter().map( |nonces| nonces.iter().map( - |commitments| commitments[0] + (commitments[1] * sign.binding) + |commitments| commitments[0] + (commitments[1] * sign.B[l].1) ).collect() ).collect::>(), responses[l] diff --git a/crypto/frost/src/tests/literal/dalek.rs b/crypto/frost/src/tests/literal/dalek.rs index fdcc0c0f..3342efc4 100644 --- a/crypto/frost/src/tests/literal/dalek.rs +++ b/crypto/frost/src/tests/literal/dalek.rs @@ -21,20 +21,20 @@ fn ristretto_vectors() { included: &[1, 3], nonces: &[ [ - "b358743151e33d84bf00c12f71808f4103957c3e2cabab7b895c436b5e70f90c", - "7bd112153b9ae1ab9b31f5e78f61f5c4ca9ee67b7ea6d1181799c409d14c350c" + "eb0dc12ae7b746d36e3f2de46ce3833a05b9d4af5434eeb8cafaefda76906d00", + "491e91aa9df514ef598d5e0c7c5cdd088fbde4965b96069d546c0f04f1822b03" ], [ - "22acad88478e0d0373a991092a322ebd1b9a2dad90451a976d0db3215426af0e", - "9155e3d7bcf7cd468b980c7e20b2c77cbdfbe33a1dcae031fd8bc6b1403f4b04" + "abd12b8e6f255ee1e540eab029003a6e956567617720f61115f0941615892209", + "218e22625f93f262f025bd2d13c46ba722aa29fe585ceed66ff442d98fe4e509" ] ], sig_shares: &[ - "ff801b4e0839faa67f16dee4127b9f7fbcf5fd007900257b0e2bbc02cbe5e709", - "afdf5481023c855bf3411a5c8a5fafa92357296a078c3b80dc168f294cb4f504" + "efae3a83437fa8cd96194aacc56a7eb841630c280da99e7764a81d1340323306", + "96ddc4582e45eabce46f07b9e9375f8b49d35d1510fd34ac02b1e79d6100a602" ], - sig: "deae61af10e8ee48ba492573592fba547f5debeff6bd6e2024e8673584746f5e".to_owned() + - "ae6070cf0a757f027358f8409dda4e29e04c276b808c60fbea414b2c179add0e" + sig: "7ec584cef9a383afb43883b73bcaa6313afe878bd5fe75a608311b866a76ec67".to_owned() + + "858cffdb71c4928a7b895165afa2dd438b366a3d1da6d323675905b1a132d908" } ); } @@ -58,20 +58,20 @@ fn ed25519_vectors() { included: &[1, 3], nonces: &[ [ - "8c76af04340e83bb5fc427c117d38347fc8ef86d5397feea9aa6412d96c05b0a", - "14a37ddbeae8d9e9687369e5eb3c6d54f03dc19d76bb54fb5425131bc37a600b" + "d9aad97e1a1127bb87702ce8d81d8c07c7cbca89e784868d8e3876ff6b459700", + "5063be2774520d08a5ccd7f1213fb1179a5fa292bf13bc91cb28e7bd4d4a690c" ], [ - "5ca39ebab6874f5e7b5089f3521819a2aa1e2cf738bae6974ee80555de2ef70e", - "0afe3650c4815ff37becd3c6948066e906e929ea9b8f546c74e10002dbcc150c" + "86961f3a429ac0c5696f49e6d796817ff653f83c07f34e9e1f4d4c8c515b7900", + "72225ec11c1315d9f1ea0e78b1160ed95800fadd0191d23fd2f2c90ac96cb307" ] ], sig_shares: &[ - "4369474a398aa10357b60d683da91ea6a767dcf53fd541a8ed6b4d780827ea0a", - "32fcc690d926075e45d2dfb746bab71447943cddbefe80d122c39174aa2e1004" + "caae171b83bff0c2c6f56a1276892918ba228146f6344b85d2ec6efeb6f16d0d", + "ea6fdbf61683cf5f1f742e1b91583f0f667f0369efd2e33399b96d5a3ff0300d" ], - sig: "2b8d9c6995333c5990e3a3dd6568785539d3322f7f0376452487ea35cfda587b".to_owned() + - "75650edb12b1a8619c88ed1f8463d6baeefb18d3fed3c279102fdfecb255fa0e" + sig: "5da10008c13c04dd72328ba8e0f72b63cad43c3bf4b7eaada1c78225afbd977e".to_owned() + + "c74afdb47fdfadca0fcda18a28e8891220a284afe5072fb96ba6dc58f6e19e0a" } ); } diff --git a/crypto/frost/src/tests/literal/kp256.rs b/crypto/frost/src/tests/literal/kp256.rs index dee20157..f9640ce4 100644 --- a/crypto/frost/src/tests/literal/kp256.rs +++ b/crypto/frost/src/tests/literal/kp256.rs @@ -36,20 +36,20 @@ fn p256_vectors() { included: &[1, 3], nonces: &[ [ - "081617b24375e069b39f649d4c4ce2fba6e38b73e7c16759de0b6079a22c4c7e", - "4de5fb77d99f03a2491a83a6a4cb91ca3c82a3f34ce94cec939174f47c9f95dd" + "33a519cf070a166f9ef41a798d03423743f3e7d0b0efd5d0d963773c4c53205e", + "307d208d0c5728f323ae374f1ebd7f14a1a49b77d9d4bc1eab222218a17765ff" ], [ - "d186ea92593f83ea83181b184d41aa93493301ac2bc5b4b1767e94d2db943e38", - "486e2ee25a3fbc8e6399d748b077a2755fde99fa85cc24fa647ea4ebf5811a15" + "a614eadb972dc37b88aeceb6e899903f3104742d13f379a0e014541decbea4a4", + "e509791018504c5bb87edaf0f44761cc840888507c4cd80237971d78e65f70f2" ] ], sig_shares: &[ - "9e4d8865faf8c7b3193a3b35eda3d9e12118447114b1e7d5b4809ea28067f8a9", - "b7d094eab6305ae74daeed1acd31abba9ab81f638d38b72c132cb25a5dfae1fc" + "61e8b9c474df2e66ad19fd80a6e6cec1c6fe43c0a1cffd2d1c28299e93e1bbdb", + "9651d355ca1dea2557ba1f73e38a9f4ff1f1afc565323ef27f88a9d14df8370e" ], - sig: "0342c14c77f9d4ef9b8bd64fb0d7bbfdb9f8216a44e5f7bbe6ac0f3ed5e1a57367".to_owned() + - "561e1d51b129229966e92850bad5859bfee96926fad3007cd3f38639e1ffb554" + sig: "02dfba781e17b830229ae4ed22ebe402873683d9dfd945d01762217fb3172c2a7".to_owned() + + "1f83a8d1a3efd188c04d41cf48a716e11b8eff38607023c1f9bb0d36fe1d9f2e9" } ); }