Update to FROST v7

This commit is contained in:
Luke Parker 2022-07-12 02:45:18 -04:00
parent 5eb61f3a87
commit 94f380f857
No known key found for this signature in database
GPG key ID: F9F1386DB1E119B6
4 changed files with 60 additions and 45 deletions

View file

@ -69,7 +69,7 @@ impl Transcript for IetfTranscript {
type Challenge = Vec<u8>; type Challenge = Vec<u8>;
fn new(_: &'static [u8]) -> IetfTranscript { fn new(_: &'static [u8]) -> IetfTranscript {
unimplemented!("IetfTranscript should not be used with multiple nonce protocols"); IetfTranscript(vec![])
} }
fn domain_separate(&mut self, _: &[u8]) {} fn domain_separate(&mut self, _: &[u8]) {}

View file

@ -130,8 +130,7 @@ fn preprocess<R: RngCore + CryptoRng, C: Curve, A: Algorithm<C>>(
#[allow(non_snake_case)] #[allow(non_snake_case)]
struct Package<C: Curve> { struct Package<C: Curve> {
B: HashMap<u16, Vec<Vec<[C::G; 2]>>>, B: HashMap<u16, (Vec<Vec<[C::G; 2]>>, C::F)>,
binding: C::F,
Rs: Vec<Vec<C::G>>, Rs: Vec<Vec<C::G>>,
share: Vec<u8> share: Vec<u8>
} }
@ -156,19 +155,16 @@ fn sign_with_share<C: Curve, A: Algorithm<C>>(
let transcript = params.algorithm.transcript(); let transcript = params.algorithm.transcript();
// Domain separate FROST // Domain separate FROST
transcript.domain_separate(b"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)] #[allow(non_snake_case)]
let mut B = HashMap::<u16, _>::with_capacity(params.view.included.len()); let mut B = HashMap::<u16, _>::with_capacity(params.view.included.len());
// Get the binding factor // Get the binding factors
let nonces = params.algorithm.nonces(); let nonces = params.algorithm.nonces();
let mut addendums = HashMap::new(); let mut addendums = HashMap::new();
let binding = {
{
let transcript = params.algorithm.transcript(); let transcript = params.algorithm.transcript();
// Parse the commitments // Parse the commitments
for l in &params.view.included { for l in &params.view.included {
@ -218,15 +214,34 @@ fn sign_with_share<C: Curve, A: Algorithm<C>>(
addendums.insert(*l, serialized[c ..].to_vec()); addendums.insert(*l, serialized[c ..].to_vec());
} }
B.insert(*l, commitments); B.insert(*l, (commitments, C::F::zero()));
} }
// Append the message to the transcript // Re-format into the FROST-expected rho transcript
transcript.append_message(b"message", &C::hash_msg(&msg)); 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 // Generate the per-signer binding factors
C::hash_binding_factor(transcript.challenge(b"binding").as_ref()) 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 // Process the addendums
for l in &params.view.included { for l in &params.view.included {
@ -240,8 +255,8 @@ fn sign_with_share<C: Curve, A: Algorithm<C>>(
#[allow(non_snake_case)] #[allow(non_snake_case)]
for g in 0 .. nonces[n].len() { for g in 0 .. nonces[n].len() {
Rs[n][g] = { Rs[n][g] = {
B.values().map(|B| B[n][g][0]).sum::<C::G>() + B.values().map(|(B, _)| B[n][g][0]).sum::<C::G>() +
(B.values().map(|B| B[n][g][1]).sum::<C::G>() * binding) B.values().map(|(B, binding)| B[n][g][1] * binding).sum::<C::G>()
}; };
} }
} }
@ -250,12 +265,12 @@ fn sign_with_share<C: Curve, A: Algorithm<C>>(
&params.view, &params.view,
&Rs, &Rs,
&our_preprocess.nonces.iter().map( &our_preprocess.nonces.iter().map(
|nonces| nonces[0] + (nonces[1] * binding) |nonces| nonces[0] + (nonces[1] * B[&params.keys.params.i()].1)
).collect::<Vec<_>>(), ).collect::<Vec<_>>(),
msg msg
).to_repr().as_ref().to_vec(); ).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<C: Curve, A: Algorithm<C>>( fn complete<C: Curve, A: Algorithm<C>>(
@ -287,9 +302,9 @@ fn complete<C: Curve, A: Algorithm<C>>(
for l in &sign_params.view.included { for l in &sign_params.view.included {
if !sign_params.algorithm.verify_share( if !sign_params.algorithm.verify_share(
sign_params.view.verification_share(*l), sign_params.view.verification_share(*l),
&sign.B[l].iter().map( &sign.B[l].0.iter().map(
|nonces| nonces.iter().map( |nonces| nonces.iter().map(
|commitments| commitments[0] + (commitments[1] * sign.binding) |commitments| commitments[0] + (commitments[1] * sign.B[l].1)
).collect() ).collect()
).collect::<Vec<_>>(), ).collect::<Vec<_>>(),
responses[l] responses[l]

View file

@ -21,20 +21,20 @@ fn ristretto_vectors() {
included: &[1, 3], included: &[1, 3],
nonces: &[ nonces: &[
[ [
"b358743151e33d84bf00c12f71808f4103957c3e2cabab7b895c436b5e70f90c", "eb0dc12ae7b746d36e3f2de46ce3833a05b9d4af5434eeb8cafaefda76906d00",
"7bd112153b9ae1ab9b31f5e78f61f5c4ca9ee67b7ea6d1181799c409d14c350c" "491e91aa9df514ef598d5e0c7c5cdd088fbde4965b96069d546c0f04f1822b03"
], ],
[ [
"22acad88478e0d0373a991092a322ebd1b9a2dad90451a976d0db3215426af0e", "abd12b8e6f255ee1e540eab029003a6e956567617720f61115f0941615892209",
"9155e3d7bcf7cd468b980c7e20b2c77cbdfbe33a1dcae031fd8bc6b1403f4b04" "218e22625f93f262f025bd2d13c46ba722aa29fe585ceed66ff442d98fe4e509"
] ]
], ],
sig_shares: &[ sig_shares: &[
"ff801b4e0839faa67f16dee4127b9f7fbcf5fd007900257b0e2bbc02cbe5e709", "efae3a83437fa8cd96194aacc56a7eb841630c280da99e7764a81d1340323306",
"afdf5481023c855bf3411a5c8a5fafa92357296a078c3b80dc168f294cb4f504" "96ddc4582e45eabce46f07b9e9375f8b49d35d1510fd34ac02b1e79d6100a602"
], ],
sig: "deae61af10e8ee48ba492573592fba547f5debeff6bd6e2024e8673584746f5e".to_owned() + sig: "7ec584cef9a383afb43883b73bcaa6313afe878bd5fe75a608311b866a76ec67".to_owned() +
"ae6070cf0a757f027358f8409dda4e29e04c276b808c60fbea414b2c179add0e" "858cffdb71c4928a7b895165afa2dd438b366a3d1da6d323675905b1a132d908"
} }
); );
} }
@ -58,20 +58,20 @@ fn ed25519_vectors() {
included: &[1, 3], included: &[1, 3],
nonces: &[ nonces: &[
[ [
"8c76af04340e83bb5fc427c117d38347fc8ef86d5397feea9aa6412d96c05b0a", "d9aad97e1a1127bb87702ce8d81d8c07c7cbca89e784868d8e3876ff6b459700",
"14a37ddbeae8d9e9687369e5eb3c6d54f03dc19d76bb54fb5425131bc37a600b" "5063be2774520d08a5ccd7f1213fb1179a5fa292bf13bc91cb28e7bd4d4a690c"
], ],
[ [
"5ca39ebab6874f5e7b5089f3521819a2aa1e2cf738bae6974ee80555de2ef70e", "86961f3a429ac0c5696f49e6d796817ff653f83c07f34e9e1f4d4c8c515b7900",
"0afe3650c4815ff37becd3c6948066e906e929ea9b8f546c74e10002dbcc150c" "72225ec11c1315d9f1ea0e78b1160ed95800fadd0191d23fd2f2c90ac96cb307"
] ]
], ],
sig_shares: &[ sig_shares: &[
"4369474a398aa10357b60d683da91ea6a767dcf53fd541a8ed6b4d780827ea0a", "caae171b83bff0c2c6f56a1276892918ba228146f6344b85d2ec6efeb6f16d0d",
"32fcc690d926075e45d2dfb746bab71447943cddbefe80d122c39174aa2e1004" "ea6fdbf61683cf5f1f742e1b91583f0f667f0369efd2e33399b96d5a3ff0300d"
], ],
sig: "2b8d9c6995333c5990e3a3dd6568785539d3322f7f0376452487ea35cfda587b".to_owned() + sig: "5da10008c13c04dd72328ba8e0f72b63cad43c3bf4b7eaada1c78225afbd977e".to_owned() +
"75650edb12b1a8619c88ed1f8463d6baeefb18d3fed3c279102fdfecb255fa0e" "c74afdb47fdfadca0fcda18a28e8891220a284afe5072fb96ba6dc58f6e19e0a"
} }
); );
} }

View file

@ -36,20 +36,20 @@ fn p256_vectors() {
included: &[1, 3], included: &[1, 3],
nonces: &[ nonces: &[
[ [
"081617b24375e069b39f649d4c4ce2fba6e38b73e7c16759de0b6079a22c4c7e", "33a519cf070a166f9ef41a798d03423743f3e7d0b0efd5d0d963773c4c53205e",
"4de5fb77d99f03a2491a83a6a4cb91ca3c82a3f34ce94cec939174f47c9f95dd" "307d208d0c5728f323ae374f1ebd7f14a1a49b77d9d4bc1eab222218a17765ff"
], ],
[ [
"d186ea92593f83ea83181b184d41aa93493301ac2bc5b4b1767e94d2db943e38", "a614eadb972dc37b88aeceb6e899903f3104742d13f379a0e014541decbea4a4",
"486e2ee25a3fbc8e6399d748b077a2755fde99fa85cc24fa647ea4ebf5811a15" "e509791018504c5bb87edaf0f44761cc840888507c4cd80237971d78e65f70f2"
] ]
], ],
sig_shares: &[ sig_shares: &[
"9e4d8865faf8c7b3193a3b35eda3d9e12118447114b1e7d5b4809ea28067f8a9", "61e8b9c474df2e66ad19fd80a6e6cec1c6fe43c0a1cffd2d1c28299e93e1bbdb",
"b7d094eab6305ae74daeed1acd31abba9ab81f638d38b72c132cb25a5dfae1fc" "9651d355ca1dea2557ba1f73e38a9f4ff1f1afc565323ef27f88a9d14df8370e"
], ],
sig: "0342c14c77f9d4ef9b8bd64fb0d7bbfdb9f8216a44e5f7bbe6ac0f3ed5e1a57367".to_owned() + sig: "02dfba781e17b830229ae4ed22ebe402873683d9dfd945d01762217fb3172c2a7".to_owned() +
"561e1d51b129229966e92850bad5859bfee96926fad3007cd3f38639e1ffb554" "1f83a8d1a3efd188c04d41cf48a716e11b8eff38607023c1f9bb0d36fe1d9f2e9"
} }
); );
} }