From 450131c6fa4178c067505724fd35dd01b831a4d6 Mon Sep 17 00:00:00 2001 From: theBreadCompany Date: Wed, 4 Dec 2024 13:56:14 +0100 Subject: [PATCH] use 16-bit n and add comments --- src/main.rs | 8 ++++-- src/pollard_rho.rs | 66 +++++++++++++++++++++++++++++----------------- 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/src/main.rs b/src/main.rs index fd0ca05..2029d5d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,11 @@ mod pollard_rho; fn main() { - let n = rand::random::(); + let mut n = 0; + while n % 2 == 0 { n = rand::random::(); } let n_primediv = pollard_rho::pollard_rho(n.into()); - eprintln!("Generated random number {}, got prime divisor {}", n, n_primediv); + eprintln!( + "Generated random number {}, got prime divisor {}", + n, n_primediv + ); } diff --git a/src/pollard_rho.rs b/src/pollard_rho.rs index 91ca656..3dff6f9 100644 --- a/src/pollard_rho.rs +++ b/src/pollard_rho.rs @@ -1,53 +1,71 @@ use gcd::Gcd; /** - * Calculate the primedivisor for some number `n` + * Calculate the prime divisor for some number `n` + * + * Uses cycle finding */ -pub fn pollard_rho(n: u16) -> u16 { - if n == 1 { return 1; } // 1 only has 1 as prime divisor - if n % 2 == 0 { return 2; } // even numbers have at least 2 as prime divisor - if is_prime(n) { return n; } +pub fn pollard_rho(n: u32) -> u32 { + if n == 1 { + return 1; + } // 1 only has 1 as prime divisor + if n % 2 == 0 { + return 2; + } // even numbers have at least 2 as prime divisor + if is_prime(n) { + return n; + } // need to detect to be able to decide if we have bad random numbers or the - let mut x = rand::random::() % 2; - let mut y = x; + let mut x = rand::random::() % n; // cycle finding: tortoise + let mut y = x; // cycle finding: hare - let c = rand::random::() % 2; - let mut div = 1; + let c = rand::random::() % n; // random number to add to the cycle finding moves + let mut div = 1; // divisor - 1 applies to all numbers and is our failed and start value while div == 1 { + // tortoise move x = (mod_pow(x, 2, n) + c + n) % n; + // hare move y = (mod_pow(y, 2, n) + c + n) % n; y = (mod_pow(y, 2, n) + c + n) % n; - div = u16::try_from((i16::try_from(x).unwrap()-i16::try_from(y).unwrap()).abs()).unwrap().gcd(n); - eprintln!("Got div {}", div); - if div == n { return pollard_rho(n); } + // divisor is the greatest common divisor between |x-y| and n + div = u32::try_from((i32::try_from(x).unwrap() - i32::try_from(y).unwrap()).abs()) + .unwrap() + .gcd(n); + // bad random numbers, try again + if div == n { + return pollard_rho(n); + } } - return div; + div } /** * Discrete/Modular exponentiation - * - * Highly memory efficient because the full result is never stored, but shortened by defined modulo instead. + * + * Highly memory efficient because the full result is never stored, but shortened by defined modulo instead. * We can use that because the prime divisor required for our algorithm is guarenteed to be smaller * than n. - * + * * Counterpart function to the discrete logarithm. */ -fn mod_pow(base: u16, exp: u16, r#mod: u16) -> u16 { - let mut result = 1; - - for _ in 0..exp-1 { +fn mod_pow(base: u32, exp: u32, r#mod: u32) -> u32 { + let mut result = 1; + for _ in 0..exp - 1 { result = (result * base) % r#mod; } - result } -fn is_prime(n: u16) -> bool { - for i in (3..=(n as f32).sqrt() as u16).step_by(2) { - if n % i == 0 { return false; } +/** + * very primitive prime checker + */ +fn is_prime(n: u32) -> bool { + for i in (3..=(n as f32).sqrt() as u32).step_by(2) { + if n % i == 0 { + return false; + } } true }