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::hash::Hash;
|
||||||
use crate::padding::PaddingScheme;
|
use crate::padding::PaddingScheme;
|
||||||
use crate::pkcs1v15;
|
use crate::pkcs1v15;
|
||||||
|
use crate::raw::EncryptionPrimitive;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref MIN_PUB_EXPONENT: BigUint = BigUint::from_u64(2).unwrap();
|
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.
|
/// Generic trait for operations on a public key.
|
||||||
pub trait PublicKey {
|
pub trait PublicKey: EncryptionPrimitive {
|
||||||
/// Returns the modulus of the key.
|
/// Returns the modulus of the key.
|
||||||
fn n(&self) -> &BigUint;
|
fn n(&self) -> &BigUint;
|
||||||
/// Returns the public exponent of the key.
|
/// Returns the public exponent of the key.
|
||||||
|
@ -58,12 +58,13 @@ pub mod hash;
|
|||||||
/// Supported padding schemes.
|
/// Supported padding schemes.
|
||||||
pub mod padding;
|
pub mod padding;
|
||||||
|
|
||||||
#[cfg(feature="pem")]
|
#[cfg(feature = "pem")]
|
||||||
pub use pem;
|
pub use pem;
|
||||||
|
|
||||||
mod key;
|
mod key;
|
||||||
mod pkcs1v15;
|
|
||||||
mod parse;
|
mod parse;
|
||||||
|
mod pkcs1v15;
|
||||||
|
mod raw;
|
||||||
|
|
||||||
pub use self::key::{PublicKey, RSAPrivateKey, RSAPublicKey};
|
pub use self::key::{PublicKey, RSAPrivateKey, RSAPublicKey};
|
||||||
pub use self::padding::PaddingScheme;
|
pub use self::padding::PaddingScheme;
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
use num_bigint::BigUint;
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
|
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
|
||||||
use zeroize::Zeroize;
|
|
||||||
|
|
||||||
use crate::errors::{Error, Result};
|
use crate::errors::{Error, Result};
|
||||||
use crate::hash::Hash;
|
use crate::hash::Hash;
|
||||||
use crate::internals;
|
|
||||||
use crate::key::{self, PublicKey, RSAPrivateKey};
|
use crate::key::{self, PublicKey, RSAPrivateKey};
|
||||||
|
use crate::raw::DecryptionPrimitive;
|
||||||
|
|
||||||
// Encrypts the given message with RSA and the padding
|
// Encrypts the given message with RSA and the padding
|
||||||
// scheme from PKCS#1 v1.5. The message must be no longer than the
|
// 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() - 1] = 0;
|
||||||
em[k - msg.len()..].copy_from_slice(msg);
|
em[k - msg.len()..].copy_from_slice(msg);
|
||||||
|
|
||||||
{
|
pub_key.raw_encryption_primitive(&em)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
|
/// 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 - t_len..k - hash_len].copy_from_slice(&prefix);
|
||||||
em[k - hash_len..k].copy_from_slice(hashed);
|
em[k - hash_len..k].copy_from_slice(hashed);
|
||||||
|
|
||||||
{
|
priv_key.raw_decryption_primitive(rng, &em)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verifies an RSA PKCS#1 v1.5 signature.
|
/// Verifies an RSA PKCS#1 v1.5 signature.
|
||||||
@ -130,11 +107,7 @@ pub fn verify<H: Hash, K: PublicKey>(
|
|||||||
return Err(Error::Verification);
|
return Err(Error::Verification);
|
||||||
}
|
}
|
||||||
|
|
||||||
let em = {
|
let em = pub_key.raw_encryption_primitive(sig)?;
|
||||||
let c = BigUint::from_bytes_be(sig);
|
|
||||||
let m = internals::encrypt(pub_key, &c).to_bytes_be();
|
|
||||||
internals::left_pad(&m, k)
|
|
||||||
};
|
|
||||||
|
|
||||||
// EM = 0x00 || 0x01 || PS || 0x00 || T
|
// EM = 0x00 || 0x01 || PS || 0x00 || T
|
||||||
let mut ok = em[0].ct_eq(&0u8);
|
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
|
/// Decrypts ciphertext using `priv_key` and blinds the operation if
|
||||||
/// `rng` is given. It returns one or zero in valid that indicates whether the
|
/// `rng` is given. It returns one or zero in valid that indicates whether the
|
||||||
/// plaintext was correctly structured. In either case, the plaintext is
|
/// plaintext was correctly structured. In either case, the plaintext is
|
||||||
@ -197,16 +160,7 @@ fn decrypt_inner<R: Rng>(
|
|||||||
return Err(Error::Decryption);
|
return Err(Error::Decryption);
|
||||||
}
|
}
|
||||||
|
|
||||||
let em = {
|
let em = priv_key.raw_decryption_primitive(rng, ciphertext)?;
|
||||||
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 first_byte_is_zero = em[0].ct_eq(&0u8);
|
let first_byte_is_zero = em[0].ct_eq(&0u8);
|
||||||
let second_byte_is_two = em[1].ct_eq(&2u8);
|
let second_byte_is_two = em[1].ct_eq(&2u8);
|
||||||
@ -259,6 +213,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use base64;
|
use base64;
|
||||||
use hex;
|
use hex;
|
||||||
|
use num_bigint::BigUint;
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use num_traits::Num;
|
use num_traits::Num;
|
||||||
use rand::thread_rng;
|
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