Merge pull request #4 from tiehuis/master
Add SafePrime initial implementation
This commit is contained in:
commit
7c6a418f3e
2 changed files with 67 additions and 0 deletions
|
@ -39,6 +39,7 @@ extern crate test;
|
||||||
|
|
||||||
mod prime;
|
mod prime;
|
||||||
pub use prime::Prime;
|
pub use prime::Prime;
|
||||||
|
pub use prime::SafePrime;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
66
src/prime.rs
66
src/prime.rs
|
@ -203,6 +203,72 @@ impl Prime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An arbitrarily-length safe prime number, suitable for cryptographic purposes.
|
||||||
|
///
|
||||||
|
/// A safe prime is a prime of the form `p = 2q + 1`, where `q` is also prime.
|
||||||
|
///
|
||||||
|
/// `SafePrime`s are constructed using similar methods as those in `Prime`. An
|
||||||
|
/// extra iterative check is constructed on each generated `Prime` to ensure it
|
||||||
|
/// satisfies the safe prime condition. As a result, generation of `SafePrime`s
|
||||||
|
/// can be quite slow, and should only be used if absolutely necessary.
|
||||||
|
custom_derive! {
|
||||||
|
/// A cryptographically secure prime number.
|
||||||
|
#[derive(NewtypeDebug, NewtypeDisplay, NewtypeBinary, NewtypeOctal,
|
||||||
|
NewtypeLowerHex, NewtypeUpperHex, NewtypeAdd, NewtypeAdd(Int),
|
||||||
|
NewtypeSub, NewtypeSub(Int), NewtypeMul, NewtypeMul(Int), NewtypeDiv,
|
||||||
|
NewtypeDiv(Int), NewtypeRem, NewtypeRem(Int), NewtypeBitAnd,
|
||||||
|
NewtypeBitAnd(Int), NewtypeBitOr, NewtypeBitOr(Int), NewtypeBitXor,
|
||||||
|
NewtypeBitXor(Int)
|
||||||
|
)]
|
||||||
|
pub struct SafePrime(pub Int);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SafePrime {
|
||||||
|
/// 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) -> SafePrime {
|
||||||
|
debug_assert!(bit_length >= 512);
|
||||||
|
let mut rngesus = match OsRng::new() {
|
||||||
|
Ok(rng) => rng,
|
||||||
|
Err(reason) => panic!("Error initializing RNG: {}", reason),
|
||||||
|
};
|
||||||
|
|
||||||
|
SafePrime::from_rng(bit_length, &mut rngesus)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructs a new `SafePrime` with the size of `bit_length` bits, sourced
|
||||||
|
/// from an already-created `OsRng`. Not that you can **ONLY** use an
|
||||||
|
/// `OsRng`, as it uses the operating system's secure source of entropy.
|
||||||
|
pub fn from_rng(bit_length: usize, mut rngesus: &mut OsRng) -> SafePrime {
|
||||||
|
debug_assert!(bit_length >= 512);
|
||||||
|
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 = match Prime::from_rng(bit_length, &mut rngesus) {
|
||||||
|
Prime(inner) => inner
|
||||||
|
};
|
||||||
|
|
||||||
|
candidate_p.clone_from(&candidate);
|
||||||
|
candidate_p -= &Int::one();
|
||||||
|
candidate_p /= &Int::from(2);
|
||||||
|
|
||||||
|
if is_prime(&candidate_p) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SafePrime(candidate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn mod_exp(base: &Int, exponent: &Int, modulus: &Int) -> Int {
|
fn mod_exp(base: &Int, exponent: &Int, modulus: &Int) -> Int {
|
||||||
let mut result = Int::one();
|
let mut result = Int::one();
|
||||||
let mut base = base.clone();
|
let mut base = base.clone();
|
||||||
|
|
Loading…
Add table
Reference in a new issue