Try to speed up DSA a bit using Barrett reduction.

This commit is contained in:
2018-05-12 16:41:33 -07:00
parent f0f4891abe
commit 219641da5e
6 changed files with 25 additions and 17 deletions

View File

@@ -1,4 +1,4 @@
use cryptonum::UCN; use cryptonum::{BarrettUCN,UCN};
use digest::{FixedOutput,Input}; use digest::{FixedOutput,Input};
use dsa::errors::DSAGenError; use dsa::errors::DSAGenError;
use dsa::parameters::{DSAParameterSize,n_bits,l_bits}; use dsa::parameters::{DSAParameterSize,n_bits,l_bits};
@@ -192,7 +192,7 @@ pub fn validate_provable_primes<G: Rng>(rng: &mut G,
} }
} }
pub fn generate_verifiable_generator(p: &UCN, pub fn generate_verifiable_generator(p: &UCN, pu: &BarrettUCN,
q: &UCN, q: &UCN,
ev: &DSAGenEvidence, ev: &DSAGenEvidence,
index: u8) index: u8)
@@ -229,7 +229,7 @@ pub fn generate_verifiable_generator(p: &UCN,
dgst.process(&u); dgst.process(&u);
let w = UCN::from_bytes(dgst.fixed_result().as_slice()); let w = UCN::from_bytes(dgst.fixed_result().as_slice());
// 9. g = W^e mod p // 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. // 10. if (g < 2), then go to step 5.
if &g >= &two { if &g >= &two {
// 11. Return VALID and the value of g. // 11. Return VALID and the value of g.

View File

@@ -25,7 +25,8 @@ fn pqg_generation_checks() {
generate_provable_primes(&mut rng, &seed, params).unwrap(); generate_provable_primes(&mut rng, &seed, params).unwrap();
assert!(validate_provable_primes(&mut rng, &p, &q, &ev)); assert!(validate_provable_primes(&mut rng, &p, &q, &ev));
let index = rng.gen::<u8>(); let index = rng.gen::<u8>();
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)); assert!(verify_generator(&p, &q, &ev, index, &g));
} }
} }

View File

@@ -65,7 +65,7 @@ impl DSAKeyPair {
let one = UCN::from(1 as u64); let one = UCN::from(1 as u64);
let x = (&c % (&params.q - &one)) + &one; let x = (&c % (&params.q - &one)) + &one;
// 7. y = g^x mod p // 7. y = g^x mod p
let y = params.g.modexp(&x, &params.p); let y = params.g.fastmodexp(&x, &params.pu);
// 8. Return SUCCESS, x, and y. // 8. Return SUCCESS, x, and y.
let private = DSAPrivate { params: params.clone(), x: x }; let private = DSAPrivate { params: params.clone(), x: x };
let public = DSAPublic { params: params.clone(), y: y }; let public = DSAPublic { params: params.clone(), y: y };

View File

@@ -1,4 +1,4 @@
use cryptonum::UCN; use cryptonum::{BarrettUCN,UCN};
use dsa::errors::*; use dsa::errors::*;
use dsa::generation::{DSAGenEvidence,verify_generator, use dsa::generation::{DSAGenEvidence,verify_generator,
get_input_seed,generate_provable_primes, get_input_seed,generate_provable_primes,
@@ -37,6 +37,8 @@ pub struct DSAParameters {
pub p: UCN, pub p: UCN,
pub g: UCN, pub g: UCN,
pub q: UCN, pub q: UCN,
pub pu: BarrettUCN,
pub qu: BarrettUCN
} }
impl DSAParameters { impl DSAParameters {
@@ -56,7 +58,9 @@ impl DSAParameters {
(3072, 256) => DSAParameterSize::L3072N256, (3072, 256) => DSAParameterSize::L3072N256,
_ => return Err(DSAError::InvalidParamSize) _ => 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 /// Generate a new set of DSA parameters for use. You probably shouldn't be
@@ -89,8 +93,10 @@ impl DSAParameters {
idx: u8) idx: u8)
-> Result<DSAParameters, DSAGenError> -> Result<DSAParameters, DSAGenError>
{ {
let g = generate_verifiable_generator(&p, &q, &ev, idx)?; let pu = p.barrett_u();
Ok(DSAParameters{ size: ps, p: p, q: q, g: g }) 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 /// Given the provided evidence, validate that the domain parameters

View File

@@ -47,7 +47,7 @@ impl DSAPrivate {
.map(|x| *x) .map(|x| *x)
.collect(); .collect();
let h0 = bits2int(&h1, n); 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 // 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 // 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 // If r turns out to be zero, a new k should be selected and r
// computed again (this is an utterly improbable occurrence). // 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() { if r.is_zero() {
continue; continue;
} }
@@ -78,7 +79,7 @@ impl DSAPrivate {
// //
// The pair (r, s) is the signature. // The pair (r, s) is the signature.
let kinv = k.modinv(&self.params.q); 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 }; return DSASignature{ r: r, s: s };
} }
panic!("The world is broken; couldn't find a k in sign()."); panic!("The world is broken; couldn't find a k in sign().");

View File

@@ -46,13 +46,13 @@ impl DSAPublic {
bytes.truncate(len); bytes.truncate(len);
UCN::from_bytes(&bytes) }; UCN::from_bytes(&bytes) };
// u1 = (zw) mod q // u1 = (zw) mod q
let u1 = (&z * &w).rem(&self.params.q); let u1 = (&z * &w).reduce(&self.params.qu);
// u2 = (rw) mod q // 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 // v = (((g)^u1(y)^u2) mod p) mod q
let v_1 = self.params.g.modexp(&u1, &self.params.p); let v_1 = self.params.g.fastmodexp(&u1, &self.params.pu);
let v_2 = self.y.modexp(&u2, &self.params.p); let v_2 = self.y.fastmodexp(&u2, &self.params.pu);
let v = (&v_1 * &v_2).rem(&self.params.p) let v = (&v_1 * &v_2).reduce(&self.params.pu)
.rem(&self.params.q); .rem(&self.params.q);
// if v = r, then the signature is verified // if v = r, then the signature is verified
v == sig.r v == sig.r