Implemented custom Error and Result types to be returned
Like a good library ought to be, Pumpkin now returns actual Errors, rather than panicking.
This commit is contained in:
parent
b6134a6cfd
commit
ec63237e41
5 changed files with 115 additions and 84 deletions
|
@ -1,6 +1,8 @@
|
|||
use ramp::{Int, RandomInt};
|
||||
use rand::{OsRng, thread_rng};
|
||||
|
||||
use error::{Error, Result};
|
||||
|
||||
static SMALL_PRIMES: [u32; 999] = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
|
||||
61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127,
|
||||
131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191,
|
||||
|
@ -101,8 +103,10 @@ static SMALL_PRIMES: [u32; 999] = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
|
|||
|
||||
/// Constructs a new prime number with the size of `bit_length` bits, sourced
|
||||
/// from an already-initialized `OsRng`.
|
||||
pub fn gen_prime(bit_length: usize, rngesus: &mut OsRng) -> Int {
|
||||
debug_assert!(bit_length >= 512);
|
||||
pub fn gen_prime(bit_length: usize, rngesus: &mut OsRng) -> Result {
|
||||
if bit_length < 512 {
|
||||
Err(Error::BitLength(bit_length))
|
||||
} else {
|
||||
let mut candidate: Int;
|
||||
|
||||
// In order to remove as much bias from the system as possible, test
|
||||
|
@ -135,11 +139,10 @@ pub fn gen_prime(bit_length: usize, rngesus: &mut OsRng) -> Int {
|
|||
}
|
||||
|
||||
if found_prime {
|
||||
break;
|
||||
return Ok(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
candidate
|
||||
}
|
||||
|
||||
/// Runs the following three tests on a given `candidate` to determine
|
||||
|
|
46
src/error.rs
Normal file
46
src/error.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use ramp::Int;
|
||||
use std::{error, fmt, io, result};
|
||||
|
||||
pub type Result = result::Result<Int, Error>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
OsRngInitialization(io::Error),
|
||||
BitLength(usize)
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Error::OsRngInitialization(ref err) => {
|
||||
write!(f,
|
||||
"Error initializing the random number generator: {}",
|
||||
err
|
||||
)
|
||||
},
|
||||
Error::BitLength(length) => {
|
||||
write!(f,
|
||||
"The given bit length is too small; must be at least 512: {}",
|
||||
length
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
Error::OsRngInitialization(ref err) => err.description(),
|
||||
Error::BitLength(_) => {
|
||||
"The given bit length was less than 512"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(err: io::Error) -> Error {
|
||||
Error::OsRngInitialization(err)
|
||||
}
|
||||
}
|
|
@ -54,6 +54,7 @@ extern crate rand;
|
|||
extern crate test;
|
||||
|
||||
mod common;
|
||||
mod error;
|
||||
pub mod prime;
|
||||
pub mod safe_prime;
|
||||
|
||||
|
|
40
src/prime.rs
40
src/prime.rs
|
@ -1,9 +1,9 @@
|
|||
//! Generates cryptographically secure prime numbers.
|
||||
|
||||
use ramp::Int;
|
||||
use rand::OsRng;
|
||||
|
||||
pub use common::gen_prime as from_rng;
|
||||
use error::{Error, Result};
|
||||
|
||||
/// Constructs a new prime number with a size of `bit_length` bits.
|
||||
///
|
||||
|
@ -11,40 +11,22 @@ pub use common::gen_prime as from_rng;
|
|||
/// `from_rng()` function.
|
||||
///
|
||||
/// Note: the `bit_length` MUST be at least 512-bits.
|
||||
pub fn new(bit_length: usize) -> Int {
|
||||
assert!(bit_length >= 512);
|
||||
let mut rngesus = match OsRng::new() {
|
||||
Ok(rng) => rng,
|
||||
Err(reason) => panic!("Error initializing RNG: {}", reason),
|
||||
};
|
||||
|
||||
from_rng(bit_length, &mut rngesus)
|
||||
pub fn new(bit_length: usize) -> Result {
|
||||
if bit_length < 512 {
|
||||
Err(Error::BitLength(bit_length))
|
||||
} else {
|
||||
let mut rngesus = try!(OsRng::new());
|
||||
Ok(try!(from_rng(bit_length, &mut rngesus)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ramp::Int;
|
||||
use super::{fermat, miller_rabin};
|
||||
|
||||
#[test]
|
||||
fn test_fermat_pass() {
|
||||
assert!(fermat(&Int::from(7919)));
|
||||
}
|
||||
use super::{new, from_rng};
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_fermat_fail() {
|
||||
assert!(fermat(&Int::from(7920)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_miller_rabin_pass() {
|
||||
assert!(miller_rabin(&Int::from(7919), 5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_miller_rabin_fail() {
|
||||
assert!(miller_rabin(&Int::from(7920), 5));
|
||||
fn test_prime_bad_bit_length() {
|
||||
new(511);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use ramp::Int;
|
|||
use rand::OsRng;
|
||||
|
||||
pub use common::{gen_prime, is_prime};
|
||||
use error::{Error, Result};
|
||||
|
||||
/// Constructs a new `SafePrime` with a size of `bit_length` bits.
|
||||
///
|
||||
|
@ -11,30 +12,27 @@ pub use common::{gen_prime, is_prime};
|
|||
/// `SafePrime::from_rng()` method.
|
||||
///
|
||||
/// Note: the `bit_length` MUST be at least 512-bits.
|
||||
pub fn new(bit_length: usize) -> Int {
|
||||
debug_assert!(bit_length >= 512);
|
||||
let mut rngesus = match OsRng::new() {
|
||||
Ok(rng) => rng,
|
||||
Err(reason) => panic!("Error initializing RNG: {}", reason),
|
||||
};
|
||||
|
||||
from_rng(bit_length, &mut rngesus)
|
||||
pub fn new(bit_length: usize) -> Result {
|
||||
if bit_length < 512 {
|
||||
Err(Error::BitLength(bit_length))
|
||||
} else {
|
||||
let mut rngesus = try!(OsRng::new());
|
||||
Ok(try!(from_rng(bit_length, &mut rngesus)))
|
||||
}
|
||||
}
|
||||
|
||||
/// 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) -> Int {
|
||||
debug_assert!(bit_length >= 512);
|
||||
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;
|
||||
|
||||
// Circumvent uninitialized warning (technically valid but compiler
|
||||
// cannot determine that `clone_from` will fill the value.
|
||||
let mut candidate_p: Int = Int::zero();
|
||||
|
||||
loop {
|
||||
candidate = gen_prime(bit_length, &mut rngesus);
|
||||
candidate = try!(gen_prime(bit_length, &mut rngesus));
|
||||
|
||||
candidate_p.clone_from(&candidate);
|
||||
let mut candidate_p = (&candidate).clone();
|
||||
candidate_p -= 1_usize;
|
||||
candidate_p /= 2_usize;
|
||||
|
||||
|
@ -43,5 +41,6 @@ pub fn from_rng(bit_length: usize, mut rngesus: &mut OsRng) -> Int {
|
|||
}
|
||||
}
|
||||
|
||||
candidate
|
||||
Ok(candidate)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue