Introduce raw::{DecryptionPrimitive, EncryptionPrimitive}
This commit is contained in:
parent
d26bb6a057
commit
826ea30004
@ -12,6 +12,7 @@ use crate::errors::{Error, Result};
|
||||
use crate::hash::Hash;
|
||||
use crate::padding::PaddingScheme;
|
||||
use crate::pkcs1v15;
|
||||
use crate::raw::EncryptionPrimitive;
|
||||
|
||||
lazy_static! {
|
||||
static ref MIN_PUB_EXPONENT: BigUint = BigUint::from_u64(2).unwrap();
|
||||
@ -126,7 +127,7 @@ impl From<RSAPrivateKey> for RSAPublicKey {
|
||||
}
|
||||
|
||||
/// Generic trait for operations on a public key.
|
||||
pub trait PublicKey {
|
||||
pub trait PublicKey: EncryptionPrimitive {
|
||||
/// Returns the modulus of the key.
|
||||
fn n(&self) -> &BigUint;
|
||||
/// Returns the public exponent of the key.
|
||||
|
@ -62,8 +62,9 @@ pub mod padding;
|
||||
pub use pem;
|
||||
|
||||
mod key;
|
||||
mod pkcs1v15;
|
||||
mod parse;
|
||||
mod pkcs1v15;
|
||||
mod raw;
|
||||
|
||||
pub use self::key::{PublicKey, RSAPrivateKey, RSAPublicKey};
|
||||
pub use self::padding::PaddingScheme;
|
||||
|
@ -1,12 +1,10 @@
|
||||
use num_bigint::BigUint;
|
||||
use rand::Rng;
|
||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use crate::errors::{Error, Result};
|
||||
use crate::hash::Hash;
|
||||
use crate::internals;
|
||||
use crate::key::{self, PublicKey, RSAPrivateKey};
|
||||
use crate::raw::DecryptionPrimitive;
|
||||
|
||||
// Encrypts the given message with RSA and the padding
|
||||
// scheme from PKCS#1 v1.5. The message must be no longer than the
|
||||
@ -27,17 +25,7 @@ pub fn encrypt<R: Rng, K: PublicKey>(rng: &mut R, pub_key: &K, msg: &[u8]) -> Re
|
||||
em[k - msg.len() - 1] = 0;
|
||||
em[k - msg.len()..].copy_from_slice(msg);
|
||||
|
||||
{
|
||||
let mut m = BigUint::from_bytes_be(&em);
|
||||
let mut c = internals::encrypt(pub_key, &m).to_bytes_be();
|
||||
copy_with_left_pad(&mut em, &c);
|
||||
|
||||
// clear out tmp values
|
||||
m.zeroize();
|
||||
c.zeroize();
|
||||
}
|
||||
|
||||
Ok(em)
|
||||
pub_key.raw_encryption_primitive(&em)
|
||||
}
|
||||
|
||||
/// Decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
|
||||
@ -100,18 +88,7 @@ pub fn sign<R: Rng, H: Hash>(
|
||||
em[k - t_len..k - hash_len].copy_from_slice(&prefix);
|
||||
em[k - hash_len..k].copy_from_slice(hashed);
|
||||
|
||||
{
|
||||
let mut m = BigUint::from_bytes_be(&em);
|
||||
let mut c = internals::decrypt_and_check(rng, priv_key, &m)?.to_bytes_be();
|
||||
|
||||
copy_with_left_pad(&mut em, &c);
|
||||
|
||||
// clear tmp values
|
||||
m.zeroize();
|
||||
c.zeroize();
|
||||
}
|
||||
|
||||
Ok(em)
|
||||
priv_key.raw_decryption_primitive(rng, &em)
|
||||
}
|
||||
|
||||
/// Verifies an RSA PKCS#1 v1.5 signature.
|
||||
@ -130,11 +107,7 @@ pub fn verify<H: Hash, K: PublicKey>(
|
||||
return Err(Error::Verification);
|
||||
}
|
||||
|
||||
let em = {
|
||||
let c = BigUint::from_bytes_be(sig);
|
||||
let m = internals::encrypt(pub_key, &c).to_bytes_be();
|
||||
internals::left_pad(&m, k)
|
||||
};
|
||||
let em = pub_key.raw_encryption_primitive(sig)?;
|
||||
|
||||
// EM = 0x00 || 0x01 || PS || 0x00 || T
|
||||
let mut ok = em[0].ct_eq(&0u8);
|
||||
@ -170,16 +143,6 @@ fn hash_info<H: Hash>(hash: Option<&H>, digest_len: usize) -> Result<(usize, Vec
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn copy_with_left_pad(dest: &mut [u8], src: &[u8]) {
|
||||
// left pad with zeros
|
||||
let padding_bytes = dest.len() - src.len();
|
||||
for el in dest.iter_mut().take(padding_bytes) {
|
||||
*el = 0;
|
||||
}
|
||||
dest[padding_bytes..].copy_from_slice(src);
|
||||
}
|
||||
|
||||
/// Decrypts ciphertext using `priv_key` and blinds the operation if
|
||||
/// `rng` is given. It returns one or zero in valid that indicates whether the
|
||||
/// plaintext was correctly structured. In either case, the plaintext is
|
||||
@ -197,16 +160,7 @@ fn decrypt_inner<R: Rng>(
|
||||
return Err(Error::Decryption);
|
||||
}
|
||||
|
||||
let em = {
|
||||
let mut c = BigUint::from_bytes_be(ciphertext);
|
||||
let mut m = internals::decrypt(rng, priv_key, &c)?;
|
||||
let em = internals::left_pad(&m.to_bytes_be(), k);
|
||||
|
||||
c.zeroize();
|
||||
m.zeroize();
|
||||
|
||||
em
|
||||
};
|
||||
let em = priv_key.raw_decryption_primitive(rng, ciphertext)?;
|
||||
|
||||
let first_byte_is_zero = em[0].ct_eq(&0u8);
|
||||
let second_byte_is_two = em[1].ct_eq(&2u8);
|
||||
@ -259,6 +213,7 @@ mod tests {
|
||||
use super::*;
|
||||
use base64;
|
||||
use hex;
|
||||
use num_bigint::BigUint;
|
||||
use num_traits::FromPrimitive;
|
||||
use num_traits::Num;
|
||||
use rand::thread_rng;
|
||||
|
85
src/raw.rs
Normal file
85
src/raw.rs
Normal file
@ -0,0 +1,85 @@
|
||||
use num_bigint::BigUint;
|
||||
use rand::Rng;
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use crate::errors::Result;
|
||||
use crate::internals;
|
||||
use crate::key::{PublicKey, RSAPrivateKey, RSAPublicKey};
|
||||
|
||||
pub trait EncryptionPrimitive {
|
||||
/// Do NOT use directly! Only for implementors.
|
||||
fn raw_encryption_primitive(&self, plaintext: &[u8]) -> Result<Vec<u8>>;
|
||||
}
|
||||
|
||||
pub trait DecryptionPrimitive {
|
||||
/// Do NOT use directly! Only for implementors.
|
||||
fn raw_decryption_primitive<R: Rng>(
|
||||
&self,
|
||||
rng: Option<&mut R>,
|
||||
ciphertext: &[u8],
|
||||
) -> Result<Vec<u8>>;
|
||||
}
|
||||
|
||||
impl EncryptionPrimitive for RSAPublicKey {
|
||||
fn raw_encryption_primitive(&self, plaintext: &[u8]) -> Result<Vec<u8>> {
|
||||
let mut m = BigUint::from_bytes_be(plaintext);
|
||||
let mut c = internals::encrypt(self, &m);
|
||||
let mut c_bytes = c.to_bytes_be();
|
||||
let ciphertext = internals::left_pad(&c_bytes, self.size());
|
||||
|
||||
// clear out tmp values
|
||||
m.zeroize();
|
||||
c.zeroize();
|
||||
c_bytes.zeroize();
|
||||
|
||||
Ok(ciphertext)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> EncryptionPrimitive for &'a RSAPublicKey {
|
||||
fn raw_encryption_primitive(&self, plaintext: &[u8]) -> Result<Vec<u8>> {
|
||||
(*self).raw_encryption_primitive(plaintext)
|
||||
}
|
||||
}
|
||||
|
||||
impl EncryptionPrimitive for RSAPrivateKey {
|
||||
fn raw_encryption_primitive(&self, plaintext: &[u8]) -> Result<Vec<u8>> {
|
||||
let mut m = BigUint::from_bytes_be(plaintext);
|
||||
let mut c = internals::encrypt(self, &m);
|
||||
let mut c_bytes = c.to_bytes_be();
|
||||
let ciphertext = internals::left_pad(&c_bytes, self.size());
|
||||
|
||||
// clear out tmp values
|
||||
m.zeroize();
|
||||
c.zeroize();
|
||||
c_bytes.zeroize();
|
||||
|
||||
Ok(ciphertext)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> EncryptionPrimitive for &'a RSAPrivateKey {
|
||||
fn raw_encryption_primitive(&self, plaintext: &[u8]) -> Result<Vec<u8>> {
|
||||
(*self).raw_encryption_primitive(plaintext)
|
||||
}
|
||||
}
|
||||
|
||||
impl DecryptionPrimitive for RSAPrivateKey {
|
||||
fn raw_decryption_primitive<R: Rng>(
|
||||
&self,
|
||||
rng: Option<&mut R>,
|
||||
ciphertext: &[u8],
|
||||
) -> Result<Vec<u8>> {
|
||||
let mut c = BigUint::from_bytes_be(ciphertext);
|
||||
let mut m = internals::decrypt_and_check(rng, self, &c)?;
|
||||
let mut m_bytes = m.to_bytes_be();
|
||||
let plaintext = internals::left_pad(&m_bytes, self.size());
|
||||
|
||||
// clear tmp values
|
||||
c.zeroize();
|
||||
m.zeroize();
|
||||
m_bytes.zeroize();
|
||||
|
||||
Ok(plaintext)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user