feat: use BigUint to represent the exponent

This commit is contained in:
dignifiedquire 2018-11-08 18:17:59 +01:00
parent 4d046fa70e
commit fe7c5105fb
4 changed files with 41 additions and 28 deletions

View File

@ -8,7 +8,7 @@ use num_traits::{FromPrimitive, One, Zero};
use prime_rand::RandPrime;
/// Default exponent for RSA keys.
const EXP: u32 = 65537;
const EXP: u64 = 65537;
// Generates a multi-prime RSA keypair of the given bit
// size and the given random source, as suggested in [1]. Although the public
@ -96,7 +96,7 @@ pub fn generate_multi_prime_key<R: Rng>(
continue 'next;
}
let exp = BigUint::from_u64(u64::from(EXP)).unwrap();
let exp = BigUint::from_u64(EXP).unwrap();
if let Some(d) = exp.mod_inverse(totient) {
n_final = n;
d_final = d;
@ -105,6 +105,9 @@ pub fn generate_multi_prime_key<R: Rng>(
}
Ok(RSAPrivateKey::from_components(
n_final, EXP, d_final, primes,
n_final,
BigUint::from_u64(EXP).unwrap(),
d_final,
primes,
))
}

View File

@ -10,11 +10,16 @@ use math::ModInverse;
use padding::PaddingScheme;
use pkcs1v15;
lazy_static! {
static ref MIN_PUB_EXPONENT: BigUint = BigUint::from_u64(2).unwrap();
static ref MAX_PUB_EXPONENT: BigUint = BigUint::from_u64(1 << (31 - 1)).unwrap();
}
/// Represents the public part of an RSA key.
#[derive(Debug, Clone)]
pub struct RSAPublicKey {
n: BigUint,
e: u32,
e: BigUint,
}
/// Represents a whole RSA key, public and private parts.
@ -23,7 +28,7 @@ pub struct RSAPrivateKey {
/// Modulus
n: BigUint,
/// Public exponent
e: u32,
e: BigUint,
/// Private exponent
d: BigUint,
/// Prime factors of N, contains >= 2 elements.
@ -73,7 +78,7 @@ pub trait PublicKey {
/// Returns the modulus of the key.
fn n(&self) -> &BigUint;
/// Returns the public exponent of the key.
fn e(&self) -> u32;
fn e(&self) -> &BigUint;
/// Returns the modulus size in bytes. Raw signatures and ciphertexts for
/// or by this public key will have the same size.
fn size(&self) -> usize {
@ -86,8 +91,8 @@ impl PublicKey for RSAPublicKey {
&self.n
}
fn e(&self) -> u32 {
self.e
fn e(&self) -> &BigUint {
&self.e
}
}
@ -130,8 +135,8 @@ impl<'a> PublicKey for &'a RSAPublicKey {
&self.n
}
fn e(&self) -> u32 {
self.e
fn e(&self) -> &BigUint {
&self.e
}
}
@ -140,8 +145,8 @@ impl PublicKey for RSAPrivateKey {
&self.n
}
fn e(&self) -> u32 {
self.e
fn e(&self) -> &BigUint {
&self.e
}
}
@ -150,8 +155,8 @@ impl<'a> PublicKey for &'a RSAPrivateKey {
&self.n
}
fn e(&self) -> u32 {
self.e
fn e(&self) -> &BigUint {
&self.e
}
}
@ -162,7 +167,12 @@ impl RSAPrivateKey {
}
/// Constructs an RSA key pair from the individual components.
pub fn from_components(n: BigUint, e: u32, d: BigUint, primes: Vec<BigUint>) -> RSAPrivateKey {
pub fn from_components(
n: BigUint,
e: BigUint,
d: BigUint,
primes: Vec<BigUint>,
) -> RSAPrivateKey {
let mut k = RSAPrivateKey {
n,
e,
@ -248,7 +258,7 @@ impl RSAPrivateKey {
// inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) =
// exponent(/n). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1
// mod p. Thus a^de ≡ a mod n for all a coprime to n, as required.
let mut de = BigUint::from_u64(u64::from(self.e)).unwrap();
let mut de = self.e.clone();
de *= self.d.clone();
for prime in &self.primes {
let congruence: BigUint = &de % (prime - BigUint::one());
@ -318,11 +328,11 @@ impl RSAPrivateKey {
#[inline]
pub fn check_public(public_key: &impl PublicKey) -> Result<()> {
if public_key.e() < 2 {
if public_key.e() < &*MIN_PUB_EXPONENT {
return Err(Error::PublicExponentTooSmall);
}
if public_key.e() > 1 << (31 - 1) {
if public_key.e() > &*MAX_PUB_EXPONENT {
return Err(Error::PublicExponentTooLarge);
}
@ -331,8 +341,7 @@ pub fn check_public(public_key: &impl PublicKey) -> Result<()> {
#[inline]
pub fn encrypt<K: PublicKey>(key: &K, m: &BigUint) -> BigUint {
let e = BigUint::from_u64(u64::from(key.e())).unwrap();
m.modpow(&e, key.n())
m.modpow(key.e(), key.n())
}
/// Performs RSA decryption, resulting in a plaintext `BigUint`.
@ -372,7 +381,7 @@ pub fn decrypt<R: Rng>(
}
}
let e = BigUint::from_u64(u64::from(priv_key.e())).unwrap();
let e = priv_key.e();
let rpowe = r.modpow(&e, priv_key.n()); // N != 0
c = (c * &rpowe) % priv_key.n();
}
@ -468,7 +477,7 @@ mod tests {
fn test_from_into() {
let private_key = RSAPrivateKey {
n: BigUint::from_u64(100).unwrap(),
e: 200,
e: BigUint::from_u64(200).unwrap(),
d: BigUint::from_u64(123).unwrap(),
primes: vec![],
precomputed: None,
@ -476,7 +485,7 @@ mod tests {
let public_key: RSAPublicKey = private_key.into();
assert_eq!(public_key.n().to_u64(), Some(100));
assert_eq!(public_key.e(), 200);
assert_eq!(public_key.e().to_u64(), Some(200));
}
fn test_key_basics(private_key: RSAPrivateKey) {

View File

@ -237,6 +237,7 @@ mod tests {
use super::*;
use base64;
use hex;
use num_traits::FromPrimitive;
use num_traits::Num;
use rand::thread_rng;
use sha1::{Digest, Sha1};
@ -271,7 +272,7 @@ mod tests {
RSAPrivateKey::from_components(
BigUint::from_str_radix("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077", 10).unwrap(),
65537,
BigUint::from_u64(65537).unwrap(),
BigUint::from_str_radix("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861", 10).unwrap(),
vec![
BigUint::from_str_radix("98920366548084643601728869055592650835572950932266967461790948584315647051443",10).unwrap(),

View File

@ -11,10 +11,10 @@ use rand::{SeedableRng, StdRng};
use math::jacobi;
lazy_static! {
static ref BIG_1: BigUint = BigUint::one();
static ref BIG_2: BigUint = BigUint::from_u64(2).unwrap();
static ref BIG_3: BigUint = BigUint::from_u64(3).unwrap();
static ref BIG_64: BigUint = BigUint::from_u64(64).unwrap();
pub(crate) static ref BIG_1: BigUint = BigUint::one();
pub(crate) static ref BIG_2: BigUint = BigUint::from_u64(2).unwrap();
pub(crate) static ref BIG_3: BigUint = BigUint::from_u64(3).unwrap();
pub(crate) static ref BIG_64: BigUint = BigUint::from_u64(64).unwrap();
}
const PRIMES_A: u64 = 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 37;