make oaep and pss generic over keys
This commit is contained in:
parent
167080e2a4
commit
11500ed5e9
@ -110,13 +110,3 @@ pub fn generate_multi_prime_key<R: Rng>(
|
||||
primes,
|
||||
))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub 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);
|
||||
}
|
15
src/key.rs
15
src/key.rs
@ -549,7 +549,7 @@ impl RSAPrivateKey {
|
||||
pkcs1v15::decrypt::<ThreadRng, _>(None, self, ciphertext)
|
||||
}
|
||||
PaddingScheme::OAEP { mut digest, label } => {
|
||||
oaep::decrypt::<ThreadRng>(None, self, ciphertext, &mut *digest, label)
|
||||
oaep::decrypt::<ThreadRng, _>(None, self, ciphertext, &mut *digest, label)
|
||||
}
|
||||
_ => Err(Error::InvalidPaddingScheme),
|
||||
}
|
||||
@ -583,9 +583,14 @@ impl RSAPrivateKey {
|
||||
mut salt_rng,
|
||||
mut digest,
|
||||
salt_len,
|
||||
} => {
|
||||
pss::sign::<_, ThreadRng>(&mut *salt_rng, None, self, input, salt_len, &mut *digest)
|
||||
}
|
||||
} => pss::sign::<_, ThreadRng, _>(
|
||||
&mut *salt_rng,
|
||||
None,
|
||||
self,
|
||||
input,
|
||||
salt_len,
|
||||
&mut *digest,
|
||||
),
|
||||
_ => Err(Error::InvalidPaddingScheme),
|
||||
}
|
||||
}
|
||||
@ -607,7 +612,7 @@ impl RSAPrivateKey {
|
||||
mut salt_rng,
|
||||
mut digest,
|
||||
salt_len,
|
||||
} => pss::sign::<_, R>(
|
||||
} => pss::sign::<_, R, _>(
|
||||
&mut *salt_rng,
|
||||
Some(rng),
|
||||
self,
|
||||
|
15
src/oaep.rs
15
src/oaep.rs
@ -4,8 +4,7 @@ use digest::DynDigest;
|
||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
|
||||
|
||||
use crate::errors::{Error, Result};
|
||||
use crate::key::{self, PublicKey, PublicKeyParts, RSAPrivateKey};
|
||||
use crate::raw::DecryptionPrimitive;
|
||||
use crate::key::{self, PrivateKey, PublicKey};
|
||||
|
||||
fn inc_counter(counter: &mut [u8]) {
|
||||
if counter[3] == u8::max_value() {
|
||||
@ -109,7 +108,7 @@ pub fn encrypt<R: Rng, K: PublicKey>(
|
||||
mgf1_xor(db, digest, seed);
|
||||
mgf1_xor(seed, digest, db);
|
||||
|
||||
pub_key.raw_encryption_primitive(&em)
|
||||
pub_key.raw_encryption_primitive(&em, pub_key.size())
|
||||
}
|
||||
|
||||
/// Decrypts a plaintext using RSA and the padding scheme from pkcs1# OAEP
|
||||
@ -121,9 +120,9 @@ pub fn encrypt<R: Rng, K: PublicKey>(
|
||||
/// forge signatures as if they had the private key. See
|
||||
/// `decrypt_session_key` for a way of solving this problem.
|
||||
#[inline]
|
||||
pub fn decrypt<R: Rng>(
|
||||
pub fn decrypt<R: Rng, SK: PrivateKey>(
|
||||
rng: Option<&mut R>,
|
||||
priv_key: &RSAPrivateKey,
|
||||
priv_key: &SK,
|
||||
ciphertext: &[u8],
|
||||
digest: &mut dyn DynDigest,
|
||||
label: Option<String>,
|
||||
@ -145,9 +144,9 @@ pub fn decrypt<R: Rng>(
|
||||
/// in order to maintain constant memory access patterns. If the plaintext was
|
||||
/// valid then index contains the index of the original message in em.
|
||||
#[inline]
|
||||
fn decrypt_inner<R: Rng>(
|
||||
fn decrypt_inner<R: Rng, SK: PrivateKey>(
|
||||
rng: Option<&mut R>,
|
||||
priv_key: &RSAPrivateKey,
|
||||
priv_key: &SK,
|
||||
ciphertext: &[u8],
|
||||
digest: &mut dyn DynDigest,
|
||||
label: Option<String>,
|
||||
@ -163,7 +162,7 @@ fn decrypt_inner<R: Rng>(
|
||||
return Err(Error::Decryption);
|
||||
}
|
||||
|
||||
let mut em = priv_key.raw_decryption_primitive(rng, ciphertext)?;
|
||||
let mut em = priv_key.raw_decryption_primitive(rng, ciphertext, priv_key.size())?;
|
||||
|
||||
let label = match label {
|
||||
Some(l) => l,
|
||||
|
@ -3,14 +3,13 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
|
||||
|
||||
use crate::errors::{Error, Result};
|
||||
use crate::hash::Hash;
|
||||
use crate::raw::{DecryptionPrimitive, EncryptionPrimitive};
|
||||
use crate::key::{self, PrivateKey, PublicKey};
|
||||
|
||||
// Encrypts the given message with RSA and the padding
|
||||
// scheme from PKCS#1 v1.5. The message must be no longer than the
|
||||
// length of the public modulus minus 11 bytes.
|
||||
#[inline]
|
||||
pub fn encrypt<R: Rng>(rng: &mut R, pub_key: &RSAPublicKey, msg: &[u8]) -> Result<Vec<u8>> {
|
||||
pub fn encrypt<R: Rng, PK: PublicKey>(rng: &mut R, pub_key: &PK, msg: &[u8]) -> Result<Vec<u8>> {
|
||||
key::check_public(pub_key)?;
|
||||
|
||||
let k = pub_key.size();
|
||||
@ -25,7 +24,7 @@ pub fn encrypt<R: Rng>(rng: &mut R, pub_key: &RSAPublicKey, msg: &[u8]) -> Resul
|
||||
em[k - msg.len() - 1] = 0;
|
||||
em[k - msg.len()..].copy_from_slice(msg);
|
||||
|
||||
pub_key.raw_encryption_primitive(&em)
|
||||
pub_key.raw_encryption_primitive(&em, pub_key.size())
|
||||
}
|
||||
|
||||
/// Decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
|
||||
@ -88,13 +87,13 @@ pub fn sign<R: Rng, SK: PrivateKey>(
|
||||
em[k - t_len..k - hash_len].copy_from_slice(&prefix);
|
||||
em[k - hash_len..k].copy_from_slice(hashed);
|
||||
|
||||
priv_key.raw_decryption_primitive(rng, &em)
|
||||
priv_key.raw_decryption_primitive(rng, &em, priv_key.size())
|
||||
}
|
||||
|
||||
/// Verifies an RSA PKCS#1 v1.5 signature.
|
||||
#[inline]
|
||||
pub fn verify(
|
||||
pub_key: &RSAPublicKey,
|
||||
pub fn verify<PK: PublicKey>(
|
||||
pub_key: &PK,
|
||||
hash: Option<&Hash>,
|
||||
hashed: &[u8],
|
||||
sig: &[u8],
|
||||
@ -107,7 +106,7 @@ pub fn verify(
|
||||
return Err(Error::Verification);
|
||||
}
|
||||
|
||||
let em = pub_key.raw_encryption_primitive(sig)?;
|
||||
let em = pub_key.raw_encryption_primitive(sig, pub_key.size())?;
|
||||
|
||||
// EM = 0x00 || 0x01 || PS || 0x00 || T
|
||||
let mut ok = em[0].ct_eq(&0u8);
|
||||
@ -160,7 +159,7 @@ fn decrypt_inner<R: Rng, SK: PrivateKey>(
|
||||
return Err(Error::Decryption);
|
||||
}
|
||||
|
||||
let em = priv_key.raw_decryption_primitive(rng, ciphertext)?;
|
||||
let em = priv_key.raw_decryption_primitive(rng, ciphertext, priv_key.size())?;
|
||||
|
||||
let first_byte_is_zero = em[0].ct_eq(&0u8);
|
||||
let second_byte_is_two = em[1].ct_eq(&2u8);
|
||||
@ -219,7 +218,7 @@ mod tests {
|
||||
use rand::thread_rng;
|
||||
use sha1::{Digest, Sha1};
|
||||
|
||||
use crate::{Hash, PaddingScheme, PublicKey, RSAPublicKey};
|
||||
use crate::{Hash, PaddingScheme, PublicKey, PublicKeyParts, RSAPrivateKey, RSAPublicKey};
|
||||
|
||||
#[test]
|
||||
fn test_non_zero_bytes() {
|
||||
@ -374,4 +373,4 @@ mod tests {
|
||||
.verify(PaddingScheme::new_pkcs1v15(), msg, &sig)
|
||||
.expect("failed to verify");
|
||||
}
|
||||
|
||||
}
|
||||
|
37
src/pss.rs
37
src/pss.rs
@ -1,17 +1,14 @@
|
||||
use std::vec::Vec;
|
||||
|
||||
use digest::DynDigest;
|
||||
use num_bigint::BigUint;
|
||||
use rand::{Rng, RngCore};
|
||||
use subtle::ConstantTimeEq;
|
||||
|
||||
use crate::algorithms::copy_with_left_pad;
|
||||
use crate::errors::{Error, Result};
|
||||
use crate::internals;
|
||||
use crate::key::{PublicKeyParts, RSAPrivateKey, RSAPublicKey};
|
||||
use crate::key::{PrivateKey, PublicKey};
|
||||
|
||||
pub fn verify(
|
||||
pub_key: &RSAPublicKey,
|
||||
pub fn verify<PK: PublicKey>(
|
||||
pub_key: &PK,
|
||||
hashed: &[u8],
|
||||
sig: &[u8],
|
||||
digest: &mut dyn DynDigest,
|
||||
@ -20,17 +17,10 @@ pub fn verify(
|
||||
if sig.len() != (n_bits + 7) / 8 {
|
||||
return Err(Error::Verification);
|
||||
}
|
||||
let s = BigUint::from_bytes_be(sig);
|
||||
let m = internals::encrypt(pub_key, &s).to_bytes_be();
|
||||
|
||||
let em_bits = n_bits - 1;
|
||||
let em_len = (em_bits + 7) / 8;
|
||||
|
||||
if em_len < m.len() {
|
||||
return Err(Error::Verification);
|
||||
}
|
||||
|
||||
let mut em = vec![0; em_len];
|
||||
copy_with_left_pad(&mut em, &m);
|
||||
let mut em = pub_key.raw_encryption_primitive(sig, em_len)?;
|
||||
|
||||
emsa_pss_verify(hashed, &mut em, em_bits, None, digest)
|
||||
}
|
||||
@ -39,10 +29,10 @@ pub fn verify(
|
||||
/// Note that hashed must be the result of hashing the input message using the
|
||||
/// given hash function. The opts argument may be nil, in which case sensible
|
||||
/// defaults are used.
|
||||
pub fn sign<T: RngCore + ?Sized, S: Rng>(
|
||||
pub fn sign<T: RngCore + ?Sized, S: Rng, SK: PrivateKey>(
|
||||
rng: &mut T,
|
||||
blind_rng: Option<&mut S>,
|
||||
priv_key: &RSAPrivateKey,
|
||||
priv_key: &SK,
|
||||
hashed: &[u8],
|
||||
salt_len: Option<usize>,
|
||||
digest: &mut dyn DynDigest,
|
||||
@ -60,9 +50,9 @@ pub fn sign<T: RngCore + ?Sized, S: Rng>(
|
||||
/// Note that hashed must be the result of hashing the input message using the
|
||||
/// given hash function. salt is a random sequence of bytes whose length will be
|
||||
/// later used to verify the signature.
|
||||
fn sign_pss_with_salt<T: Rng>(
|
||||
fn sign_pss_with_salt<T: Rng, SK: PrivateKey>(
|
||||
blind_rng: Option<&mut T>,
|
||||
priv_key: &RSAPrivateKey,
|
||||
priv_key: &SK,
|
||||
hashed: &[u8],
|
||||
salt: &[u8],
|
||||
digest: &mut dyn DynDigest,
|
||||
@ -71,14 +61,7 @@ fn sign_pss_with_salt<T: Rng>(
|
||||
let mut em = vec![0; ((n_bits - 1) + 7) / 8];
|
||||
emsa_pss_encode(&mut em, hashed, n_bits - 1, salt, digest)?;
|
||||
|
||||
let m = BigUint::from_bytes_be(&em);
|
||||
|
||||
let c = internals::decrypt_and_check(blind_rng, priv_key, &m)?.to_bytes_be();
|
||||
|
||||
let mut s = vec![0; (n_bits + 7) / 8];
|
||||
copy_with_left_pad(&mut s, &c);
|
||||
|
||||
Ok(s)
|
||||
priv_key.raw_decryption_primitive(blind_rng, &em, (n_bits + 7) / 8)
|
||||
}
|
||||
|
||||
fn emsa_pss_encode(
|
||||
|
25
src/raw.rs
25
src/raw.rs
@ -2,13 +2,13 @@ use num_bigint::BigUint;
|
||||
use rand::Rng;
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use crate::errors::Result;
|
||||
use crate::errors::{Error, Result};
|
||||
use crate::internals;
|
||||
use crate::key::{PublicKeyParts, RSAPrivateKey, RSAPublicKey};
|
||||
use crate::key::{RSAPrivateKey, RSAPublicKey};
|
||||
|
||||
pub trait EncryptionPrimitive {
|
||||
/// Do NOT use directly! Only for implementors.
|
||||
fn raw_encryption_primitive(&self, plaintext: &[u8]) -> Result<Vec<u8>>;
|
||||
fn raw_encryption_primitive(&self, plaintext: &[u8], pad_size: usize) -> Result<Vec<u8>>;
|
||||
}
|
||||
|
||||
pub trait DecryptionPrimitive {
|
||||
@ -17,15 +17,20 @@ pub trait DecryptionPrimitive {
|
||||
&self,
|
||||
rng: Option<&mut R>,
|
||||
ciphertext: &[u8],
|
||||
pad_size: usize,
|
||||
) -> Result<Vec<u8>>;
|
||||
}
|
||||
|
||||
impl EncryptionPrimitive for RSAPublicKey {
|
||||
fn raw_encryption_primitive(&self, plaintext: &[u8]) -> Result<Vec<u8>> {
|
||||
fn raw_encryption_primitive(&self, plaintext: &[u8], pad_size: usize) -> 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());
|
||||
let ciphertext = internals::left_pad(&c_bytes, pad_size);
|
||||
|
||||
if pad_size < ciphertext.len() {
|
||||
return Err(Error::Verification);
|
||||
}
|
||||
|
||||
// clear out tmp values
|
||||
m.zeroize();
|
||||
@ -37,8 +42,8 @@ impl EncryptionPrimitive for RSAPublicKey {
|
||||
}
|
||||
|
||||
impl<'a> EncryptionPrimitive for &'a RSAPublicKey {
|
||||
fn raw_encryption_primitive(&self, plaintext: &[u8]) -> Result<Vec<u8>> {
|
||||
(*self).raw_encryption_primitive(plaintext)
|
||||
fn raw_encryption_primitive(&self, plaintext: &[u8], pad_size: usize) -> Result<Vec<u8>> {
|
||||
(*self).raw_encryption_primitive(plaintext, pad_size)
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,11 +52,12 @@ impl DecryptionPrimitive for RSAPrivateKey {
|
||||
&self,
|
||||
rng: Option<&mut R>,
|
||||
ciphertext: &[u8],
|
||||
pad_size: usize,
|
||||
) -> 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());
|
||||
let plaintext = internals::left_pad(&m_bytes, pad_size);
|
||||
|
||||
// clear tmp values
|
||||
c.zeroize();
|
||||
@ -67,7 +73,8 @@ impl<'a> DecryptionPrimitive for &'a RSAPrivateKey {
|
||||
&self,
|
||||
rng: Option<&mut R>,
|
||||
ciphertext: &[u8],
|
||||
pad_size: usize,
|
||||
) -> Result<Vec<u8>> {
|
||||
(*self).raw_decryption_primitive(rng, ciphertext)
|
||||
(*self).raw_decryption_primitive(rng, ciphertext, pad_size)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user