From b26541152ede542ac5f2c5960c31d5d4565d6cb7 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Wed, 29 Jan 2025 21:33:08 -0800 Subject: [PATCH] oaep: support non-string labels --- src/algorithms/oaep.rs | 18 +++++++------- src/oaep.rs | 48 ++++++++++++++++---------------------- src/oaep/decrypting_key.rs | 25 +++++--------------- src/oaep/encrypting_key.rs | 13 ++++------- 4 files changed, 40 insertions(+), 64 deletions(-) diff --git a/src/algorithms/oaep.rs b/src/algorithms/oaep.rs index 37bfaa3e..b2a5102d 100644 --- a/src/algorithms/oaep.rs +++ b/src/algorithms/oaep.rs @@ -1,6 +1,6 @@ //! Encryption and Decryption using [OAEP padding](https://datatracker.ietf.org/doc/html/rfc8017#section-7.1). //! -use alloc::string::String; +use alloc::boxed::Box; use alloc::vec::Vec; use digest::{Digest, DynDigest, FixedOutputReset}; @@ -62,7 +62,7 @@ pub(crate) fn oaep_encrypt( msg: &[u8], digest: &mut dyn DynDigest, mgf_digest: &mut dyn DynDigest, - label: Option, + label: Option>, k: usize, ) -> Result>> { let h_size = digest.output_size(); @@ -72,7 +72,7 @@ pub(crate) fn oaep_encrypt( return Err(Error::LabelTooLong); } - digest.update(label.as_bytes()); + digest.update(&label); let p_hash = digest.finalize_reset(); encrypt_internal(rng, msg, &p_hash, h_size, k, |seed, db| { @@ -96,7 +96,7 @@ pub(crate) fn oaep_encrypt_digest< >( rng: &mut R, msg: &[u8], - label: Option, + label: Option>, k: usize, ) -> Result>> { let h_size = ::output_size(); @@ -106,7 +106,7 @@ pub(crate) fn oaep_encrypt_digest< return Err(Error::LabelTooLong); } - let p_hash = D::digest(label.as_bytes()); + let p_hash = D::digest(&label); encrypt_internal(rng, msg, &p_hash, h_size, k, |seed, db| { let mut mgf_digest = MGD::new(); @@ -130,7 +130,7 @@ pub(crate) fn oaep_decrypt( em: &mut [u8], digest: &mut dyn DynDigest, mgf_digest: &mut dyn DynDigest, - label: Option, + label: Option>, k: usize, ) -> Result> { let h_size = digest.output_size(); @@ -140,7 +140,7 @@ pub(crate) fn oaep_decrypt( return Err(Error::Decryption); } - digest.update(label.as_bytes()); + digest.update(&label); let expected_p_hash = digest.finalize_reset(); @@ -170,7 +170,7 @@ pub(crate) fn oaep_decrypt( #[inline] pub(crate) fn oaep_decrypt_digest( em: &mut [u8], - label: Option, + label: Option>, k: usize, ) -> Result> { let h_size = ::output_size(); @@ -180,7 +180,7 @@ pub(crate) fn oaep_decrypt_digest( return Err(Error::LabelTooLong); } - let expected_p_hash = D::digest(label.as_bytes()); + let expected_p_hash = D::digest(&label); let res = decrypt_inner(em, h_size, &expected_p_hash, k, |seed, db| { let mut mgf_digest = MGD::new(); diff --git a/src/oaep.rs b/src/oaep.rs index 31c07059..3d90abad 100644 --- a/src/oaep.rs +++ b/src/oaep.rs @@ -10,7 +10,6 @@ mod encrypting_key; pub use self::{decrypting_key::DecryptingKey, encrypting_key::EncryptingKey}; use alloc::boxed::Box; -use alloc::string::{String, ToString}; use alloc::vec::Vec; use core::fmt; @@ -45,7 +44,7 @@ pub struct Oaep { pub mgf_digest: Box, /// Optional label. - pub label: Option, + pub label: Option>, } impl Oaep { @@ -75,13 +74,13 @@ impl Oaep { } /// Create a new OAEP `PaddingScheme` with an associated `label`, using `T` as the hash function for both the label and for MGF1. - pub fn new_with_label>( + pub fn new_with_label>>( label: S, ) -> Self { Self { digest: Box::new(T::new()), mgf_digest: Box::new(T::new()), - label: Some(label.as_ref().to_string()), + label: Some(label.into()), } } @@ -118,14 +117,14 @@ impl Oaep { pub fn new_with_mgf_hash_and_label< T: 'static + Digest + DynDigest + Send + Sync, U: 'static + Digest + DynDigest + Send + Sync, - S: AsRef, + S: Into>, >( label: S, ) -> Self { Self { digest: Box::new(T::new()), mgf_digest: Box::new(U::new()), - label: Some(label.as_ref().to_string()), + label: Some(label.into()), } } } @@ -188,7 +187,7 @@ fn encrypt( msg: &[u8], digest: &mut dyn DynDigest, mgf_digest: &mut dyn DynDigest, - label: Option, + label: Option>, ) -> Result> { key::check_public(pub_key)?; @@ -209,7 +208,7 @@ fn encrypt_digest, + label: Option>, ) -> Result> { key::check_public(pub_key)?; @@ -238,7 +237,7 @@ fn decrypt( ciphertext: &[u8], digest: &mut dyn DynDigest, mgf_digest: &mut dyn DynDigest, - label: Option, + label: Option>, ) -> Result> { if ciphertext.len() != priv_key.size() { return Err(Error::Decryption); @@ -267,7 +266,7 @@ fn decrypt_digest, priv_key: &RsaPrivateKey, ciphertext: &[u8], - label: Option, + label: Option>, ) -> Result> { key::check_public(priv_key)?; @@ -288,7 +287,6 @@ mod tests { use crate::traits::PublicKeyParts; use crate::traits::{Decryptor, RandomizedDecryptor, RandomizedEncryptor}; - use alloc::string::String; use digest::{Digest, DynDigest, FixedOutputReset}; use num_bigint::BigUint; use num_traits::FromPrimitive; @@ -362,18 +360,12 @@ mod tests { do_test_oaep_with_different_hashes::(&priv_key); } - fn get_label(rng: &mut ChaCha8Rng) -> Option { - const GEN_ASCII_STR_CHARSET: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ - abcdefghijklmnopqrstuvwxyz\ - 0123456789=+"; - + fn get_label(rng: &mut ChaCha8Rng) -> Option> { let mut buf = [0u8; 32]; rng.fill_bytes(&mut buf); - if buf[0] < (1 << 7) { - for v in buf.iter_mut() { - *v = GEN_ASCII_STR_CHARSET[(*v >> 2) as usize]; - } - Some(core::str::from_utf8(&buf).unwrap().to_string()) + + if rng.next_u32() % 2 == 0 { + Some(buf.into()) } else { None } @@ -398,7 +390,7 @@ mod tests { let pub_key: RsaPublicKey = prk.into(); let ciphertext = if let Some(ref label) = label { - let padding = Oaep::new_with_label::(label); + let padding = Oaep::new_with_label::(label.clone()); pub_key.encrypt(&mut rng, padding, &input).unwrap() } else { let padding = Oaep::new::(); @@ -408,8 +400,8 @@ mod tests { assert_ne!(input, ciphertext); let blind: bool = rng.next_u32() < (1 << 31); - let padding = if let Some(ref label) = label { - Oaep::new_with_label::(label) + let padding = if let Some(label) = label { + Oaep::new_with_label::>(label) } else { Oaep::new::() }; @@ -446,7 +438,7 @@ mod tests { let pub_key: RsaPublicKey = prk.into(); let ciphertext = if let Some(ref label) = label { - let padding = Oaep::new_with_mgf_hash_and_label::(label); + let padding = Oaep::new_with_mgf_hash_and_label::(label.clone()); pub_key.encrypt(&mut rng, padding, &input).unwrap() } else { let padding = Oaep::new_with_mgf_hash::(); @@ -456,7 +448,7 @@ mod tests { assert_ne!(input, ciphertext); let blind: bool = rng.next_u32() < (1 << 31); - let padding = if let Some(ref label) = label { + let padding = if let Some(label) = label { Oaep::new_with_mgf_hash_and_label::(label) } else { Oaep::new_with_mgf_hash::() @@ -484,7 +476,7 @@ mod tests { priv_key .decrypt_blinded( &mut rng, - Oaep::new_with_label::("label"), + Oaep::new_with_label::("label".as_bytes()), &ciphertext, ) .is_err(), @@ -572,7 +564,7 @@ mod tests { let priv_key = get_private_key(); let pub_key: RsaPublicKey = (&priv_key).into(); let encrypting_key = EncryptingKey::::new(pub_key); - let decrypting_key = DecryptingKey::::new_with_label(priv_key, "label"); + let decrypting_key = DecryptingKey::::new_with_label(priv_key, "label".as_bytes()); let ciphertext = encrypting_key .encrypt_with_rng(&mut rng, "a_plain_text".as_bytes()) .unwrap(); diff --git a/src/oaep/decrypting_key.rs b/src/oaep/decrypting_key.rs index 83ab2824..3ea19ebd 100644 --- a/src/oaep/decrypting_key.rs +++ b/src/oaep/decrypting_key.rs @@ -4,10 +4,7 @@ use crate::{ traits::{Decryptor, RandomizedDecryptor}, Result, RsaPrivateKey, }; -use alloc::{ - string::{String, ToString}, - vec::Vec, -}; +use alloc::{boxed::Box, vec::Vec}; use core::marker::PhantomData; use digest::{Digest, FixedOutputReset}; use rand_core::CryptoRngCore; @@ -26,7 +23,7 @@ where MGD: Digest + FixedOutputReset, { inner: RsaPrivateKey, - label: Option, + label: Option>, phantom: PhantomData, mg_phantom: PhantomData, } @@ -47,10 +44,10 @@ where } /// Create a new verifying key from an RSA public key using provided label - pub fn new_with_label>(key: RsaPrivateKey, label: S) -> Self { + pub fn new_with_label>>(key: RsaPrivateKey, label: S) -> Self { Self { inner: key, - label: Some(label.as_ref().to_string()), + label: Some(label.into()), phantom: Default::default(), mg_phantom: Default::default(), } @@ -63,12 +60,7 @@ where MGD: Digest + FixedOutputReset, { fn decrypt(&self, ciphertext: &[u8]) -> Result> { - decrypt_digest::( - None, - &self.inner, - ciphertext, - self.label.as_ref().cloned(), - ) + decrypt_digest::(None, &self.inner, ciphertext, self.label.clone()) } } @@ -82,12 +74,7 @@ where rng: &mut R, ciphertext: &[u8], ) -> Result> { - decrypt_digest::<_, D, MGD>( - Some(rng), - &self.inner, - ciphertext, - self.label.as_ref().cloned(), - ) + decrypt_digest::<_, D, MGD>(Some(rng), &self.inner, ciphertext, self.label.clone()) } } diff --git a/src/oaep/encrypting_key.rs b/src/oaep/encrypting_key.rs index 9a9ae290..907762c7 100644 --- a/src/oaep/encrypting_key.rs +++ b/src/oaep/encrypting_key.rs @@ -1,9 +1,6 @@ use super::encrypt_digest; use crate::{traits::RandomizedEncryptor, Result, RsaPublicKey}; -use alloc::{ - string::{String, ToString}, - vec::Vec, -}; +use alloc::{boxed::Box, vec::Vec}; use core::marker::PhantomData; use digest::{Digest, FixedOutputReset}; use rand_core::CryptoRngCore; @@ -21,7 +18,7 @@ where MGD: Digest + FixedOutputReset, { inner: RsaPublicKey, - label: Option, + label: Option>, phantom: PhantomData, mg_phantom: PhantomData, } @@ -42,10 +39,10 @@ where } /// Create a new verifying key from an RSA public key using provided label - pub fn new_with_label>(key: RsaPublicKey, label: S) -> Self { + pub fn new_with_label>>(key: RsaPublicKey, label: S) -> Self { Self { inner: key, - label: Some(label.as_ref().to_string()), + label: Some(label.into()), phantom: Default::default(), mg_phantom: Default::default(), } @@ -62,7 +59,7 @@ where rng: &mut R, msg: &[u8], ) -> Result> { - encrypt_digest::<_, D, MGD>(rng, &self.inner, msg, self.label.as_ref().cloned()) + encrypt_digest::<_, D, MGD>(rng, &self.inner, msg, self.label.clone()) } }