Support fast modular exponentiation for when your base is roughly the same order of magnitude as the modulo.
This commit is contained in:
@@ -3,7 +3,7 @@ use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::str::Lines;
|
||||
|
||||
use cryptonum::unsigned::UCN;
|
||||
use cryptonum::unsigned::{UCN,BarrettUCN};
|
||||
use cryptonum::signed::SCN;
|
||||
|
||||
fn next_value_set(line: &str) -> (String, SCN)
|
||||
@@ -184,6 +184,23 @@ fn modular_exponentiation_test()
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fast_modular_exponentiation_test()
|
||||
{
|
||||
run_test("tests/math/fastmodexp.tests", 6, |scase| {
|
||||
let case = make_unsigned(scase);
|
||||
let a = case.get("a").unwrap();
|
||||
let b = case.get("b").unwrap();
|
||||
let kbig = case.get("k").unwrap();
|
||||
let k = usize::from(kbig);
|
||||
let m = case.get("m").unwrap();
|
||||
let u = case.get("u").unwrap();
|
||||
let z = case.get("z").unwrap();
|
||||
let mu = BarrettUCN{ k: k, u: u.clone(), m: m.clone() };
|
||||
assert_eq!(a.fastmodexp(&b, &mu), *z);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn barrett_reduction_test()
|
||||
{
|
||||
|
||||
@@ -237,6 +237,25 @@ impl UCN {
|
||||
eprime >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fastmodexp(&self, e: &UCN, mu: &BarrettUCN) -> UCN {
|
||||
let mut b = self.reduce(&mu);
|
||||
let mut eprime = e.clone();
|
||||
let mut result = UCN::from(1 as u8);
|
||||
|
||||
loop {
|
||||
if eprime.is_zero() {
|
||||
return result;
|
||||
}
|
||||
|
||||
if eprime.is_odd() {
|
||||
result = (result * &b).reduce(&mu);
|
||||
}
|
||||
|
||||
b = (&b * &b).reduce(&mu);
|
||||
eprime >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn miller_rabin<G: Rng>(g: &mut G, n: &UCN, iters: usize) -> bool {
|
||||
@@ -1256,5 +1275,21 @@ mod test {
|
||||
let barrett = b.barrett_u();
|
||||
(&a % &b) == a.reduce(&barrett)
|
||||
}
|
||||
fn fastmodexp(ina: UCN, b: UCN, c: UCN) -> bool {
|
||||
let mut a = ina.clone();
|
||||
|
||||
if c.contents.len() == 0 {
|
||||
return true;
|
||||
}
|
||||
|
||||
if a.contents.len() > c.contents.len() {
|
||||
a.contents.resize(c.contents.len(), 0);
|
||||
}
|
||||
|
||||
let cu = c.barrett_u();
|
||||
let slow = a.modexp(&b, &c);
|
||||
let fast = a.fastmodexp(&b, &cu);
|
||||
slow == fast
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user