feat: use BigUint to represent the exponent
This commit is contained in:
parent
4d046fa70e
commit
fe7c5105fb
@ -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,
|
||||
))
|
||||
}
|
||||
|
49
src/key.rs
49
src/key.rs
@ -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) {
|
||||
|
@ -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(),
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user