diff --git a/lib/grammers-crypto/src/factorize.rs b/lib/grammers-crypto/src/factorize.rs index de84a629..fe54213e 100644 --- a/lib/grammers-crypto/src/factorize.rs +++ b/lib/grammers-crypto/src/factorize.rs @@ -42,6 +42,22 @@ fn modpow(mut n: u128, mut e: u128, m: u128) -> u128 { /// Richard Brent: #[allow(clippy::many_single_char_names)] pub fn factorize(pq: u64) -> (u64, u64) { + const ATTEMPTS: [u64; 5] = [43, 47, 53, 59, 61]; + for attempt in ATTEMPTS { + // > Note that this algorithm may not find the factors and will return failure for composite n. + // > In that case, use a different f(x) and try again [...] We choose f(x) = x*x + c + // Thus by choosing a different `c` we're changing `f(x)` and can try again. + // Prime factors are used for the attempts in the hopes they'll be more likely to work. + let c = attempt * (pq / 103); + let (p, q) = factorize_with_param(pq, c); + if p != 1 { + return (p, q); + } + } + panic!("failed to factorize in a fixed amount of attempts") +} + +fn factorize_with_param(pq: u64, c: u64) -> (u64, u64) { if pq % 2 == 0 { return (2, pq / 2); } @@ -52,8 +68,9 @@ pub fn factorize(pq: u64) -> (u64, u64) { } // Random values in the range of 1..pq, chosen by fair dice roll. + // c is an input free to change in case the chosen value fails. let mut y = 3 * (pq / 7); - let c = 5 * (pq / 11); + let c = c as u128; let m = 7 * (pq / 13); let mut g = 1u128; let mut r = 1u128;