Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

oaep: support non-string labels #467

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions src/algorithms/oaep.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -62,7 +62,7 @@ pub(crate) fn oaep_encrypt<R: CryptoRngCore + ?Sized>(
msg: &[u8],
digest: &mut dyn DynDigest,
mgf_digest: &mut dyn DynDigest,
label: Option<String>,
label: Option<Box<[u8]>>,
k: usize,
) -> Result<Zeroizing<Vec<u8>>> {
let h_size = digest.output_size();
Expand All @@ -72,7 +72,7 @@ pub(crate) fn oaep_encrypt<R: CryptoRngCore + ?Sized>(
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| {
Expand All @@ -96,7 +96,7 @@ pub(crate) fn oaep_encrypt_digest<
>(
rng: &mut R,
msg: &[u8],
label: Option<String>,
label: Option<Box<[u8]>>,
k: usize,
) -> Result<Zeroizing<Vec<u8>>> {
let h_size = <D as Digest>::output_size();
Expand All @@ -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();
Expand All @@ -130,7 +130,7 @@ pub(crate) fn oaep_decrypt(
em: &mut [u8],
digest: &mut dyn DynDigest,
mgf_digest: &mut dyn DynDigest,
label: Option<String>,
label: Option<Box<[u8]>>,
k: usize,
) -> Result<Vec<u8>> {
let h_size = digest.output_size();
Expand All @@ -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();

Expand Down Expand Up @@ -170,7 +170,7 @@ pub(crate) fn oaep_decrypt(
#[inline]
pub(crate) fn oaep_decrypt_digest<D: Digest, MGD: Digest + FixedOutputReset>(
em: &mut [u8],
label: Option<String>,
label: Option<Box<[u8]>>,
k: usize,
) -> Result<Vec<u8>> {
let h_size = <D as Digest>::output_size();
Expand All @@ -180,7 +180,7 @@ pub(crate) fn oaep_decrypt_digest<D: Digest, MGD: Digest + FixedOutputReset>(
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();
Expand Down
48 changes: 20 additions & 28 deletions src/oaep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -45,7 +44,7 @@ pub struct Oaep {
pub mgf_digest: Box<dyn DynDigest + Send + Sync>,

/// Optional label.
pub label: Option<String>,
pub label: Option<Box<[u8]>>,
}

impl Oaep {
Expand Down Expand Up @@ -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<T: 'static + Digest + DynDigest + Send + Sync, S: AsRef<str>>(
pub fn new_with_label<T: 'static + Digest + DynDigest + Send + Sync, S: Into<Box<[u8]>>>(
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()),
}
}

Expand Down Expand Up @@ -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<str>,
S: Into<Box<[u8]>>,
>(
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()),
}
}
}
Expand Down Expand Up @@ -188,7 +187,7 @@ fn encrypt<R: CryptoRngCore + ?Sized>(
msg: &[u8],
digest: &mut dyn DynDigest,
mgf_digest: &mut dyn DynDigest,
label: Option<String>,
label: Option<Box<[u8]>>,
) -> Result<Vec<u8>> {
key::check_public(pub_key)?;

Expand All @@ -209,7 +208,7 @@ fn encrypt_digest<R: CryptoRngCore + ?Sized, D: Digest, MGD: Digest + FixedOutpu
rng: &mut R,
pub_key: &RsaPublicKey,
msg: &[u8],
label: Option<String>,
label: Option<Box<[u8]>>,
) -> Result<Vec<u8>> {
key::check_public(pub_key)?;

Expand Down Expand Up @@ -238,7 +237,7 @@ fn decrypt<R: CryptoRngCore + ?Sized>(
ciphertext: &[u8],
digest: &mut dyn DynDigest,
mgf_digest: &mut dyn DynDigest,
label: Option<String>,
label: Option<Box<[u8]>>,
) -> Result<Vec<u8>> {
if ciphertext.len() != priv_key.size() {
return Err(Error::Decryption);
Expand Down Expand Up @@ -267,7 +266,7 @@ fn decrypt_digest<R: CryptoRngCore + ?Sized, D: Digest, MGD: Digest + FixedOutpu
rng: Option<&mut R>,
priv_key: &RsaPrivateKey,
ciphertext: &[u8],
label: Option<String>,
label: Option<Box<[u8]>>,
) -> Result<Vec<u8>> {
key::check_public(priv_key)?;

Expand All @@ -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;
Expand Down Expand Up @@ -362,18 +360,12 @@ mod tests {
do_test_oaep_with_different_hashes::<Sha3_512, Sha1>(&priv_key);
}

fn get_label(rng: &mut ChaCha8Rng) -> Option<String> {
const GEN_ASCII_STR_CHARSET: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz\
0123456789=+";

fn get_label(rng: &mut ChaCha8Rng) -> Option<Box<[u8]>> {
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
}
Expand All @@ -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::<D, _>(label);
let padding = Oaep::new_with_label::<D, _>(label.clone());
pub_key.encrypt(&mut rng, padding, &input).unwrap()
} else {
let padding = Oaep::new::<D>();
Expand All @@ -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::<D, _>(label)
let padding = if let Some(label) = label {
Oaep::new_with_label::<D, Box<[u8]>>(label)
} else {
Oaep::new::<D>()
};
Expand Down Expand Up @@ -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::<D, U, _>(label);
let padding = Oaep::new_with_mgf_hash_and_label::<D, U, _>(label.clone());
pub_key.encrypt(&mut rng, padding, &input).unwrap()
} else {
let padding = Oaep::new_with_mgf_hash::<D, U>();
Expand All @@ -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::<D, U, _>(label)
} else {
Oaep::new_with_mgf_hash::<D, U>()
Expand Down Expand Up @@ -484,7 +476,7 @@ mod tests {
priv_key
.decrypt_blinded(
&mut rng,
Oaep::new_with_label::<Sha1, _>("label"),
Oaep::new_with_label::<Sha1, _>("label".as_bytes()),
&ciphertext,
)
.is_err(),
Expand Down Expand Up @@ -572,7 +564,7 @@ mod tests {
let priv_key = get_private_key();
let pub_key: RsaPublicKey = (&priv_key).into();
let encrypting_key = EncryptingKey::<Sha1>::new(pub_key);
let decrypting_key = DecryptingKey::<Sha1>::new_with_label(priv_key, "label");
let decrypting_key = DecryptingKey::<Sha1>::new_with_label(priv_key, "label".as_bytes());
let ciphertext = encrypting_key
.encrypt_with_rng(&mut rng, "a_plain_text".as_bytes())
.unwrap();
Expand Down
25 changes: 6 additions & 19 deletions src/oaep/decrypting_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -26,7 +23,7 @@ where
MGD: Digest + FixedOutputReset,
{
inner: RsaPrivateKey,
label: Option<String>,
label: Option<Box<[u8]>>,
phantom: PhantomData<D>,
mg_phantom: PhantomData<MGD>,
}
Expand All @@ -47,10 +44,10 @@ where
}

/// Create a new verifying key from an RSA public key using provided label
pub fn new_with_label<S: AsRef<str>>(key: RsaPrivateKey, label: S) -> Self {
pub fn new_with_label<S: Into<Box<[u8]>>>(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(),
}
Expand All @@ -63,12 +60,7 @@ where
MGD: Digest + FixedOutputReset,
{
fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>> {
decrypt_digest::<DummyRng, D, MGD>(
None,
&self.inner,
ciphertext,
self.label.as_ref().cloned(),
)
decrypt_digest::<DummyRng, D, MGD>(None, &self.inner, ciphertext, self.label.clone())
}
}

Expand All @@ -82,12 +74,7 @@ where
rng: &mut R,
ciphertext: &[u8],
) -> Result<Vec<u8>> {
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())
}
}

Expand Down
13 changes: 5 additions & 8 deletions src/oaep/encrypting_key.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -21,7 +18,7 @@ where
MGD: Digest + FixedOutputReset,
{
inner: RsaPublicKey,
label: Option<String>,
label: Option<Box<[u8]>>,
phantom: PhantomData<D>,
mg_phantom: PhantomData<MGD>,
}
Expand All @@ -42,10 +39,10 @@ where
}

/// Create a new verifying key from an RSA public key using provided label
pub fn new_with_label<S: AsRef<str>>(key: RsaPublicKey, label: S) -> Self {
pub fn new_with_label<S: Into<Box<[u8]>>>(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(),
}
Expand All @@ -62,7 +59,7 @@ where
rng: &mut R,
msg: &[u8],
) -> Result<Vec<u8>> {
encrypt_digest::<_, D, MGD>(rng, &self.inner, msg, self.label.as_ref().cloned())
encrypt_digest::<_, D, MGD>(rng, &self.inner, msg, self.label.clone())
}
}

Expand Down