//! Generates [safe prime numbers](https://www.wikiwand.com/en/Sophie_Germain_prime). use ramp::Int; use rand::rngs::OsRng; pub use common::{gen_prime, is_prime}; use common::{two, three}; use error::{Error, Result}; /// Constructs a new `SafePrime` with a size of `bit_length` bits. /// /// This will initialize an `OsRng` instance and call the /// `SafePrime::from_rng()` method. /// /// Note: the `bit_length` MUST be at least 512-bits. pub fn new(bit_length: usize) -> Result { if bit_length < 512 { Err(Error::BitLength(bit_length)) } else { let mut rngesus = OsRng::new()?; Ok(from_rng(bit_length, &mut rngesus)?) } } /// Checks if number is a safe prime pub fn is_safe_prime(candidate: &Int) -> bool { // according to https://eprint.iacr.org/2003/186.pdf // a safe prime is congruent to 2 mod 3 if (candidate % three()) == two() { if is_prime(&candidate) { // a safe prime satisfies (p-1)/2 is prime. Since a // prime is odd, We just need to divide by 2 let candidate_p = candidate >> 1; return is_prime(&candidate_p) } } false } /// Constructs a new `SafePrime` with the size of `bit_length` bits, sourced /// from an already-initialized `OsRng`. pub fn from_rng(bit_length: usize, mut rngesus: &mut OsRng) -> Result { if bit_length < 512 { Err(Error::BitLength(bit_length)) } else { let mut candidate: Int; loop { candidate = gen_prime(bit_length, &mut rngesus)?; if is_safe_prime(&candidate) { break; } candidate <<= 1; candidate += 1; if is_prime(&candidate) { break; } } Ok(candidate) } } #[cfg(test)] mod tests { use super::{new, is_safe_prime}; use ramp::Int; #[test] fn test_safe_prime_bit_length_too_small() { let sp = new(511); assert_eq!(false, match sp { Ok(_) => true, Err(_) => false }); } #[test] fn test_safe_prime() { let sp = new(512); assert_eq!(true, match sp { Ok(_) => true, Err(_) => false }); } #[test] fn test_is_safe_prime() { //Numbers pulled from https://github.com/mikelodder7/cunningham_chain/blob/master/findings.md //p0 is sophie german prime let p0 = Int::from_str_radix("37313426856874901938110133384605074194791927500210707276948918975046371522830901596065044944558427864187196889881993164303255749681644627614963632713725183364319410825898054225147061624559894980555489070322738683900143562848200257354774040241218537613789091499134051387344396560066242901217378861764936185029", 10).unwrap(); assert!(!is_safe_prime(&p0)); let p1 = Int::from_str_radix("74626853713749803876220266769210148389583855000421414553897837950092743045661803192130089889116855728374393779763986328606511499363289255229927265427450366728638821651796108450294123249119789961110978140645477367800287125696400514709548080482437075227578182998268102774688793120132485802434757723529872370059", 10).unwrap(); assert!(is_safe_prime(&p1)); let p2 = Int::from_str_radix("149253707427499607752440533538420296779167710000842829107795675900185486091323606384260179778233711456748787559527972657213022998726578510459854530854900733457277643303592216900588246498239579922221956281290954735600574251392801029419096160964874150455156365996536205549377586240264971604869515447059744740119", 10).unwrap(); assert!(is_safe_prime(&p2)); let p3 = Int::from_str_radix("298507414854999215504881067076840593558335420001685658215591351800370972182647212768520359556467422913497575119055945314426045997453157020919709061709801466914555286607184433801176492996479159844443912562581909471201148502785602058838192321929748300910312731993072411098755172480529943209739030894119489480239", 10).unwrap(); assert!(is_safe_prime(&p3)); let p4 = Int::from_str_radix("4806876214089177439121678559764069543282270755154137981051366776821330958611719328037311759924923156830623290278296826263863902327008664143707117531049168010908663795201825132050017581985031718536424081509084930569115857201636971728388275433540277562846153879803474020036767852693656753257597801227199822164846876100177774044259379232968071371318658371230787073384750022830829873718254139779006439569882904712552834431199870749249168775012460891012776977366721903", 10).unwrap(); assert!(is_safe_prime(&p4)); } }