Skip to content

Commit

Permalink
Merge #192
Browse files Browse the repository at this point in the history
192: Mpi::is_probably_prime (mbedtls_mpi_is_prime_ext) r=jethrogb a=zugzwang

Support mbedtls_mpi_is_prime, the Miller-Rabin primality test.

Co-authored-by: Francisco Vial-Prado <[email protected]>
  • Loading branch information
bors[bot] and zugzwang authored Mar 22, 2022
2 parents b99bd02 + 38e86e9 commit b923ea4
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 1 deletion.
19 changes: 18 additions & 1 deletion mbedtls/src/bignum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use core::cmp::Ordering;
use core::fmt::{Binary, Debug, Display, Formatter, Octal, Result as FmtResult, UpperHex};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign};
use core::ops::{Shl, ShlAssign, Shr, ShrAssign};
use crate::rng::Random;

pub use mbedtls_sys::mpi_sint;

Expand Down Expand Up @@ -407,6 +408,23 @@ impl Mpi {

Ok(r)
}

/// The Miller-Rabin primality test with k rounds. Returns
/// `MpiNotAcceptable` if self is definitely not prime. If no error is
/// returned, self is prime with a probability of 1 - 1/2^{2k}. See
/// mbedtls_mpi_is_prime.
pub fn is_probably_prime<F: Random>(&self, k: u32, rng: &mut F) -> Result<()> {
unsafe {
mpi_is_prime_ext(
&self.inner,
k as i32,
Some(F::call),
rng.data_ptr(),
)
.into_result()?;
}
Ok(())
}
}

impl Ord for Mpi {
Expand Down Expand Up @@ -768,4 +786,3 @@ impl ShrAssign<usize> for Mpi {
// mbedtls_mpi_sub_abs
// mbedtls_mpi_mod_int
// mbedtls_mpi_gcd
// mbedtls_mpi_is_prime
62 changes: 62 additions & 0 deletions mbedtls/tests/bignum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,3 +415,65 @@ fn test_base58_encode() {
"3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f",
);
}

#[cfg(feature = "rdrand")]
#[test]
fn is_probably_prime() {
fn test_is_prime(input: Mpi, prime_expected: bool) {
use mbedtls::rng::{CtrDrbg, Rdseed};
use mbedtls::Error::MpiNotAcceptable;
let mut rng = CtrDrbg::new(Rdseed.into(), None).unwrap();
let rounds = 15; // accuracy 1/2**30

let result = input.is_probably_prime(rounds, &mut rng);
if prime_expected {
assert!(result.is_ok());
} else {
assert!(result == Err(MpiNotAcceptable), "expected not prime");
}
}
test_is_prime(Mpi::new(-4).unwrap(), false);
test_is_prime(Mpi::new(-3).unwrap(), true);
test_is_prime(Mpi::new(-2).unwrap(), true);
test_is_prime(Mpi::new(-1).unwrap(), false);
test_is_prime(Mpi::new(0).unwrap(), false);
test_is_prime(Mpi::new(1).unwrap(), false);
test_is_prime(Mpi::new(2).unwrap(), true);
test_is_prime(Mpi::new(3).unwrap(), true);
test_is_prime(Mpi::new(4).unwrap(), false);
test_is_prime(Mpi::new(9973).unwrap(), true); // Last prime before 10000
test_is_prime(Mpi::new(10007).unwrap(), true); // First prime after 10000
test_is_prime(Mpi::new(10009).unwrap(), true);
test_is_prime(Mpi::new(22801763489).unwrap(), true); // 1000000000th prime
test_is_prime(Mpi::new(22801763491).unwrap(), false);

// RSA-250, the largest RSA challenge solved (829 bits)
let rsa_250_n = Mpi::from_binary(&[
0x13, 0x21, 0xD2, 0xFD, 0xDD, 0xE8, 0xBD, 0x9D, 0xFF, 0x37, 0x9A, 0xFF,
0x03, 0x0D, 0xE2, 0x05, 0xB8, 0x46, 0xEB, 0x5C, 0xEC, 0xC4, 0x0F, 0xA8,
0xAA, 0x9C, 0x2A, 0x85, 0xCE, 0x3E, 0x99, 0x21, 0x93, 0xE8, 0x73, 0xB2,
0xBC, 0x66, 0x7D, 0xAB, 0xE2, 0xAC, 0x3E, 0xE9, 0xDD, 0x23, 0xB3, 0xA9,
0xED, 0x9E, 0xC0, 0xC3, 0xC7, 0x44, 0x56, 0x63, 0xF5, 0x45, 0x54, 0x69,
0xB7, 0x27, 0xDD, 0x6F, 0xBC, 0x03, 0xB1, 0xBF, 0x95, 0xD0, 0x3A, 0x13,
0xC0, 0x36, 0x86, 0x45, 0x76, 0x76, 0x30, 0xC7, 0xEA, 0xBF, 0x5E, 0x7A,
0xB5, 0xFA, 0x27, 0xB9, 0x4A, 0xDE, 0x7E, 0x1E, 0x23, 0xBC, 0xC6, 0x5D,
0x2A, 0x7D, 0xED, 0x1C, 0x5B, 0x36, 0x4B, 0x51]
).unwrap();
let rsa_250_p = Mpi::from_binary(&[
0x61, 0x04, 0xFA, 0xF8, 0x1F, 0x41, 0xFD, 0xD7, 0x61, 0x6B, 0x43, 0x78,
0xF6, 0xBD, 0x99, 0x12, 0x92, 0xCB, 0x2F, 0x21, 0xC1, 0x0D, 0x06, 0xC5,
0xE8, 0xE5, 0x71, 0xA5, 0xE9, 0x62, 0xB7, 0xE8, 0x2D, 0xFD, 0x9F, 0xE7,
0x12, 0x0F, 0x6D, 0x03, 0xA8, 0x6C, 0xC6, 0xBB, 0xC7, 0xDD, 0x3A, 0x62,
0x80, 0x83, 0x9E, 0xF7]
).unwrap();
let rsa_250_q = Mpi::from_binary(&[
0x32, 0x7B, 0x9F, 0xDA, 0x4B, 0x21, 0x1E, 0x3B, 0xFD, 0xB5, 0x4F, 0x68,
0x0E, 0x5C, 0x04, 0x52, 0x8A, 0xAA, 0x20, 0x42, 0x8A, 0xE0, 0x08, 0xFA,
0xF4, 0x8D, 0xF6, 0xC9, 0x13, 0xF5, 0x74, 0x7D, 0x86, 0x08, 0xA5, 0xA4,
0x8E, 0x2B, 0xFE, 0x41, 0xFA, 0xE7, 0xA0, 0x46, 0x83, 0xF2, 0x30, 0x58,
0x52, 0xCD, 0xAD, 0xF7]
).unwrap();
test_is_prime(rsa_250_p.clone(), true);
test_is_prime(rsa_250_q.clone(), true);
test_is_prime(rsa_250_n.clone(), false);
}

0 comments on commit b923ea4

Please sign in to comment.