Try to speed up DSA a bit using Barrett reduction.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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().");
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user