From 219641da5e81abf9befe8464a48944edf00765b8 Mon Sep 17 00:00:00 2001 From: Adam Wick Date: Sat, 12 May 2018 16:41:33 -0700 Subject: [PATCH] Try to speed up DSA a bit using Barrett reduction. --- src/dsa/generation.rs | 6 +++--- src/dsa/gold_tests.rs | 3 ++- src/dsa/mod.rs | 2 +- src/dsa/parameters.rs | 14 ++++++++++---- src/dsa/private.rs | 7 ++++--- src/dsa/public.rs | 10 +++++----- 6 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/dsa/generation.rs b/src/dsa/generation.rs index 221820a..0424322 100644 --- a/src/dsa/generation.rs +++ b/src/dsa/generation.rs @@ -1,4 +1,4 @@ -use cryptonum::UCN; +use cryptonum::{BarrettUCN,UCN}; use digest::{FixedOutput,Input}; use dsa::errors::DSAGenError; use dsa::parameters::{DSAParameterSize,n_bits,l_bits}; @@ -192,7 +192,7 @@ pub fn validate_provable_primes(rng: &mut G, } } -pub fn generate_verifiable_generator(p: &UCN, +pub fn generate_verifiable_generator(p: &UCN, pu: &BarrettUCN, q: &UCN, ev: &DSAGenEvidence, index: u8) @@ -229,7 +229,7 @@ pub fn generate_verifiable_generator(p: &UCN, dgst.process(&u); let w = UCN::from_bytes(dgst.fixed_result().as_slice()); // 9. g = W^e mod p - let g = w.modexp(&e, &p); + let g = w.fastmodexp(&e, &pu); // 10. if (g < 2), then go to step 5. if &g >= &two { // 11. Return VALID and the value of g. diff --git a/src/dsa/gold_tests.rs b/src/dsa/gold_tests.rs index b6ea25c..489586d 100644 --- a/src/dsa/gold_tests.rs +++ b/src/dsa/gold_tests.rs @@ -25,7 +25,8 @@ fn pqg_generation_checks() { generate_provable_primes(&mut rng, &seed, params).unwrap(); assert!(validate_provable_primes(&mut rng, &p, &q, &ev)); let index = rng.gen::(); - let g = generate_verifiable_generator(&p, &q, &ev, index).unwrap(); + let pu = p.barrett_u(); + let g = generate_verifiable_generator(&p, &pu, &q, &ev, index).unwrap(); assert!(verify_generator(&p, &q, &ev, index, &g)); } } diff --git a/src/dsa/mod.rs b/src/dsa/mod.rs index 757d8f3..4540b8e 100644 --- a/src/dsa/mod.rs +++ b/src/dsa/mod.rs @@ -65,7 +65,7 @@ impl DSAKeyPair { let one = UCN::from(1 as u64); let x = (&c % (¶ms.q - &one)) + &one; // 7. y = g^x mod p - let y = params.g.modexp(&x, ¶ms.p); + let y = params.g.fastmodexp(&x, ¶ms.pu); // 8. Return SUCCESS, x, and y. let private = DSAPrivate { params: params.clone(), x: x }; let public = DSAPublic { params: params.clone(), y: y }; diff --git a/src/dsa/parameters.rs b/src/dsa/parameters.rs index 4376b2d..d9539e7 100644 --- a/src/dsa/parameters.rs +++ b/src/dsa/parameters.rs @@ -1,4 +1,4 @@ -use cryptonum::UCN; +use cryptonum::{BarrettUCN,UCN}; use dsa::errors::*; use dsa::generation::{DSAGenEvidence,verify_generator, get_input_seed,generate_provable_primes, @@ -37,6 +37,8 @@ pub struct DSAParameters { pub p: UCN, pub g: UCN, pub q: UCN, + pub pu: BarrettUCN, + pub qu: BarrettUCN } impl DSAParameters { @@ -56,7 +58,9 @@ impl DSAParameters { (3072, 256) => DSAParameterSize::L3072N256, _ => return Err(DSAError::InvalidParamSize) }; - Ok(DSAParameters{ size: size, p: p, g: g, q: q }) + let pu = p.barrett_u(); + let qu = q.barrett_u(); + Ok(DSAParameters{ size: size, p: p, g: g, q: q, pu: pu, qu: qu }) } /// Generate a new set of DSA parameters for use. You probably shouldn't be @@ -89,8 +93,10 @@ impl DSAParameters { idx: u8) -> Result { - let g = generate_verifiable_generator(&p, &q, &ev, idx)?; - Ok(DSAParameters{ size: ps, p: p, q: q, g: g }) + let pu = p.barrett_u(); + let qu = q.barrett_u(); + let g = generate_verifiable_generator(&p, &pu, &q, &ev, idx)?; + Ok(DSAParameters{ size: ps, p: p, q: q, g: g, pu: pu, qu: qu }) } /// Given the provided evidence, validate that the domain parameters diff --git a/src/dsa/private.rs b/src/dsa/private.rs index e41af53..058d607 100644 --- a/src/dsa/private.rs +++ b/src/dsa/private.rs @@ -47,7 +47,7 @@ impl DSAPrivate { .map(|x| *x) .collect(); let h0 = bits2int(&h1, n); - let h = h0.rem(&self.params.q); + let h = h0.reduce(&self.params.qu); // 2. A random value modulo q, dubbed k, is generated. That value // shall not be 0; hence, it lies in the [1, q-1] range. Most @@ -68,7 +68,8 @@ impl DSAPrivate { // // If r turns out to be zero, a new k should be selected and r // computed again (this is an utterly improbable occurrence). - let r = self.params.g.modexp(&k, &self.params.p) % &self.params.q; + let r = self.params.g.fastmodexp(&k, &self.params.pu) + .rem(&self.params.q); if r.is_zero() { continue; } @@ -78,7 +79,7 @@ impl DSAPrivate { // // The pair (r, s) is the signature. let kinv = k.modinv(&self.params.q); - let s = ((&h + (&self.x * &r)) * &kinv) % &self.params.q; + let s = ((&h + (&self.x * &r)) * &kinv).rem(&self.params.q); return DSASignature{ r: r, s: s }; } panic!("The world is broken; couldn't find a k in sign()."); diff --git a/src/dsa/public.rs b/src/dsa/public.rs index b853aaf..f8abbc4 100644 --- a/src/dsa/public.rs +++ b/src/dsa/public.rs @@ -46,13 +46,13 @@ impl DSAPublic { bytes.truncate(len); UCN::from_bytes(&bytes) }; // u1 = (zw) mod q - let u1 = (&z * &w).rem(&self.params.q); + let u1 = (&z * &w).reduce(&self.params.qu); // u2 = (rw) mod q - let u2 = (&sig.r * &w).rem(&self.params.q); + let u2 = (&sig.r * &w).reduce(&self.params.qu); // v = (((g)^u1(y)^u2) mod p) mod q - let v_1 = self.params.g.modexp(&u1, &self.params.p); - let v_2 = self.y.modexp(&u2, &self.params.p); - let v = (&v_1 * &v_2).rem(&self.params.p) + let v_1 = self.params.g.fastmodexp(&u1, &self.params.pu); + let v_2 = self.y.fastmodexp(&u2, &self.params.pu); + let v = (&v_1 * &v_2).reduce(&self.params.pu) .rem(&self.params.q); // if v = r, then the signature is verified v == sig.r