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 dsa::errors::DSAGenError;
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,
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.

View File

@@ -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::<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));
}
}

View File

@@ -65,7 +65,7 @@ impl DSAKeyPair {
let one = UCN::from(1 as u64);
let x = (&c % (&params.q - &one)) + &one;
// 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.
let private = DSAPrivate { params: params.clone(), x: x };
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::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<DSAParameters, DSAGenError>
{
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

View File

@@ -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().");

View File

@@ -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