fix: proper error handling
This commit is contained in:
parent
1a6c9a9487
commit
73cbdd7c0d
@ -1,6 +1,6 @@
|
||||
use rand::Rng;
|
||||
|
||||
use errors::Result;
|
||||
use errors::{Error, Result};
|
||||
use key::RSAPrivateKey;
|
||||
use math::ModInverse;
|
||||
use num_bigint::BigUint;
|
||||
@ -27,7 +27,7 @@ pub fn generate_multi_prime_key<R: Rng>(
|
||||
bit_size: usize,
|
||||
) -> Result<RSAPrivateKey> {
|
||||
if nprimes < 2 {
|
||||
return Err(format_err!("nprimes must be >= 2"));
|
||||
return Err(Error::NprimesTooSmall);
|
||||
}
|
||||
|
||||
if bit_size < 64 {
|
||||
@ -40,11 +40,9 @@ pub fn generate_multi_prime_key<R: Rng>(
|
||||
// Use a factor of two to ensure taht key generation terminates in a
|
||||
// reasonable amount of time.
|
||||
pi /= 2f64;
|
||||
println!("{} < {}", pi, nprimes as f64);
|
||||
|
||||
if pi < nprimes as f64 {
|
||||
return Err(format_err!(
|
||||
"too few primes of given length to generate an RSA key"
|
||||
));
|
||||
return Err(Error::TooFewPrimes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,32 @@
|
||||
use failure::Error;
|
||||
|
||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
||||
|
||||
/// Error types
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum Error {
|
||||
#[fail(display = "invalid padding scheme")]
|
||||
InvalidPaddingScheme,
|
||||
#[fail(display = "decryption error")]
|
||||
Decryption,
|
||||
#[fail(display = "verification error")]
|
||||
Verification,
|
||||
#[fail(display = "message too long")]
|
||||
MessageTooLong,
|
||||
#[fail(display = "input must be hashed")]
|
||||
InputNotHashed,
|
||||
#[fail(display = "nprimes must be >= 2")]
|
||||
NprimesTooSmall,
|
||||
#[fail(display = "too few primes of given length to generate an RSA key")]
|
||||
TooFewPrimes,
|
||||
#[fail(display = "invalid prime value")]
|
||||
InvalidPrime,
|
||||
#[fail(display = "invalid modulus")]
|
||||
InvalidModulus,
|
||||
#[fail(display = "invalid exponent")]
|
||||
InvalidExponent,
|
||||
#[fail(display = "public exponent too small")]
|
||||
PublicExponentTooSmall,
|
||||
#[fail(display = "public exponent too large")]
|
||||
PublicExponentTooLarge,
|
||||
#[fail(display = "internal error")]
|
||||
Internal,
|
||||
}
|
||||
|
48
src/key.rs
48
src/key.rs
@ -4,7 +4,7 @@ use num_traits::{FromPrimitive, One, Signed, Zero};
|
||||
use rand::{Rng, ThreadRng};
|
||||
|
||||
use algorithms::generate_multi_prime_key;
|
||||
use errors::Result;
|
||||
use errors::{Error, Result};
|
||||
use hash::Hash;
|
||||
use math::ModInverse;
|
||||
use padding::PaddingScheme;
|
||||
@ -102,10 +102,7 @@ impl RSAPublicKey {
|
||||
match padding {
|
||||
PaddingScheme::PKCS1v15 => pkcs1v15::encrypt(rng, self, msg),
|
||||
PaddingScheme::OAEP => unimplemented!("not yet implemented"),
|
||||
_ => Err(format_err!(
|
||||
"invalid padding scheme for decryption: {:?}",
|
||||
padding
|
||||
)),
|
||||
_ => Err(Error::InvalidPaddingScheme),
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,10 +120,7 @@ impl RSAPublicKey {
|
||||
match padding {
|
||||
PaddingScheme::PKCS1v15 => pkcs1v15::verify(self, hash, hashed, sig),
|
||||
PaddingScheme::PSS => unimplemented!("not yet implemented"),
|
||||
_ => Err(format_err!(
|
||||
"invalid padding scheme for decryption: {:?}",
|
||||
padding
|
||||
)),
|
||||
_ => Err(Error::InvalidPaddingScheme),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -241,12 +235,12 @@ impl RSAPrivateKey {
|
||||
for prime in &self.primes {
|
||||
// Any primes ≤ 1 will cause divide-by-zero panics later.
|
||||
if prime < &BigUint::one() {
|
||||
return Err(format_err!("invalid prime value"));
|
||||
return Err(Error::InvalidPrime);
|
||||
}
|
||||
m *= prime;
|
||||
}
|
||||
if m != self.n {
|
||||
return Err(format_err!("invalid modulus"));
|
||||
return Err(Error::InvalidModulus);
|
||||
}
|
||||
|
||||
// Check that de ≡ 1 mod p-1, for each prime.
|
||||
@ -259,7 +253,7 @@ impl RSAPrivateKey {
|
||||
for prime in &self.primes {
|
||||
let congruence: BigUint = &de % (prime - BigUint::one());
|
||||
if !congruence.is_one() {
|
||||
return Err(format_err!("invalid exponents"));
|
||||
return Err(Error::InvalidExponent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,10 +266,7 @@ impl RSAPrivateKey {
|
||||
// need to pass any Rng as the type arg, so the type checker is happy, it is not actually used for anything
|
||||
PaddingScheme::PKCS1v15 => pkcs1v15::decrypt::<ThreadRng>(None, self, ciphertext),
|
||||
PaddingScheme::OAEP => unimplemented!("not yet implemented"),
|
||||
_ => Err(format_err!(
|
||||
"invalid padding scheme for decryption: {:?}",
|
||||
padding
|
||||
)),
|
||||
_ => Err(Error::InvalidPaddingScheme),
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,10 +281,7 @@ impl RSAPrivateKey {
|
||||
match padding {
|
||||
PaddingScheme::PKCS1v15 => pkcs1v15::decrypt(Some(rng), self, ciphertext),
|
||||
PaddingScheme::OAEP => unimplemented!("not yet implemented"),
|
||||
_ => Err(format_err!(
|
||||
"invalid padding scheme for decryption: {:?}",
|
||||
padding
|
||||
)),
|
||||
_ => Err(Error::InvalidPaddingScheme),
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,10 +295,7 @@ impl RSAPrivateKey {
|
||||
match padding {
|
||||
PaddingScheme::PKCS1v15 => pkcs1v15::sign::<ThreadRng, _>(None, self, hash, digest),
|
||||
PaddingScheme::PSS => unimplemented!("not yet implemented"),
|
||||
_ => Err(format_err!(
|
||||
"invalid padding scheme for decryption: {:?}",
|
||||
padding
|
||||
)),
|
||||
_ => Err(Error::InvalidPaddingScheme),
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,10 +311,7 @@ impl RSAPrivateKey {
|
||||
match padding {
|
||||
PaddingScheme::PKCS1v15 => pkcs1v15::sign(Some(rng), self, hash, digest),
|
||||
PaddingScheme::PSS => unimplemented!("not yet implemented"),
|
||||
_ => Err(format_err!(
|
||||
"invalid padding scheme for decryption: {:?}",
|
||||
padding
|
||||
)),
|
||||
_ => Err(Error::InvalidPaddingScheme),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -337,11 +319,11 @@ impl RSAPrivateKey {
|
||||
#[inline]
|
||||
pub fn check_public(public_key: &impl PublicKey) -> Result<()> {
|
||||
if public_key.e() < 2 {
|
||||
return Err(format_err!("public exponent too small"));
|
||||
return Err(Error::PublicExponentTooSmall);
|
||||
}
|
||||
|
||||
if public_key.e() > 1 << (31 - 1) {
|
||||
return Err(format_err!("public exponent too large"));
|
||||
return Err(Error::PublicExponentTooLarge);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -362,11 +344,11 @@ pub fn decrypt<R: Rng>(
|
||||
c: &BigUint,
|
||||
) -> Result<BigUint> {
|
||||
if c > priv_key.n() {
|
||||
return Err(format_err!("decryption error"));
|
||||
return Err(Error::Decryption);
|
||||
}
|
||||
|
||||
if priv_key.n().is_zero() {
|
||||
return Err(format_err!("decryption error"));
|
||||
return Err(Error::Decryption);
|
||||
}
|
||||
|
||||
let mut c = c.clone();
|
||||
@ -456,7 +438,7 @@ pub fn decrypt_and_check<R: Rng>(
|
||||
// calculated, which should match the original ciphertext.
|
||||
let check = encrypt(priv_key, &m);
|
||||
if c != &check {
|
||||
return Err(format_err!("internal error"));
|
||||
return Err(Error::Internal);
|
||||
}
|
||||
|
||||
Ok(m)
|
||||
|
@ -2,7 +2,7 @@ use num_bigint::BigUint;
|
||||
use rand::Rng;
|
||||
use subtle::{Choice, ConditionallyAssignable, ConditionallySelectable, ConstantTimeEq};
|
||||
|
||||
use errors::Result;
|
||||
use errors::{Error, Result};
|
||||
use hash::Hash;
|
||||
use key::{self, PublicKey, RSAPrivateKey};
|
||||
|
||||
@ -15,7 +15,7 @@ pub fn encrypt<R: Rng, K: PublicKey>(rng: &mut R, pub_key: &K, msg: &[u8]) -> Re
|
||||
|
||||
let k = pub_key.size();
|
||||
if msg.len() > k - 11 {
|
||||
return Err(format_err!("message too long"));
|
||||
return Err(Error::MessageTooLong);
|
||||
}
|
||||
|
||||
// EM = 0x00 || 0x02 || PS || 0x00 || M
|
||||
@ -50,7 +50,7 @@ pub fn decrypt<R: Rng>(
|
||||
|
||||
let (valid, out, index) = decrypt_inner(rng, priv_key, ciphertext)?;
|
||||
if valid == 0 {
|
||||
return Err(format_err!("decryption error"));
|
||||
return Err(Error::Decryption);
|
||||
}
|
||||
|
||||
Ok(out[index as usize..].to_vec())
|
||||
@ -81,7 +81,7 @@ pub fn sign<R: Rng, H: Hash>(
|
||||
let t_len = prefix.len() + hash_len;
|
||||
let k = priv_key.size();
|
||||
if k < t_len + 11 {
|
||||
return Err(format_err!("message too long"));
|
||||
return Err(Error::MessageTooLong);
|
||||
}
|
||||
|
||||
// EM = 0x00 || 0x01 || PS || 0x00 || T
|
||||
@ -113,7 +113,7 @@ pub fn verify<H: Hash, K: PublicKey>(
|
||||
let t_len = prefix.len() + hash_len;
|
||||
let k = pub_key.size();
|
||||
if k < t_len + 11 {
|
||||
return Err(format_err!("verification error"));
|
||||
return Err(Error::Verification);
|
||||
}
|
||||
|
||||
let c = BigUint::from_bytes_be(sig);
|
||||
@ -132,7 +132,7 @@ pub fn verify<H: Hash, K: PublicKey>(
|
||||
}
|
||||
|
||||
if ok.unwrap_u8() != 1 {
|
||||
return Err(format_err!("verification error"));
|
||||
return Err(Error::Verification);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -144,7 +144,7 @@ fn hash_info<H: Hash>(hash: Option<&H>, digest_len: usize) -> Result<(usize, Vec
|
||||
Some(hash) => {
|
||||
let hash_len = hash.size();
|
||||
if digest_len != hash_len {
|
||||
return Err(format_err!("input must be a hashed messsage"));
|
||||
return Err(Error::InputNotHashed);
|
||||
}
|
||||
|
||||
Ok((hash_len, hash.asn1_prefix()))
|
||||
@ -178,7 +178,7 @@ fn decrypt_inner<R: Rng>(
|
||||
) -> Result<(u8, Vec<u8>, u32)> {
|
||||
let k = priv_key.size();
|
||||
if k < 11 {
|
||||
return Err(format_err!("decryption error"));
|
||||
return Err(Error::Decryption);
|
||||
}
|
||||
|
||||
let c = BigUint::from_bytes_be(ciphertext);
|
||||
|
Loading…
x
Reference in New Issue
Block a user