diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index 9c8fa07..f2fce95 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -1,5 +1,5 @@
[package]
-name = "TPNSM"
+name = "crypto_test"
version = "0.1.0"
edition = "2021"
@@ -7,4 +7,5 @@ edition = "2021"
[dependencies]
num = "0.4"
-rayon = "1.5.3"
\ No newline at end of file
+rayon = "1.5"
+rand = "0.8"
\ No newline at end of file
diff --git a/rust/algo.md b/rust/algo.md
index b79d918..6466e89 100644
--- a/rust/algo.md
+++ b/rust/algo.md
@@ -1,2 +1,22 @@
-Elliptic_curve_primality
-
\ No newline at end of file
+# Primality tests
+
+
+Elliptic curve
+
+
+
+
+
+
+Miller–Rabin
+
+
+
+
+
+
+Baillie–PSW
+
+AKS
+
+Adleman–Pomerance–Rumely
\ No newline at end of file
diff --git a/rust/pictures/mrp.png b/rust/pictures/mrp.png
new file mode 100644
index 0000000..27689a2
Binary files /dev/null and b/rust/pictures/mrp.png differ
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 94a8f2f..edcf95f 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -1,2 +1,2 @@
pub mod prime;
-pub mod utils;
\ No newline at end of file
+pub mod utils;
diff --git a/rust/src/main.rs b/rust/src/main.rs
index 8a2b537..e7a11a9 100644
--- a/rust/src/main.rs
+++ b/rust/src/main.rs
@@ -1,15 +1,3 @@
-use TPNSM::prime::{prime_classical, prime_dumb_rayon};
-
fn main() {
println!("Hello, world!");
-
- let max = 1000000;
- find_prime(prime_classical(max));
- //find_prime(prime_dumb_rayon(max));
}
-
-fn find_prime(primes: Vec) {
- //println!("{:?}", primes);
- println!("{:?}", primes.last());
- println!("{}", primes.len());
-}
\ No newline at end of file
diff --git a/rust/src/prime.rs b/rust/src/prime.rs
index a3afcc2..a9bb46a 100644
--- a/rust/src/prime.rs
+++ b/rust/src/prime.rs
@@ -1,17 +1,60 @@
+use crate::utils::fast_exp;
use num::integer::sqrt;
+use rand::{thread_rng, Rng};
use rayon::prelude::*;
+pub fn miller_rabbin_gen(max: u32, acr: u32) -> Vec {
+ let method = |n| miller_rabbin_test(n, acr);
+ prime_gen(max, method)
+}
+
+pub fn miller_rabbin_test(n: u32, acr: u32) -> bool {
+ if n % 2 == 0 {
+ false
+ } else {
+ let (k, q) = find_2_k_q(n - 1);
+ let mut random = thread_rng();
+
+ 'l: for _ in 0..acr {
+ let a = random.gen_range(1..n - 1);
+ let mut x = fast_exp(a, q, n);
+
+ if x != 1 && x != n - 1 {
+ for _ in 0..k - 1 {
+ x = fast_exp(x, 2, n);
+ if x == n - 1 {
+ continue 'l;
+ }
+ }
+ return false;
+ }
+ }
+ true
+ }
+}
+
+fn find_2_k_q(mut n: u32) -> (u32, u32) {
+ let mut k = 0;
+ while n % 2 == 0 {
+ n /= 2;
+ k += 1;
+ }
+ (k, n)
+}
+
fn prime_gen(max: u32, method: F) -> Vec
- where F: Fn(u32) -> bool {
+where
+ F: Fn(u32) -> bool,
+{
let mut primes = vec![2_u32];
- let mut i = 1;
+ let mut i = 3;
while i < max {
- i += 2;
let prime = method(i);
if prime {
primes.push(i);
}
+ i += 2;
}
primes
}
@@ -19,7 +62,7 @@ fn prime_gen(max: u32, method: F) -> Vec
pub fn prime_classical(max: u32) -> Vec {
let mut primes = vec![2_u32];
let mut i = 1;
- 'l: while i < max {
+ 'l: while i + 2 < max {
i += 2;
for p in &primes {
if i % p == 0 {
@@ -35,16 +78,53 @@ pub fn prime_classical(max: u32) -> Vec {
pub fn prime_dumb_rayon(max: u32) -> Vec {
let mut primes = vec![2_u32];
- let mut i = 1;
+ let mut i = 3;
while i < max {
- i += 2;
- let found = primes.par_iter()
- .filter(|x| { **x <= sqrt(i) })
- .any(|x| { i % *x == 0 });
+ let found = primes
+ .par_iter()
+ .filter(|x| **x <= sqrt(i))
+ .any(|x| i % *x == 0);
if !found {
primes.push(i);
}
+ i += 2;
}
primes
-}
\ No newline at end of file
+}
+#[cfg(test)]
+mod tests {
+ use super::*;
+ const PRIME_TEST: [(u32, u32); 6] = [
+ (10, 7),
+ (100, 97),
+ (500, 499),
+ (1000, 997),
+ (8300, 8297),
+ (10000, 9973),
+ ];
+
+ #[test]
+ fn test_prime_classical() {
+ for (max, prem) in PRIME_TEST {
+ assert_eq!(prime_classical(max).last(), Some(&prem));
+ }
+ }
+
+ #[test]
+ fn test_prime_dumb_rayon() {
+ for (max, prem) in PRIME_TEST {
+ assert_eq!(prime_dumb_rayon(max).last(), Some(&prem));
+ }
+ }
+
+ #[test]
+ fn test_miller_rabbin() {
+ for (max, prem) in PRIME_TEST {
+ assert_eq!(miller_rabbin_gen(max, 10).last(), Some(&prem));
+ }
+
+ assert!(!miller_rabbin_test(2147483649, 10));
+ assert!(miller_rabbin_test(2147483647, 10));
+ }
+}
diff --git a/rust/src/utils.rs b/rust/src/utils.rs
index be52dae..bb5828d 100644
--- a/rust/src/utils.rs
+++ b/rust/src/utils.rs
@@ -48,7 +48,6 @@ pub fn congruent(a: i32, b: i32, n: i32) -> bool {
(a - b) % n == 0
}
-
pub fn gcd_euclid(mut a: u32, mut b: u32) -> u32 {
let mut r = a % b;
while r != 0 {
@@ -79,6 +78,23 @@ pub fn modular_inverse(a: u32, n: u32) -> Option {
Some(t as u32)
}
+pub fn fast_exp(mut b: u32, mut e: u32, m: u32) -> u32 {
+ if m == 1 {
+ return 0;
+ }
+ let mut result = 1;
+
+ b %= m;
+ while e > 0 {
+ if e % 2 == 1 {
+ result = (result as u64 * b as u64 % m as u64) as u32;
+ }
+ e >>= 1;
+ b = (b as u64 * b as u64 % m as u64) as u32;
+ }
+ result
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -124,4 +140,12 @@ mod tests {
assert_eq!(modular_inverse(10, 19), Some(2));
assert_eq!(modular_inverse(4, 6), None);
}
-}
\ No newline at end of file
+
+ #[test]
+ fn test_fast_exp() {
+ assert_eq!(fast_exp(5, 3, 13), 8);
+ assert_eq!(fast_exp(11, 13, 19), 11);
+ assert_eq!(fast_exp(1234, 754, 452), 392);
+ assert_eq!(fast_exp(76158, 24586, 5364), 576);
+ }
+}