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 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.
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ impl DSAKeyPair {
|
|||||||
let one = UCN::from(1 as u64);
|
let one = UCN::from(1 as u64);
|
||||||
let x = (&c % (¶ms.q - &one)) + &one;
|
let x = (&c % (¶ms.q - &one)) + &one;
|
||||||
// 7. y = g^x mod p
|
// 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.
|
// 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 };
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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().");
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user