diff --git a/Cargo.lock b/Cargo.lock index 02a3f6c7..2aee6c3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -250,9 +250,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "285743a676ccb6b3e116bc14cc69319b957867930ae9c4822f8e0f54509d7243" +checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" dependencies = [ "block-buffer", "const-oid", @@ -416,9 +416,9 @@ checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" [[package]] name = "hmac" -version = "0.13.0-rc.5" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef451d73f36d8a3f93ad32c332ea01146c9650e1ec821a9b0e46c01277d544f8" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" dependencies = [ "digest", ] @@ -786,6 +786,7 @@ dependencies = [ "digest", "hex", "hex-literal", + "hmac", "pkcs1", "pkcs8", "proptest", diff --git a/Cargo.toml b/Cargo.toml index 12b4079e..1473c411 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ pkcs8 = { version = "0.11.0-rc.10", optional = true, default-features = false, f serdect = { version = "0.4", optional = true } sha1 = { version = "0.11.0-rc.5", optional = true, default-features = false, features = ["oid"] } sha2 = { version = "0.11.0-rc.5", optional = true, default-features = false, features = ["oid"] } +hmac = { version = "0.13.0", optional = true, default-features = false } spki = { version = "0.8.0-rc.4", optional = true, default-features = false, features = ["alloc"] } serde = { version = "1.0.184", optional = true, default-features = false, features = ["derive"] } @@ -58,6 +59,7 @@ getrandom = ["crypto-bigint/getrandom", "crypto-common"] serde = ["encoding", "dep:serde", "dep:serdect", "crypto-bigint/serde"] pkcs5 = ["pkcs8/encryption"] std = ["pkcs1?/std", "pkcs8?/std"] +implicit_rejection = ["sha2", "dep:hmac"] [package.metadata.docs.rs] features = ["std", "serde", "hazmat", "sha2"] diff --git a/src/algorithms/pkcs1v15.rs b/src/algorithms/pkcs1v15.rs index 346d7947..f1a855c9 100644 --- a/src/algorithms/pkcs1v15.rs +++ b/src/algorithms/pkcs1v15.rs @@ -15,6 +15,15 @@ use zeroize::Zeroizing; use crate::errors::{Error, Result}; +#[cfg(feature = "implicit_rejection")] +use { + crate::algorithms::pad::uint_to_zeroizing_be_pad, + crypto_bigint::{BoxedUint, CtGt, CtLt}, + digest::OutputSizeUser, + hmac::{Hmac, KeyInit, Mac}, + sha2::Sha256, +}; + /// Fills the provided slice with random values, which are guaranteed /// to not be zero. #[inline] @@ -116,6 +125,190 @@ fn decrypt_inner(em: Vec, k: usize) -> Result<(u8, Vec, u32)> { Ok((valid.to_u8(), em, index)) } +/// Removes PKCS#1 v1.5 encryption padding with implicit rejection. +/// +/// Unlike [`pkcs1v15_encrypt_unpad`], this function does not return an error if +/// the padding is invalid. Instead, it deterministically generates and returns +/// a replacement random message using a key-derivation function. +/// As a result, callers cannot distinguish between valid and +/// invalid padding based on the output, thus preventing side-channel attacks. +/// +/// See +/// [draft-irtf-cfrg-rsa-guidance-08 § 7.2](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-rsa-guidance-08#section-7.2) +#[cfg(feature = "implicit_rejection")] +pub(crate) fn pkcs1v15_encrypt_unpad_implicit_rejection( + em: Vec, + k: usize, + kdk: &KeyDerivationKey, +) -> Result> { + const LENGTH_LABEL: &[u8] = b"length"; + const MESSAGE_LABEL: &[u8] = b"message"; + + if k < 11 || k != em.len() { + return Err(Error::Decryption); + } + + // The maximum allowed message size is the modulus size minus 2 bytes + // and a minimum of 8 bytes for padding. + let max_length = u16::try_from(k - 10).map_err(|_| Error::Decryption)?; + + // CL = IRPRF (KDK, "length", 256). + let rejection_lengths = kdk.prf(LENGTH_LABEL, 256)?; + + // AM = IRPRF (KDK, "message", k). + let rejection_message = kdk.prf(MESSAGE_LABEL, k)?; + + // Mask with 1s up to the most significant bit set in max_length. + // This ensures the mask covers all bits up to the highest bit set. + let mut mask = max_length; + mask |= mask >> 1; + mask |= mask >> 2; + mask |= mask >> 4; + mask |= mask >> 8; + + // Select the rejection length from the prf output. + let rejection_length = rejection_lengths.chunks_exact(2).fold(0u16, |acc, el| { + let candidate_length = (u16::from(el[0]) << 8 | u16::from(el[1])) & mask; + let less_than_max_length = candidate_length.ct_lt(&max_length); + acc.ct_select(&candidate_length, less_than_max_length) + }); + + let Some(rejection_msg_index) = k.checked_sub(usize::from(rejection_length)) else { + return Err(Error::Decryption); + }; + + let first_byte_is_zero = em[0].ct_eq(&0u8); + let second_byte_is_two = em[1].ct_eq(&2u8); + + // Indicates whether the zero byte has been found. + let mut found_zero_byte = Choice::FALSE; + // Padding | message separation index. + let mut zero_index: u32 = 0; + + for (i, el) in em.iter().enumerate().skip(2) { + let equals0 = el.ct_eq(&0u8); + zero_index.ct_assign(&(i as u32), !found_zero_byte & equals0); + found_zero_byte |= equals0; + } + + // Padding must be at least 8 bytes long, and it starts two bytes into the message. + let index_is_greater_than_prefix = zero_index.ct_gt(&9); + + let valid = + first_byte_is_zero & second_byte_is_two & found_zero_byte & index_is_greater_than_prefix; + + let real_message_index = zero_index.wrapping_add(1) as usize; + + // Select either the rejection or real message depending on valid padding. + let message_index = rejection_msg_index.ct_select(&real_message_index, valid); + // At this stage, message_index does not directly reveal whether the padding check was successful, + // thus avoiding leaking information through the message length. + let mut output = vec![0u8; usize::from(max_length)]; + for ((&em_byte, &syn_byte), out_byte) in em[message_index..] + .iter() + .zip(&rejection_message[message_index..]) + .zip(output.iter_mut()) + { + *out_byte = syn_byte.ct_select(&em_byte, valid); + } + output.truncate(em.len() - message_index); + + Ok(output) +} + +#[cfg(feature = "implicit_rejection")] +pub(crate) struct KeyDerivationKey(Zeroizing<[u8; 32]>); + +#[cfg(feature = "implicit_rejection")] +impl KeyDerivationKey { + /// Derives a key derivation key from the private key, the ciphertext, and the key length. + /// + /// ## Specifications + /// ```text + /// + /// Input: + /// d - RSA private exponent + /// k - length in octets of the RSA modulus n + /// ciphertext - the ciphertext + /// Output: + /// KDK - the key derivation key + /// + /// D = I2OSP (d, k). + /// DH = SHA256 (D) + /// KDK = HMAC (DH, C, SHA256). + /// ``` + /// + /// See: + /// [draft-irtf-cfrg-rsa-guidance-08 § 7.2.3](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-rsa-guidance-08#section-7.2) + #[inline] + pub fn derive(d: &BoxedUint, k: usize, ciphertext: &[u8]) -> Result { + if k < 11 { + return Err(Error::Decryption); + } + + // D = I2OSP (d, k). + let d_padded = Zeroizing::new(uint_to_zeroizing_be_pad(d.clone(), k)?); + + // DH = SHA256 (D). + let d_hash: Zeroizing<[u8; 32]> = Zeroizing::new(Sha256::digest(d_padded).into()); + + // KDK = HMAC-SHA256 (DH, C). + let mut mac = + Hmac::::new_from_slice(d_hash.as_ref()).map_err(|_| Error::Decryption)?; + if ciphertext.len() < k { + mac.update(&vec![0u8; k - ciphertext.len()]); + } + mac.update(ciphertext); + let kdk = mac.finalize(); + + Ok(Self(Zeroizing::new(kdk.into_bytes().into()))) + } + + /// Implements the pseudo-random function (PRF) to derive randomness for implicit rejection. + /// + /// ## Specifications + /// + /// ```text + /// IRPRF (KDK, label, length) + /// Input: + /// KDK - the key derivation key + /// label - a label making the output unique for a given KDK + /// length - requested length of output in octets + /// Output: derived key, an octet string + /// ``` + /// See: + /// [draft-irtf-cfrg-rsa-guidance-08 § 7.1] (https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-rsa-guidance-08#section-7.1) + #[inline] + fn prf(&self, label: &[u8], output_len: usize) -> Result> { + // bitLength = 2 octets + // throw an error if the output length bits does not fit into 2 octets + let bitlen_bytes = u16::try_from(output_len * 8) + .map_err(|_| Error::Decryption)? + .to_be_bytes(); + + let mut prf_output = vec![0u8; output_len]; + for (chunk_idx, chunk) in prf_output + .chunks_mut(Hmac::::output_size()) + .enumerate() + { + // I + let index = u16::try_from(chunk_idx).map_err(|_| Error::Decryption)?; + + // P_i = I (2 octets) || label || bitLength (2 octets) + let mut hmac = + Hmac::::new_from_slice(self.0.as_ref()).map_err(|_| Error::Decryption)?; + hmac.update(&index.to_be_bytes()); + hmac.update(label); + hmac.update(&bitlen_bytes); + + // chunk_i = HMAC(KDK, P_i). + let chunk_data = hmac.finalize(); + chunk.copy_from_slice(&chunk_data.as_bytes()[..chunk.len()]); + } + Ok(prf_output) + } +} + #[inline] pub(crate) fn pkcs1v15_sign_pad(prefix: &[u8], hashed: &[u8], k: usize) -> Result> { let hash_len = hashed.len(); diff --git a/src/lib.rs b/src/lib.rs index 7a993669..4f5a7c7b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -253,7 +253,7 @@ mod key; pub use pkcs1; #[cfg(feature = "encoding")] pub use pkcs8; -#[cfg(feature = "sha2")] +#[cfg(any(feature = "sha2", feature = "implicit_rejection"))] pub use sha2; pub use crate::{ @@ -265,5 +265,8 @@ pub use crate::{ traits::keys::CrtValue, }; +#[cfg(feature = "implicit_rejection")] +pub use pkcs1v15::Pkcs1v15EncryptImplicitRejection; + #[cfg(feature = "hazmat")] pub mod hazmat; diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index 92ebee18..2862c99d 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -37,6 +37,9 @@ pub use self::{ signing_key::SigningKey, verifying_key::VerifyingKey, }; +#[cfg(feature = "implicit_rejection")] +use crate::algorithms::pkcs1v15::{pkcs1v15_encrypt_unpad_implicit_rejection, KeyDerivationKey}; + use alloc::{boxed::Box, vec::Vec}; use const_oid::AssociatedOid; use core::fmt::Debug; @@ -49,6 +52,8 @@ use crate::algorithms::pkcs1v15::*; use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; use crate::errors::{Error, Result}; use crate::key::{self, RsaPrivateKey, RsaPublicKey}; +#[cfg(feature = "implicit_rejection")] +use crate::traits::PrivateKeyParts; use crate::traits::{PaddingScheme, PublicKeyParts, SignatureScheme}; /// Encryption using PKCS#1 v1.5 padding. @@ -75,6 +80,32 @@ impl PaddingScheme for Pkcs1v15Encrypt { } } +/// Encryption using PKCS#1 v1.5 padding with implicit rejection. +#[cfg(feature = "implicit_rejection")] +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +pub struct Pkcs1v15EncryptImplicitRejection; + +#[cfg(feature = "implicit_rejection")] +impl PaddingScheme for Pkcs1v15EncryptImplicitRejection { + fn decrypt( + self, + rng: Option<&mut Rng>, + priv_key: &RsaPrivateKey, + ciphertext: &[u8], + ) -> Result> { + decrypt_implicit_rejection(rng, priv_key, ciphertext) + } + + fn encrypt( + self, + rng: &mut Rng, + pub_key: &RsaPublicKey, + msg: &[u8], + ) -> Result> { + encrypt(rng, pub_key, msg) + } +} + /// `RSASSA-PKCS1-v1_5`: digital signatures using PKCS#1 v1.5 padding. #[derive(Clone, Debug, Eq, PartialEq)] pub struct Pkcs1v15Sign { @@ -183,6 +214,37 @@ fn decrypt( pkcs1v15_encrypt_unpad(em, priv_key.size()) } +/// Decrypts plaintext using RSA and the PKCS#1 v1.5 padding scheme with implicit rejection. +/// +/// If an `rng` is provided, RSA blinding is used to avoid timing side-channel attacks. +/// +/// Unlike [`decrypt`], this function does not return an error if +/// the padding is invalid. Instead, it deterministically generates and returns +/// a replacement random message using a key-derivation function. +/// As a result, callers cannot distinguish between valid and +/// invalid paddings based on the output, thus reducing the risk of side-channel attacks. +/// +/// See +/// [draft-irtf-cfrg-rsa-guidance-08](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-rsa-guidance-08) +#[cfg(feature = "implicit_rejection")] +#[inline] +fn decrypt_implicit_rejection( + rng: Option<&mut R>, + priv_key: &RsaPrivateKey, + ciphertext: &[u8], +) -> Result> { + key::check_public(priv_key)?; + + let k = priv_key.size(); + let ct_boxed = BoxedUint::from_be_slice(ciphertext, priv_key.n_bits_precision())?; + let em = rsa_decrypt_and_check(priv_key, rng, &ct_boxed)?; + // TODO: Check the timing leakage in this function. + let em = uint_to_zeroizing_be_pad(em, k)?; + + let kdk = KeyDerivationKey::derive(priv_key.d(), k, ciphertext)?; + pkcs1v15_encrypt_unpad_implicit_rejection(em, k, &kdk) +} + /// Calculates the signature of hashed using /// RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5. Note that `hashed` must /// be the result of hashing the input message using the given hash diff --git a/src/pkcs1v15/decrypting_key.rs b/src/pkcs1v15/decrypting_key.rs index d3ae9ee3..c2eebcde 100644 --- a/src/pkcs1v15/decrypting_key.rs +++ b/src/pkcs1v15/decrypting_key.rs @@ -1,4 +1,4 @@ -use super::{decrypt, EncryptingKey}; +use super::EncryptingKey; use crate::{ dummy_rng::DummyRng, traits::{Decryptor, EncryptingKeypair, RandomizedDecryptor}, @@ -28,7 +28,14 @@ impl DecryptingKey { impl Decryptor for DecryptingKey { fn decrypt(&self, ciphertext: &[u8]) -> Result> { - decrypt::(None, &self.inner, ciphertext) + #[cfg(feature = "implicit_rejection")] + { + crate::pkcs1v15::decrypt_implicit_rejection::(None, &self.inner, ciphertext) + } + #[cfg(not(feature = "implicit_rejection"))] + { + crate::pkcs1v15::decrypt::(None, &self.inner, ciphertext) + } } } @@ -38,7 +45,14 @@ impl RandomizedDecryptor for DecryptingKey { rng: &mut R, ciphertext: &[u8], ) -> Result> { - decrypt(Some(rng), &self.inner, ciphertext) + #[cfg(feature = "implicit_rejection")] + { + crate::pkcs1v15::decrypt_implicit_rejection::(Some(rng), &self.inner, ciphertext) + } + #[cfg(not(feature = "implicit_rejection"))] + { + crate::pkcs1v15::decrypt::(Some(rng), &self.inner, ciphertext) + } } } diff --git a/tests/examples/pkcs1v15_cfrg_rsa_guidance/k2048.pem b/tests/examples/pkcs1v15_cfrg_rsa_guidance/k2048.pem new file mode 100644 index 00000000..e9faf257 --- /dev/null +++ b/tests/examples/pkcs1v15_cfrg_rsa_guidance/k2048.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDIzIOXFAmNpWyq +I2QPk9yJl8FjcpaPwbDG31ETwclOiyHkitIpfmVBkBG05tj15zsbeLJXQAMh0e9r +YC1OyM6NFByUkF60rTBmOaSSBlNLbn8mB0I+l9/9EzyI1yE5ne+8fpbM3L1/Oq4f +6JJxK/tJKYF9URZmRAofrLeiCPXqFlkQrdij8tSXICNgzLYyAk8NBxacGRjzFveU +sUOu9U7IdSKkwCl4+WiZgL/79knDB+gYGb/4hAljjUi9lL4VK1n/ZJ+gvWKdD/oY +E8Or9LVr08LqVGXf+hRYkpKp2KJK0mvn7gUQdBtjgtQ8g9W/pApGYT0GK+RFUX28 +rwy04adpAgMBAAECggEAFFUBDg8tWHZjpmam/xzNu/Dt2BAGRtAqAjkikImSxK05 +5VZZKXJu9lCMOnEVjvC2/3UdOdB1gLstLwYyEEQtBgP/UNu9ezX+LJuxmkehr4Wk +wkkB4CyotYt5GbIO3zKqz79RrbS8S2G5t+loyqTVcPcO8Y2AYyKIk+R9Q578p5Ml +m88s0Qij2GiM3weOeseZlp8jOdLB9SK5aWhGKakzuq7CaBYl6rhPTlb0RH6diPua +GZz3ECPg4lexREGzPITTvGfKgDHSYSYYEDp6CkCEQmL3XYiQzWFuUfkDVIj9bgmd +6P9tZaT/EYJUgHyfWNL7uouhUdyMaL40nJd6IE4EwQKBgQD49a1rqCiTG+pFm4o/ +bcBB0jSCQJwlcelj8x90hgKiVjcbOIPtRZ7PlwUmRZ7dFuBVIvWkXZR1Gy7C2vJy +x/iBalLADRgIAXFjTaiZ15cyIvUbk3YwVIaWqffYwkpZSXwe/NRVz7l+6G0rbTSX +KzMv2jA/BJmbTra1zAuzPndh3QKBgQDOei47SakLljMKEtxoK9+9+66N1twDthR6 +771XV0Pw9tpNhiNQYbca/ZytLTQCXlashrD3dD6zXhrLyiN4lUJEZbcG7SIXXlcY +yMcLZwPqj2tRD5Rb5I5aNrs8PJFzK1id/AXXLYCQMZRFK9ohNIZH7HKUPxGoRuYv +rr6OtTaw/QKBgHb+FfGK4jnN8d9rRFykvGu5aNeIwhkzpPXc0oADPWcSBizAim3y +BMH70L5GMHRD5t1KZFY3VCnU4DjKJW+vHJvekcaxe3b4GZX5HEjLvrx78ONJTAg1 +nk6M1qWH17ltYiH9fg+1xVdfCC7ld2l5gHGyu7SjIjgVG0cxS7ZUeQMRAoGBAJmI +SLBVSZoQCcvH0pSzax/98gIObnNkBT6U3hoADck0BYf34nJ29ozfYI11O2M3ewO2 +9AhNLAJ8SziWCmIzup7Zc4t28Q6nW+RWB4v3AfZ8xrPz/cGG5kM2x2s3LoCRDsgL +CtzCPQL7muEEhqKCSAdbTqflbd/POILkUVYUcaKRAoGAZDv3RkKffYNmegZTAhNH +77/AXmNR+CGp3rtg4OzN5QBa2ensMeVY9+ksKTKOdFadfO98dMq8KzVe1AGhoJFL +Tjy7BkhOWBlgURae0UyqLvpuoETgVNJhRMwWKcVQEFWKBOEz9Et8JE2sJb+RPFe4 +kO5J9UglnNY0BP72hZ3Pl1o= +-----END PRIVATE KEY----- diff --git a/tests/examples/pkcs1v15_cfrg_rsa_guidance/k2049.pem b/tests/examples/pkcs1v15_cfrg_rsa_guidance/k2049.pem new file mode 100644 index 00000000..c5b67e47 --- /dev/null +++ b/tests/examples/pkcs1v15_cfrg_rsa_guidance/k2049.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQFV+IlVahd18cen +eGpQsYvCjJ6Ybt5WZ8qzm4QSTpDrp1wdsIOsPkQ7upTcI1YPdeOoFpOipDvcdCbY +xOr+aMhd4P51f25Ju57UR+YCQwgA27BM6yLn+lehjTOPtmAmzbRn5wzAQOfTZ+9A +PHvx499iRlAJRjHyHq/S+1vJFf8EN5rNERL3MsC0ZgfBeNOKIPUu2lCfL5wEBdUQ +aegMz5QVVNBHBGdQXDz1QeoIl9/J9ADOyymP/HUzctn2kzrxdMxA7ZbUZwMXM7l/ +jN3T+SvDoD6oV2xBfyQAe15PdQEQW1RN6frc3/rfmN+0uwW4GZ8/haz9kfepoJS5 +o4P1BJCXAgMBAAECggEBARnCs/UKetYVJnnX/1EJWKwtjKbwAoWS8zLVWhZzYXio +5n8X5wXOMA4+h1RyUQBgE/l00KPbSe80TKWiajTARQcE0OQi4M4jppQlwV/vtvJu +EG7v9kzIuddELk2k6MhQCOrrNlhZoilPo5N7wmvlYzLn2B4sFg72NcxSiqe+VeYz +pyPbweFrop5SsprvL55WVP3AZmuw/CVKy+gOY4dPD18CB4Ljydz8JSDQycSntjTk +UD+7ST4ar+6z+IvXoTOYcl2ub+OZ53XNXUzwn8g4NHxMmNqxpIg8zmIFE2Fa+qEK +YzaObXt530FmqxYnOe9RWkQC7h4GAcWlW8cd8OMO34ECgYEBiPaTYPAeGNmi3ilS +U9JSwx5Eds6l/3v4QT33/eNWUjzcl2gF+E/A3ex3DfBs7QZcgRNIdUs0avFpdWh3 +/Ts9VoaCyHh9CzFO9qxn1l6BMzmLYqCDwPh2XFrUDVqB+bvc4lJ+1+lQCMsQKctM +q9H56b7fwobJZVIlXafqsZIXjvcCgYEA3sfPEdreg6TEPS+AGX8h/V1G/Ve0MfRP +6Bod439qCR/8BGTtlx3IUIg1rebMX1ZvOWVhOos2eYyS5uI/Uu+QfpVn40G+vFM3 +GJYl+76rHzt7P5L/smgebvWnhKjC1498LYmqqiTSztvQZoHP5lw2x7+jxboTUWIi +LvXC6RTJg2ECgYASCT86c8rt2Q9gowTkVAL4casyyMlVsJr0Y6O+Q3Dy1VhKmrur +af2wMepE+YQGXQRh6ECrIYiGYA43FVRsiwuFrSbTjLQwj1LQf5lEfZHwh/Od00A4 +2y6TjpetBTpx++1ndeHchxjlTmyvfmVGfZy63cfnZchYniyY39wlyk7KgQKBgQCM +zmE0ec+WCPf3bCRc+Ru0ldYeneZIhJBUtN0bQxbz+YFCDcCVeL95Fv5Gkc+ummTm +NAuGAyNFI/Jdd7ZqZvw+5ZOp8Y3qXfY+1fff650gummlvvVZ/7DslNtyX2/26ruj +1JVHwMp08D4B7B5JDROaoKeUe41mLM5KPA8bXoYXQQKBgQD5lZs0xLyozkiIeBsx +sem12K310NPj7VReg2fT+FRbpkQyuIcwNe+IHCvN4A0YCfksQNh4N7XE+az0iza4 +3FOllWGkVlI0AtHo+jrzAOVMkbY+bO4G/m3mZvOSlYKgPh9FTneJ+weBpNb7tSbv +iBYh/R6s0hRm5M3Ziu0Q9OdveQ== +-----END PRIVATE KEY----- diff --git a/tests/examples/pkcs1v15_cfrg_rsa_guidance/k4096.pem b/tests/examples/pkcs1v15_cfrg_rsa_guidance/k4096.pem new file mode 100644 index 00000000..fd2b2499 --- /dev/null +++ b/tests/examples/pkcs1v15_cfrg_rsa_guidance/k4096.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +q4gl5hM8H5F0iWcKq25nZYHamz7f +-----END PRIVATE KEY----- diff --git a/tests/examples/pkcs1v15_cfrg_rsa_guidance/test_cases.json b/tests/examples/pkcs1v15_cfrg_rsa_guidance/test_cases.json new file mode 100644 index 00000000..b2561ede --- /dev/null +++ b/tests/examples/pkcs1v15_cfrg_rsa_guidance/test_cases.json @@ -0,0 +1,269 @@ +{ + "B.1": { + "key_pem": "k2048.pem", + "cases": [ + { + "id": "B.1.2", + "ciphertext_hex": "8bfe264e85d3bdeaa6b8851b8e3b956ee3d226fd3f69063a86880173a273d9f283b2eebdd1ed35f7e02d91c571981b6737d5320bd8396b0f3ad5b019daec1b0aab3cbbc026395f4fd14f13673f2dfc81f9b660ec26ac381e6db3299b4e460b43fab9955df2b3cfaa20e900e19c856238fd371899c2bf2ce8c868b76754e5db3b036533fd603746be13c10d4e3e6022ebc905d20c2a7f32b215a4cd53b3f44ca1c327d2c2b651145821c08396c89071f665349c25e44d2733cd9305985ceef6430c3cf57af5fa224089221218fa34737c79c446d28a94c41c96e4e92ac53fbcf384dea8419ea089f8784445a492c812eb0d409467f75afd7d4d1078886205a066", + "expect": { + "ascii": "lorem ipsum dolor sit amet" + } + }, + { + "id": "B.1.3", + "ciphertext_hex": "443ad9c5f00a1f4e9601717d274aacc93a824cb4d99b3c6a42e2b017e52e018443bd77d34a80703cd9b6acf523cd3b2cd1fea31940a68fba828836f1c3ed2fef071e95e0922ff0f47d0e81dacc13ecdeda3db6476f41e5b3f9ccfcfdf91558007b68ffbbe5e93bb088f1e4f0bb39bc7d8600b38930ecd00a341d8cc76955837efff0f0797c4b46fb1b375bba49bcdc877f39aaadb045c56b836072383eec6627ae280ad4f9a45d6e5b4cc7cf61d42b194ff0b9c9167c621e5380d8333e3b7f20c8d564c9ec6c2805f77c0146adea2f688a943b67ce8889f4a6353e6396d551c36a6dbf19359a825d14b69ccc4fd747cf14a1ca8578d7f0a67dc14b37f5e17ca3", + "expect": { + "empty": true + } + }, + { + "id": "B.1.4", + "ciphertext_hex": "00a2e8f114ea8d05d12dc843e3cc3b2edc8229ff2a028bda29ba9d55e3cd02911902fef1f42a075bf05e8016e8567213d6f260fa49e360779dd81aeea3e04c2cb567e0d72b98bf754014561b7511e083d20e0bfb9cd23f8a0d3c88900c49d2fcd5843ff0765607b2026f28202a87aa94678aed22a0c20724541394cd8f44e373eba1d2bae98f516c1e2ba3d86852d064f856b1daf24795e767a2b90396e50743e3150664afab131fe40ea405dcf572dd1079af1d3f0392ccadcca0a12740dbb213b925ca2a06b1bc1383e83a658c82ba2e7427342379084d5f66b544579f07664cb26edd4f10fd913fdbc0de05ef887d4d1ec1ac95652397ea7fd4e4759fda8b", + "expect": { + "ascii": "lorem ipsum" + } + }, + { + "id": "B.1.5", + "ciphertext_hex": "20aaa8adbbc593a924ba1c5c7990b5c2242ae4b99d0fe636a19a4cf754edbcee774e472fe028160ed42634f8864900cb514006da642cae6ae8c7d087caebcfa6dad1551301e130344989a1d462d4164505f6393933450c67bc6d39d8f5160907cabc251b737925a1cf21e5c6aa5781b7769f6a2a583d97cce008c0f8b6add5f0b2bd80bee60237aa39bb20719fe75749f4bc4e42466ef5a861ae3a92395c7d858d430bfe38040f445ea93fa2958b503539800ffa5ce5f8cf51fa8171a91f36cb4f4575e8de6b4d3f096ee140b938fd2f50ee13f0d050222e2a72b0a3069ff3a6738e82c87090caa5aed4fcbe882c49646aa250b98f12f83c8d528113614a29e7", + "expect": { + "empty": true + } + }, + { + "id": "B.1.6", + "ciphertext_hex": "48cceab10f39a4db32f60074feea473cbcdb7accf92e150417f76b44756b190e843e79ec12aa85083a21f5437e7bad0a60482e601198f9d86923239c8786ee728285afd0937f7dde12717f28389843d7375912b07b991f4fdb0190fced8ba665314367e8c5f9d2981d0f5128feeb46cb50fc237e64438a86df198dd0209364ae3a842d77532b66b7ef263b83b1541ed671b120dfd660462e2107a4ee7b964e734a7bd68d90dda61770658a3c242948532da32648687e0318286473f675b412d6468f013f14d760a358dfcad3cda2afeec5e268a37d250c37f722f468a70dfd92d7294c3c1ee1e7f8843b7d16f9f37ef35748c3ae93aa155cdcdfeb4e78567303", + "expect": { + "hex": "22d850137b9eebe092b24f602dc5bb7918c16bd89ddbf20467b119d205f9c2e4bd7d2592cf1e532106e0f33557565923c73a02d4f09c0c22bea89148183e60317f7028b3aa1f261f91c979393101d7e15f4067e63979b32751658ef769610fe97cf9cef3278b3117d384051c3b1d82c251c2305418c8f6840530e631aad63e70e20e025bcd8efb54c92ec6d3b106a2f8e64eeff7d38495b0fc50c97138af4b1c0a67a1c4e27b077b8439332edfa8608dfeae653cd6a628ac550395f7e74390e42c11682234870925eeaa1fa71b76cf1f2ee3bda69f6717033ff8b7c95c9799e7a3bea5e7e4a1c359772fb6b1c6e6c516661dfe30c3" + } + }, + { + "id": "B.1.7", + "ciphertext_hex": "006f89db685c0a132700c6a17f88a37a6635d0ab89de4c45dc09736c891ca5bf3401ce34c6e5d51e94ed2f518857ddc12d9f9f9e68e01cdc30d86ae5dd83988c0c46a8e39daa1b328a23def551d67fa1964fb15242c83ddd7dd5b1aec720a391d0b86cb16cf4d3c466850c3df88a3ed85993900d1287a0c90c4b04d34ba29e59967661f3f10e0c998f64e14e777e8e81371eca5318b4e0b53414292130c821477c51e2bff844836ab10dff293d82e4f40d345968ef268c92ed0bc238f31d50f4d3f759c23964923e135d15527556410fbd2c451d6a2aa852dc88b01139c6fdd826736d8cd3780601b2977b09c080bd8c0fa471606ad59f053ad33d9eeb905f20", + "expect": { + "hex": "2b5dd72df3cae37f1aef" + } + }, + { + "id": "B.1.8", + "ciphertext_hex": "1439e08c3f84c1a7fec74ce07614b20e01f6fa4e8c2a6cffdc3520d8889e5d9a950c6425798f85d4be38d300ea5695f13ecd4cb389d1ff5b82484b494d6280ab7fa78e645933981cb934cce8bfcd114cc0e6811eefa47aae20af638a1cd163d2d3366186d0a07df0c81f6c9f3171cf3561472e98a6006bf75ddb457bed036dcce199369de7d94ef2c68e8467ee0604eea2b3009479162a7891ba5c40cab17f49e1c438cb6eaea4f76ce23cce0e483ff0e96fa790ea15be67671814342d0a23f4a20262b6182e72f3a67cd289711503c85516a9ed225422f98b116f1ab080a80abd6f0216df88d8cfd67c139243be8dd78502a7aaf6bc99d7da71bcdf627e7354", + "expect": { + "hex": "0f9b" + } + }, + { + "id": "B.1.9", + "ciphertext_hex": "9b2ec9c0c917c98f1ad3d0119aec6be51ae3106e9af1914d48600ab6a2c0c0c8ae02a2dc3039906ff3aac904af32ec798fd65f3ad1afa2e69400e7c1de81f5728f3b3291f38263bc7a90a0563e43ce7a0d4ee9c0d8a716621ca5d3d081188769ce1b131af7d35b13dea99153579c86db31fe07d5a2c14d621b77854e48a8df41b5798563af489a291e417b6a334c63222627376118c02c53b6e86310f728734ffc86ef9d7c8bf56c0c841b24b82b59f51aee4526ba1c4268506d301e4ebc498c6aebb6fd5258c876bf900bac8ca4d309dd522f6a6343599a8bc3760f422c10c72d0ad527ce4af1874124ace3d99bb74db8d69d2528db22c3a37644640f95c05f", + "expect": { + "hex": "a1f8c9255c35cfba403ccc" + } + }, + { + "id": "B.1.10", + "ciphertext_hex": "782c2b59a21a511243820acedd567c136f6d3090c115232a82a5efb0b178285f55b5ec2d2bac96bf00d6592ea7cdc3341610c8fb07e527e5e2d20cfaf2c7f23e375431f45e998929a02f25fd95354c33838090bca838502259e92d86d568bc2cdb132fab2a399593ca60a015dc2bb1afcd64fef8a3834e17e5358d822980dc446e845b3ab4702b1ee41fe5db716d92348d5091c15d35a110555a35deb4650a5a1d2c98025d42d4544f8b32aa6a5e02dc02deaed9a7313b73b49b0d4772a3768b0ea0db5846ace6569cae677bf67fb0acf3c255dc01ec8400c963b6e49b1067728b4e563d7e1e1515664347b92ee64db7efb5452357a02fff7fcb7437abc2e579", + "expect": { + "hex": "e6d700309ca0ed62452254" + } + }, + { + "id": "B.1.11", + "ciphertext_hex": "0096136621faf36d5290b16bd26295de27f895d1faa51c800dafce73d001d60796cd4e2ac3fa2162131d859cd9da5a0c8a42281d9a63e5f353971b72e36b5722e4ac444d77f892a5443deb3dca49fa732fe855727196e23c26eeac55eeced8267a209ebc0f92f4656d64a6c13f7f7ce544ebeb0f668fe3a6c0f189e4bcd5ea12b73cf63e0c8350ee130dd62f01e5c97a1e13f52fde96a9a1bc9936ce734fdd61f27b18216f1d6de87f49cf4f2ea821fb8efd1f92cdad529baf7e31aff9bff4074f2cad2b4243dd15a711adcf7de900851fbd6bcb53dac399d7c880531d06f25f7002e1aaf1722765865d2c2b902c7736acd27bc6cbd3e38b560e2eecf7d4b576", + "expect": { + "hex": "ba27b1842e7c21c0e7ef6a" + } + }, + { + "id": "B.1.12", + "ciphertext_hex": "a7a340675a82c30e22219a55bc07cdf36d47d01834c1834f917f18b517419ce9de2a96460e745024436470ed85e94297b283537d52189c406a3f533cb405cc6a9dba46b482ce98b6e3dd52d8fce2237425617e38c11fbc46b61897ef200d01e4f25f5f6c4c5b38cd0de38ba11908b86595a8036a08a42a3d05b79600a97ac18ba368a08d6cf6ccb624f6e8002afc75599fba4de3d4f3ba7d208391ebe8d21f8282b18e2c10869eb2702e68f9176b42b0ddc9d763f0c86ba0ff92c957aaeab76d9ab8da52ea297ec11d92d770146faa1b300e0f91ef969b53e7d2907ffc984e9a9c9d11fb7d6cba91972059b46506b035efec6575c46d7114a6b935864858445f", + "expect": { + "hex": "63cb0bf65fc8255dd29e17" + } + }, + { + "id": "B.1.13", + "ciphertext_hex": "3d1b97e7aa34eaf1f4fc171ceb11dcfffd9a46a5b6961205b10b302818c1fcc9f4ec78bf18ea0cee7e9fa5b16fb4c611463b368b3312ac11cf9c06b7cf72b54e284848a508d3f02328c62c2999d0fb60929f81783c7a256891bc2ff4d91df2af96a24fc5701a1823af939ce6dbdc510608e3d41eec172ad2d51b9fc61b4217c923cadcf5bac321355ef8be5e5f090cdc2bd0c697d9058247db3ad613fdce87d2955a6d1c948a5160f93da21f731d74137f5d1f53a1923adb513d2e6e1589d44cc079f4c6ddd471d38ac82d20d8b1d21f8d65f3b6907086809f4123e08d86fb38729585de026a485d8f0e703fd4772f6668febf67df947b82195fa3867e3a3065", + "expect": { + "hex": "6f09a0b62699337c497b0b" + } + } + ] + }, + "B.2": { + "key_pem": "k2049.pem", + "cases": [ + { + "id": "B.2.2", + "ciphertext_hex": "013300edbf0bb3571e59889f7ed76970bf6d57e1c89bbb6d1c3991d9df8e65ed54b556d928da7d768facb395bbcc81e9f8573b45cf8195dbd85d83a59281cddf4163aec11b53b4140053e3bd109f787a7c3cec31d535af1f50e0598d85d96d91ea01913d07097d25af99c67464ebf2bb396fb28a9233e56f31f7e105d71a23e9ef3b736d1e80e713d1691713df97334779552fc94b40dd733c7251bc522b673d3ec9354af3dd4ad44fa71c0662213a57ada1d75149697d0eb55c053aaed5ffd0b815832f454179519d3736fb4faf808416071db0d0f801aca8548311ee708c131f4be658b15f6b54256872c2903ac708bd43b017b073b5707bc84c2cd9da70e967", + "expect": { + "ascii": "lorem ipsum" + } + }, + { + "id": "B.2.3", + "ciphertext_hex": "00cc52e83755a4526fea5e62450450638430a84a5878fd12c2a571f33c55729cfab6e35c2e1703c452cff65731249460919aeb1b40084bdef573407851e48b3c72923e48d5c4f3e80990c462bc291a3e635515636ab9ebeb317ca0d75b04b80c17e2f4851f8929f72c9bea4ec4a6a1fbc5155837813567062d6b4b2a6b6e40be545d25da39b08c52f3543e2f2cdfa314832dcbf475fcbb8d3565a64bb09b55f922e6ec6cd8bb5203a11e2fa0c1b383674c4f0b63acd78f3690e3a16ad1b71f6cfe48c56533e2ae42b1393b2d156c2323272490a574ce4f14055249b6a34c3e08d4a417039450910ec34bd5f08eb06078f51bdd6e50334ee64c9695a5bde52938e3", + "expect": { + "empty": true + } + }, + { + "id": "B.2.4", + "ciphertext_hex": "0002aadf846a329fadc6760980303dbd87bfadfa78c2015ce4d6c5782fd9d3f1078bd3c0a2c5bfbdd1c024552e5054d98b5bcdc94e476dd280e64d650089326542ce7c61d4f1ab40004c2e6a88a883613568556a10f3f9edeab67ae8dddc1e6b0831c2793d2715de943f7ce34c5c05d1b09f14431fde566d17e76c9feee90d86a2c158616ec81dda0c642f58c0ba8fa4495843124a7235d46fb4069715a51bf710fd024259131ba94da73597ace494856c94e7a3ec261545793b0990279b15fa91c7fd13dbfb1df2f221dab9fa9f7c1d21e48aa49f6aaecbabf5ee76dc6c2af2317ffb4e303115386a97f8729afc3d0c89419669235f1a3a69570e0836c79fc162", + "expect": { + "ascii": "lorem ipsum" + } + }, + { + "id": "B.2.5", + "ciphertext_hex": "0128a1f7837e53b21ee37f0b4d08c76180305d5d854a1bcf3885471610646795f1e4c85ce7fce0f71ac3504598afdfc26792dea8ac55c7da10f96d26236ae652b282459d679ec84847d523f07213e81d1c713fb159eded43112eab68b610e3f871d9c0009fde783ad7bcdca5568f7a86a716be6b96219c34b061f68718abad7c947ed107097dc68341b865d73f2e857a345f5cf05c53bb2899d2895565009125c7b5fe1c35a73c03bb0f59e7faf381c784988bb71194307ee9a8ac122990fabb5cc1fd877aaa79039ac163d084c7ee1642aaf05befb9d7ed0e29558f11f0708c8e83f804f92fd41310a6fd21d91c3ceb88ceee3e424a3fcdda57fe3abb8b7bae7d", + "expect": { + "empty": true + } + }, + { + "id": "B.2.6", + "ciphertext_hex": "013a60aa202dedad2d9e78c0c99077ccc17b7d0533aeaf184dcb8c9a81ca4de5715ada598d59b926606dcb005935421f6ebfd32e62802f0e2de8df08f1ae00e4aced6ebf361a38df817c892309bd07c92c4f2f7be89f286f99711372e3dd959ccb0a150b28578f29040b39ecf989c26eb77a3480c2d4d363b9563a70f0a0789cc4300af1e600de39dae4a49335d35ac0156f5395ebebf35531c819c9cf498a97e67ee2299d84564444f7bcd51f9f08d6bac0872439ad57eb9a8134dc665add1f813d5031484c905a433c115bf889dc46ac672a8898fe235bf463b1b46345299b6f100b48fa954fc262ce58e83f95955b321c1e86bbfe398b588dd5c75c2c68532b", + "expect": { + "hex": "5c5345594cec69769af002af6513415a0848a4d45601c44b9e84b6e0a42c1356cfc20604df8d334de53fafc6de2125f2eae2ec9864b0b0d03ef1539017ecf312460cbb3c7c49fe124cf1becce8903f227ec85daaae73fe256acdf39f47b46c14fbd289d7f9b9e22ee0e7c5d77cbbf22a2f9fbf4e26c5999a7b8335f6478912edfb77a373a82dabbc8233e585ea5ddfef3d0d872a4a007018005014a8873495951210a4b90209b8286466030e56b1050ed600c777b4dbdb64f86516ef269a3ba77285f9be9afebcaad35226f7b3296932baf8dbfea3d77eb6520da203ffc0672232761e2a8a05186181b8dd1f77f069f7af8de118aa18" + } + }, + { + "id": "B.2.7", + "ciphertext_hex": "000a56cfd7abf21e2c65a28b8145fee663818b6cd218601e9e62bed7de5ac74ceb07b435b305c99e3e286152036086b4a13eb26164f6f4bf79ac7d6c3fbcdcd74c6dc324c04949a0c88cbf616626cb171a4e333a0e124524b44f78e2d8100c03e231791523b7d76db2d464e6b5e64244e04ad21128a5feb56092b4ceda35ebfb84f7fafa8e1c098d9923d66e541b36307574db8912630fcf734af7bcd4118f1f700804c5001a5950780188fc7862384fb3fc0708eaf3cb2b119177bb6928758fa75e644d258ac02748dcae7a78ec6c8679598fa9deee4663f1efe27efe8bd15572ff40676b95469aaa42eab4226d86c1160343255cce4fb7728f7349da27ed096b", + "expect": { + "hex": "fc874af235e261083c2c" + } + }, + { + "id": "B.2.8", + "ciphertext_hex": "011644d88f2955389b6d215fc3acd733265d82348fa15178d99e38fd2842030d4e31d1ab15b0f00a80add1a9bfe112f9c42e827c487193c360dc5888c8c42d5459b1f2c1952dca679ded08f190b6a78bbb6ea00438ebb8b03dc56e45cb36bee49a385c71fbf9bbcceda7b130ad6cee2106eff34dd224fba8e9990edf893ae52b0910cdadf44bf29812a98bb9dc1638815112950bb9e7bad11c610d6406dd2d1c36cddd639e024205a1a2bd82ec97059ef61b5226e3246ca672962194d1222cc032003fe34bf5ca0227f1c86439dcfba5203cf57099884276b0fbbf9b9cec93392673d8290a1a3452f3791c3881c9be6a1eef23841a8a5fde255cbbd3c4fc33827c", + "expect": { + "hex": "9b9b496e44544456e70d9be86bd398dae00c7c05d6ea76c45d12f050b1c61c219b2fe47749451e44d96d11916f6ec4cf9eea67cb" + } + }, + { + "id": "B.2.9", + "ciphertext_hex": "002c9ddc36ba4cf0038692b2d3a1c61a4bb3786a97ce2e46a3ba74d03158aeef456ce0f4db04dda3fe062268a1711250a18c69778a6280d88e133a16254e1f0e30ce8dac9b57d2e39a2f7d7be3ee4e08aec2fdbe8dadad7fdbf442a29a8fb40857407bf6be35596b8eefb5c2b3f58b894452c2dc54a6123a1a38d642e23751746597e08d71ac92704adc17803b19e131b4d1927881f43b0200e6f95658f559f912c889b4cd51862784364896cd6e8618f485a992f82997ad6a0917e32ae5872eaf850092b2d6c782ad35f487b79682333c1750c685d7d32ab3e1538f31dcaa5e7d5d2825875242c83947308dcf63ba4bfff20334c9c140c837dbdbae7a8dee72ff", + "expect": { + "hex": "f6d0f5b78082fe61c04674" + } + }, + { + "id": "B.2.10", + "ciphertext_hex": "00c5d77826c1ab7a34d6390f9d342d5dbe848942e2618287952ba0350d7de6726112e9cebc391a0fae1839e2bf168229e3e0d71d4161801509f1f28f6e1487ca52df05c466b6b0a6fbbe57a3268a970610ec0beac39ec0fa67babce1ef2a86bf77466dc127d7d0d2962c20e66593126f276863cd38dc6351428f884c1384f67cad0a0ffdbc2af16711fb68dc559b96b37b4f04cd133ffc7d79c43c42ca4948fa895b9daeb853150c8a5169849b730cc77d68b0217d6c0e3dbf38d751a1998186633418367e7576530566c23d6d4e0da9b038d0bb5169ce40133ea076472d055001f0135645940fd08ea44269af2604c8b1ba225053d6db9ab43577689401bdc0f3", + "expect": { + "hex": "1ab287fcef3ff17067914d" + } + }, + { + "id": "B.2.11", + "ciphertext_hex": "011e24da411e182d85e7c350a7dbff898c3e17bee1573fe3d0c0d3be53a384a65d597d52247e56d10b01cf1a51533e47c37f38bc62490e449b5f4ea35aec422a63142c95da26e800e14504ce704edc7e38faaff697b74814c14d19f7f6f4d942c1db61eca70266748ed83195bffa2eb85f49047a7bc7aae7f927ff445f15136b28b4cad396312ae09a62ef894688ad50bc53d6977236b76d30c9bb2dacd0d58300f2b3dc69a7c3212c6dcf6db583c59d94e7550ecc871991139259a9a001451635c777c7ac46db113a2460f157f9f830c186f0a0c47ca3012c8d309bea899852febe76b87874292b8230be9de5c88fb94a0f19b2df71ca1efeb5f772b2d9b38016", + "expect": { + "hex": "5659f49338cfcd423dfcce" + } + }, + { + "id": "B.2.12", + "ciphertext_hex": "014b47d00714b92e98eacd73b07816ef530f8355fca68de6ba56828afab9d43b96fcb11bee0e900e966a51705b95e82599f3df202d51d520c96adf32e1c0758a7e0a8694699af8cfd9ed2850678f70e952f029a4b461ac8a8e049ef9ffc483ebdc9a525bae3ddf8d69f8f711d30135fd9cce0c3d09d1a75c5b837d9f0d86827a5f9edccd56af835572ba099a44a69277f31999753cd9887fe46ae7c7eb98d5894692847179dac0ba305ed584f2887f7a6e88c843e6f0d4e99ffdcf51e266198301dab2bcb7b07944207c71a89f1449f3690cf09b9f15a5588a2c16d18ef437876285e9d04fd01ff30dea46a3eb17151e63b784548f1c65eeb08bec9901b9353432", + "expect": { + "hex": "c917a56bd800b8d9578657" + } + }, + { + "id": "B.2.13", + "ciphertext_hex": "01541f0012b2dfd2d2b91cd22570dd577af0d27c29baa4d7a3cec2ddf8cdb957257d8d436455d331e35730d1df7058cbb01649beb236154858843e2e14ae54fd53496883163b8cb30fea540778726453204a846b04535878bebe9e60f8783b77e5dfd4d346cd688aa2ee9e0ba9ac2bfd16005de994ea4a9c40adbafcf79dac4859480a8e6e6849077b07f5e3dce8b97f678fc4b1da7e72004cfae36f01cb23f69180a46e3b9488f3b595e83510c9c4b298c953971d82610562976271e756f97ef317b440271be9847178a482098447516ea29bd599592dbf22e35c91f8e2155bd2f6289bac31c4c608b80bc208608a17cc45f7cff774549782882cf72baf0feb2f", + "expect": { + "hex": "a4e88815652839f2482a8f" + } + } + ] + }, + "B.4": { + "key_pem": "k4096.pem", + "cases": [ + { + "id": "B.4.2", + "ciphertext_hex": "041f9bbe8372454ffadce0befc99ad4bd01cdbe016dffb5d0d84ee879e7ff64a25dced4d504f48a14b700a34a1c148e4b4028eecc9158cf5e3469daad1dddb2157b176dcf5716627aebd6072b965cfb67b42b149e88c0a8dc54703ec244637b3039b80c06d1d4968aeb838f3afcd3dc675fc90736cf0f0adaba182e27a19a7294cef500ed1fcca324c3ffa6ff02bd749a4a66f18da138d53ff549c4e6b3fff0b9ee2029ea8293fcd72a03e1dee4445629979be7fd65e5dbe5e6e77ec2aa87879a01c3e2502af0cc4bc04b637d17b175d92b4dcd70cfe83b6c1d4f91c61e911b81cb6d60b99146f17937d127054521b132acb9ca95cbc6f80cd926d709bd7219d48ce7378e4416328a49be6c773dbdeb00ce23dc91f25f4807526cf4de8dd3fbb13ae1011eefe3a2aad9982f6c9268883b4633057d119c97c1178aae671859af0a488ab7b841c6583572d1261137a4292ba1c1caa4baf808be42075940d7e612efa56ac9a7ffff3e7dbf10b6193ea14c4841fc5c43e031a69ddbd79118ccd92b16a6ef66c7404c001ebc6402301a90248eb6562b7a2f549f52c058109dd5f2617877719ad13e81d19425a4cd5cf9e56e8538f5cb09b6f7ab646910b8c2ff6bf8cf17abdb4758bfba80df9f643950a6d4a8f60c6872700e5919d36503486667e4328a6b74b774eb483a9922706baa7f456644781cc0d78add9024e28da2d5e9d81", + "expect": { + "ascii": "lorem ipsum" + } + }, + { + "id": "B.4.3", + "ciphertext_hex": "31529676f990b750e8b742babe933346bd77610e7ea74a6b815bb06ee3c91a376848a4d8b148c2882d65ca0213e68600354b68b7790110ed744e34786fa5f7b703144a12f7f7a4d5402ef048f248fec83dede7f931bcb872054fd25cfe4279840352f2c495bcb511cf20269d8177baba474e790a2d16b655c4e07b28ad6a61e81ce5db3845cb5395aa4affa413e3f1bdecf3fa0aa3073b40d23e9bb0aa7cf3595bd73d1d38a2661d70a8e4ef525fd446f496ddbe5413657c06d51464977421e057387a92a5b9428d02d1a8fb0d50a1623e1b1d0685c371db24b63dd6a4aebf0e31c637997ae26dbd3441b9f7dce164d948a156aee8c9dc4049286244c85178f7b4f49d3ba0870f7c71f8f546a902a559fd860ed61e550c4143907d118a15f317e9ccd84ce3893db372fff1d9a9e5182258d9f9d840a6b75b1618ce4999734d147f5334763c0b87ca1c8e57c6f923cff9c7107eea45cf5d4fae0ec0b94e892a6f6790b07f9e24bff041620b1fb47bcefb956ba61949fea02db6ec785b4070e84f390234d83d17dbf89819d5c6b52a488f36cd9f8d81e1811bbadbd6756b9ec5fbdcc1d32728efc8ef4318463996c0f829f9064436580f9502af97b1e40c854b0ef0a20da4368e5b94327b62c27a8a1cf6103bc780e06e5ee5232624fe5bee59fe79a3956a7d782380a3398eab6d11f618fc2c698eb28a6029f846c378ecf2d102", + "expect": { + "empty": true + } + }, + { + "id": "B.4.4", + "ciphertext_hex": "00c40ab6440e544ced2c0bbd3f6db05fd0068eb8e9ed83099cf5843ea3d2cfd6adf7ede1c61f1974a5696f503205346b51d7b00eca20432f0082abf2a3cd67433c5f860b32f1f6fe9985dcec65e7f19949999e142bc76ce5b2dcb80615d379e9715ac24ef77fbbe3d969131c0f39666b3ad641fac669d53542ae9389d86f6f28fe63ba272b1f6bd015b4187b6e2014fb74fc32bf4a2e48abfbfc0470956c73791c1d81db6c024f4d1cc81ba01be114b41ddb95572a832086c33fcaf90b32358b5b13ef0bea74a6dd01d5c351a231d4e7d15d121cffff023e0c2bdac11c982fb2419955a495e8dac3d84cbd8d71ac380072a02bb026ed61151f0d202b3133e6030a2db7560ca926de3927f1ed578522edac441071498b4565fb0c8071886b79fc9e8d8c14bec1d7a6106441c16e9b2bd3090dad1fe82d0e43f40b036f00506cea36af61d5f10aac0d0591c12107ceb8999787e34943974025b9c47d16cb523a58c5828da975fa74e431ace2dcf934e21613f877f65c67b729ca79ee25f27ea07a74ff38c3b25bcaf22dfe2e9e5d0adecaa01d98d55b5cd0b20f80e672d1bedf4acda32184db0f5ce89dd64f538f038cbefb625347ef77a16ab9d48dbee9549f1c8d55b5470a5c6693bec146f0190bbca5b93a66667150a661851add729b24dca78a1f051093ecd40a0ac43a593101f579597b7638065bdff4191bdc0cae12c052", + "expect": { + "ascii": "lorem ipsum" + } + }, + { + "id": "B.4.5", + "ciphertext_hex": "577d6457be536bf1fac80993f5f76e797607227a42e325deb246bf8bf475e1d1819c5dfb6d288eb131ead32238b7a8796b76517e78f979b34f5c2272ae4d40e60b265ad3c897ecc4d26587c8ac32db431ed8d2996d64edadf7719baa4b4292b34e042f26693c90f04addffe8ba0e3c3f1cbabafbfd2e3a6bcd9203e9a1cebb1c968caa73430556ea5743ecfa49edab656bfeadf7c114105f3e222fe60983d55bc48cb738c5a307353281c573be6ffc69630185ae6de695c35fbf8cbc24b5590f5e511adb68a38a37bc6dc74a5052e5063f20c30d2f331dafb07797f9e577cb3d18280f318fe2a6116cef6846b7a8384663a5aaac32693b9b159f506d8812f76a1ee405abb1e5e439a0aee4d1b51f435ea2d043fe4f4ef1a6ccf069201ceb7978139eed579b01bcb5b4e525cce6b179f72fcb6aabbd916538d580ce3e1ed57a4d3433efd826fffd75d8fdc43de69afab66dc32a4f4f81b14c0650a097709265e26b57f233008013b275e7b58817b02f4473a99bb48ec7d9562bc78d1f032340d3083b762f19fb204be7f26d7ceef6c7ff712479a6cdf18123586b87c2751493f1bb2585626b1aa486a2ec50a197728cf24d3968e6d9b9bdfedfda91db292abdeffda2334c85fd359e65e7e662193b6feb5df6d70c7727880150c785d809ba3ffce3b2701aad313da60cd4affe85e85d32c4fe271b0b107e529a22cffbb01871c8", + "expect": { + "empty": true + } + }, + { + "id": "B.4.6", + "ciphertext_hex": "09be60b83b63aa1f2398c6ccd7ba602917dfffbc1a2ee01094221ef7140ba8b364b4979b7d068be084d34b70309bc48103d9e7dc76c042d1063ce6d7239d3542ad511da821c6ad53dcaefdd9e950de889d1d462a5a8bcdda4e2ac579c0dc12ab684a16a3c4075ec5062db79f95e5b436a8927fe7e3a795152cb6407faedf088ae4531cca8482348a3c44267b1ea46fa3bfcb4754be735e434c4ef17b84f6fd6c184e8c4adf91fbf00be6a6ff86351e6fd76c8929ef7fae14113370cbe6ba0181ef6970855a2cfde5b366a44bf0575e7e5d5354676b5429a6916bb7065c23417442150f8fa23a1ae284a27008980691eb886b693adb1bf4d38faae5037007900e47124a695c67b51fe9e1e66153cb32fae0e7370151024fe49b2781e50ac5a31d1c7de58923c0360ae61f4a3bcfd7839a104c23d95ddeb76bcaf2b1956f81c355aeb11a46b48762baf072318727e56d4e682a3b71898d3725b00a334c94cb1adccea81525b28c2a1c2b82950b93786ea5b893ffe6dc0932a95b064c838d6f04eaa8334f92b0dec8c7bbc1a5900d7e7680c24e66867ec2b837e30be18083c6fb2bfc67ace569989171f05d312ce97307b477379837351e9199528e88671a93e55868a577fb9eae76a2cbf3cc62c6aaabbee88cf6638012554ba92772e923fbe531fe8aa2036ee7230954ffa24e802a399f531c8cad0a78262442c92089f06b06c7", + "expect": { + "hex": "7a57bf4c557abe6bdd45ed471260ec2749e66710b707ff4e4761738dbe2cdc19267aec5070d2472f53ba0c86e8b607566c871b6c3de28772aa197e369fad293f8218fd32178ecebe60cc7926e093bbdd629ed6a6a29b4a905eefe443f3621d89582a41bac7d4f6b77f9c935681e892d17b2261151a4b4244506cfc49ba578b975840d88f637321d20c25950640d2b43aa660611cc07d016534324b84bada224485488af08a8d54af1698babccd76b87218b074987273dd3746eacd2dee8068d0c4f5e8f219689d55deea3cccb86e52599cebf3777cab3bfc2da5ae31c90199739ba5d5e01816f8f8a21c7f6b6acdada8a2b2ab4f32502d6296a365267a76837878d204a1b8cc5299708e9eb1b44d9663c75c9b8c17dd8f1a9f04109087e22329769fcc5fa65506a0f6294d8bf4a362559c497a36b2a5c55ee12213bd9c42a2dc0f6f35176e194641dcfbb334b13924e6883b4f68c88d016ecdc67bafdeff4b2e4122777726e06b0e37642d42090be622288ce11a8af4261b5d186092002e7d71cb43fc2182e4d341c610e6860904cbc526e74292aa1df81dd08d87b51a953c0be511346d604aa3a8e87f943db3e951a69cc4dcd1b996d3d8ab595aa9b7ca591ae2e9b49798a9b98aa1c1c233f938937c88ad675e6297f36ba0fb161a8b42e9ee9a98d8b781165ed75d30cc55d88e6df5c688c32390" + } + }, + { + "id": "B.4.7", + "ciphertext_hex": "00cd3bf408c742514e30ebfd001708e01f42de439a09d0d4b10044628becd8bc690c45b967a6a900d6259c7d7d20ad49810c270d2fe1b75ffaa84f50071f64d1696bce76e96dbcf2af054d77ded54c742aa38fadba52eebf7a5c8b6dbbf01f28b3ebf4e9b3ca453c92ca8b65771c23671b9da85c51e7a2987395de45b125353d430820b4c90b0ab9fc29e1c576a0ec35828c99c9880e208ecddf80bdaa9c3474561e4c5bf67bf5d144b173f4f28edd1064a9dd8cf5f40b7c35e7e4dbeb370ccabf06efb54e243645b902871a804c27904a620f31ef321af4d1589ca359de889524dfb43ddad51ab50617ab79a50a2d20e2325a05c9963602f2a1d7feaffc80d2b8b88cbd3673531c399342f0bf1c04521d9a441c06593d9e95771129da942d83bb81c627a50c8baafc2a731d97f2e1f638217f9f7b18f2644578fde5073a54a8988fda357c64398a95965a7dd35ffdd7eb7495d4d1c9a950a0cd208a68371829420633cb25e9da9e22b215e50f6ec2714f94ce6abb9a94fbbf6cd18f2fd5bfb78076034b88186957428fe0ea5e1dec7be31d753f155e2a8f7f4854a726612f43ef91f88124011cd32f6841a347dc0411d708db65492ec277b81a335b76a862302acebf7db7cac724144c975ed4d91412eeec4cac3b2409696e3678cffcb7756bde795c55f72da44f325b71dd6ac4e3c1ef512ee8ff24ab316507c6ac60031569", + "expect": { + "hex": "59ccd9c2cfe740e9287b" + } + }, + { + "id": "B.4.8", + "ciphertext_hex": "09f010936fd77967dd2aa090be72ecdd8cb2b2a9fb954e644f08a1c1fd5450007ece0b4e8e992831534309419c034b1c4b369269b808a890eac31d5bbfe73737fd716e117e19638064292539e84dae20ec1d98ecd104e6c88d39d3544d5c43c9fd4e9f4361c67116516fc2569f96e5df50a63e949d92009a7c865c7dd70ea89c0002dd697dcd0e0304f8fa0738a3681322e672a9748f9d9eb1b7b8c1646a7bf2a1967b2aa9793ae0ecdbaa2d601350fd931ea164bc02a33a9c22cee47f2d536d92e465180b44e310bf044eec49cc54972d22e735123fbee76496a4c768acef8966ae9e0ed46b753ec47e20a89af0ccf78c266aeb63aeb99d80e4c34bc4608e164aeffd93e886accd426e9e1cfee4f912f235940a9b8d4554953bee8753b8fe05606fe5f46da70394b10f7e71dba3c10becf85a1f4ee619d421ef69fca837d8b1b42598dea0232668b9c42223d77bae7fbe79a9dbf057eeaa51fceac114661a3b572130776c36cfff9f134b08907ab2a6f927145806a779bc55bfb4215cb8c85decaec5b15cd0a4be691b13e068a2381c33fb5adbdb564fd8be0938fdd710590c08f95aa4ea90cc2cea195ef7a344e14715beff2186ad7d898e8f904861ab9133817a13d8a6af23f83a89e5e1e7f8e163d6190e91a09c11939e3a7d48990b8e3b5c0e01b773ba683f7df73b2f88746593c010cd9cab2ea3d9af5ebf30fba1ef0c", + "expect": { + "hex": "0cfdf702efa4dc6bc686" + } + }, + { + "id": "B.4.9", + "ciphertext_hex": "0eb5e0c87c4ffffb760c8fac2a7f5b06f46301ab5b8374a59cc7006aa16e7f38f27d957a4b475b41975246ffb5f2387ffdb62565411733331a4522a07a70bd40ffe23f28f457be55a6cd1b6aab8c7127ec4b0c9d653c3d979fbd371854a80727c0546d9852ccd6220b32a9081f6687fd2262dc806e55964ac799cfba56c0be1a9fb3d4f46161cc5f251ddf3579a87c48c086da786d953829e513a525a87d889661606593600109a98159a91b606f138b9da1b2d427418d50647476fbdd17b52111ca1a2ff9896167277d158d82ade196ad52ea6d381a63748e0068b160331c9cb27c20afbeb696c1db16ea145e96a6e54a825c87c10f85b0d92fc299e254aa7f74c73f17bc704407c31dba9fbda37e31f1231d06744beacb82a0130a9e7d004bed7e7036e33f1c89bd8ed0833def8e946efb53a9ea4abda91f1e1ed44e884d8e45ea692e8f7e2b0f698024c8ed7ade62b251dcb91b249e937a85f823e6978e01e8f7e9ed9c53f2f16d99afe58d3b77b3818aba64e139b3fcb0174542f348f9d2c47dc9d78902a28e1a6613397a0f5938b860a3f6cd44e3b74a37ccdeda248cdeee4a39497d76722e6860127eefdd80f447e69279bf177c1cd6c27ddd3f2f89924f21775df4824ece7f2a6f16266772a13669bfc04aa3b998ad03de17bbc27e629a495052e3e7f0b7b1c06dd4b429585a663172ba20527ad5186447bb74b5f368", + "expect": { + "hex": "8bf3b682d8b950055940" + } + }, + { + "id": "B.4.10", + "ciphertext_hex": "714102bbe701855ec564853befd91262dc4cfbb3c417113c0c650b49c6878b101a76ba4822bde7ca538a2726c6eb9272a3dbda84119ec107d86d2b3a49d82de9d176824f1c2d9cd9b432064c45dbfc60f1e71ec2772aef2669e756cae67ed757b528cccc4ac6f1437a2d4bbedefece1bb5c21381eb4aebc1670c5bd65d408a19c1329b9d9d236939da58a1285357e910edc83d428d1e5315c81cb070aecc24be7fde807ce5d4f50dbe14478334c26be91ed4cb7335c63561b1a8c8c67e40844b465fcf7df6e0df031572682427c62d3cd0c650ec5ef3875fd420516c5cb8089a34757c81360dda37f7fbbd5ea9c8a54ff29f702741a0d496e268a8934b32cd16bea2aa2628397097df0ba08545b9b23bc103a08077745239de34eec09f63fdcbf3aece33a796adbd8dba0705ee3a1092d51f18f195e896b9c35b1a185752c62755c4d9bf2069db141fddc6755c6927cae8d2811aef492f8324ca555b51a4eaf73001ddf88918798df67138a5475fd881b79a158dbe7dd61f241680039a7ae3128a7b925ec7577cddbe116940e2f50ffa3ed36aee7e46ed6dc5b26e7c5f1d16cdc199140742d3fe6bb7d2d4b74d0be675a3388c6fd6d09112dfdea93a701486e38f28add60fb674ac141b389eb4e09153167596a96d2e6618d98593278d22f5605041882743ebafbeb18cdae093609ae6852498bedd8fb6b0a18ce358bfc9d6f2", + "expect": { + "hex": "630fbcef34c1b72f790d" + } + }, + { + "id": "B.4.11", + "ciphertext_hex": "1dd961276ba110ba4fdaf4f177780cbcb6373d2ae6769417a32c9b02eb00a48b427e7e6edefac562fc42c5e2216c885af0f76bcfaf3da4db54ce9db0e22c498c71e146561c1bbf7ff6246ffc6b0bfcd107830790c07ed9aeda70f2ead9e957992e3ed781e054f336e2ab08110f14ca3be11b92d77b0048c334d97d61c8bc4d82db9c7236973d9ba4da066643440333b5a9e905e799f966c9164907866d9e6af2d7f83466fe8409f24d5c9b3a06614af620087e838039355e65bde8f3ab7a8e06943613e00fd143e21ec2684ac07e1dfdef85da32188a97e7585a667f896941116250f30e31bc0e2b20e536366e225759b12cdd578df18799dfee20b529189ad49789f60ce3649431889d740641df90d1dc372a62b4d77f9f5f9677b4f96770b07107ef37afe4e4dd6af4838ae18b61ce953eedcfc95d081951cbe0b097c6c334489cf46fbba26009d7ebc8ecaa0b155ac60e1f40cc381cd9c85ac7fb25f8458d964bd6e1fc85d6e18bc0fa5491c6995fa7225dcfe43d6a12bde24343d16ce42146cf26a5ec1fd7fae5d829e1f274819a10445ac106f5a517ab89e62455c02469271812be18e972af7d5ba3079dc427f1b7ff7eda2d0cba55f28edef280f5d9243466d1c6f9c4b671777c75c9464e571e7115d97d0d86712781e6346a4472c98da976032ff1073850e7304b6bb4b60b019a7bd870c8d3fb26b212ddfd889b9fae", + "expect": { + "hex": "778f208b90bef0f260a8" + } + }, + { + "id": "B.4.12", + "ciphertext_hex": "3d4477615f8b49c9453d31a5d5a228610d6d3e476737c163725106fa386440ff23a9139f57977c09a1e885ddf2f180ddf0f0b0502ef60f0ff53d2ba444f0322820f11acdd70e48543bd8ddd40d00ad9214d03487b265910cf423dea905af908836bf56ef872493b686aa15731714d1f0280e5cddad24ada53374c8aad063184d62bbdc00efd4839b8f06de6c258d26149480b2fad6fcb2fc97cd78fb60305aa254cf1186fa134741a2340dc1d5243423c82c442f3afd915241f317607a2e223664601932e7b967d6793a7fde2819d475e2b8ab0117e3cc4854063a0c1ff1f5cd9c9dc3e6c993d8861c11ee7155dd0ba2d4f47ff0ffc9c7fc8a891284789e5988806fe7b5f5ec5783861fef756ef7339380215de11337ec8f2379b293c3cacf2f81691c1ad75c9223a6c8edfb0451373d0b759d9d701f547b3c46d3fe1f3d24d33447a52bb55b9dd7050c41d11f3108ddccd5738a072905eb48067350e76a65f0d274b0f4bde004cb673b715d4ab01dded4b6b7f69e133135ffcad4b1776e3610830ae55a98d23610256865e305153ad7319ff905c16453297f5ebe64b8857bff69c750d338368f6a55d73ae363a516fa4bf719cd01d46b609c134e3508d9616f495ff2c869db7ad146376b102529c26407d8ffdedbfb005b7b220e0dcb089da3682c9af7c278472cc19b6523b09661fe6f165bd7b7765ca2524eefa3526397b0", + "expect": { + "hex": "364cfecf7e70a0829f28" + } + }, + { + "id": "B.4.13", + "ciphertext_hex": "44c5b648e960aed2ad38497b6af118577a7978db288c0019cb6f8818578021ca0d782c4e87bd6c3a73ef89e379311f0d449410c336bffdc9d970f995e7b5978910c230b1ef11c06cc5de6ee79ca2f85f6f14e5c42cbb8269d40c032b91783755fbfa7b87f16790bfea91933c67d2499a3d815cb70142285449757e606a438752b803b0928c28dab4fd21125e5b79af04fe912fb444d32039e9e0e10210fbe0174f43e2833ab862e4370b007025a919cf7b9c11241cf95ab10a9baa44a7ce7fa6e802c5b8e5c466dba52704fc2325317526f36d25842e130fcdbbc3c631a1e4c67d23ffcb2218065863c178526616e8429916dff9101baf71857901bdaf305d269c944994f9cf0e02a5499432324b90a62c3c78bd7a7821420a11c43d0a80ee3968ab8a363d6e6476f5424ae98bd59352aa9842e8f42cb0a34da68eac9dd16cf704573007efc4b3fc97161c342c836ff781c331c306f61052d3877ab190e307f4f8d63c3bc8f6ab9a6920f9d1b9be482d3096b0b02447f53b0f974693e2a49b733684d8e33d7dfbb60d3b1aae02c222c395209b1e2647e7fcbf3c44cdee9c73329ce9ed255e011847d6d2e119d252d57c72572b2a309472f059cdae1f24e9cf1ffddebc70b8b252229c7c0adfa763bda2243840bc9a553b6a4ea7737c0a002261b36e198fca4314f659ca1071aceb2668079d663e4ed40e15e10d764aa8cb0c68", + "expect": { + "hex": "750d91268328712552cd" + } + } + ] + } +} \ No newline at end of file diff --git a/tests/pkcs1v15_cfrg_rsa_guidance.rs b/tests/pkcs1v15_cfrg_rsa_guidance.rs new file mode 100644 index 00000000..12f68996 --- /dev/null +++ b/tests/pkcs1v15_cfrg_rsa_guidance.rs @@ -0,0 +1,91 @@ +//! PKCS#1 v1.5 implicit rejection test vectors (draft-irtf-cfrg-rsa-guidance-08 appendix B: 2048-, 2049-, 4096-bit keys). +//! [draft-irtf-cfrg-rsa-guidance-08]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-rsa-guidance-08 +//! +//! Vectors are stored in `examples/pkcs1v15_implicit_rfc/appendix_b.json`. + +#![cfg(all(feature = "implicit_rejection", feature = "encoding"))] + +use pkcs8::DecodePrivateKey; +use rsa::{traits::PublicKeyParts, Pkcs1v15EncryptImplicitRejection, RsaPrivateKey}; +use serde::Deserialize; + +#[derive(Deserialize)] +struct Appendix { + #[serde(rename = "B.1")] + b1: Section, + #[serde(rename = "B.2")] + b2: Section, + #[serde(rename = "B.4")] + b4: Section, +} + +#[derive(Deserialize)] +struct Section { + key_pem: String, + cases: Vec, +} + +#[derive(Deserialize)] +struct Case { + id: String, + ciphertext_hex: String, + expect: Expect, +} + +#[derive(Deserialize, Debug)] +struct Expect { + #[serde(default)] + empty: bool, + ascii: Option, + hex: Option, +} + +fn static_key_pem(file: &str) -> &'static str { + match file { + "k2048.pem" => include_str!("examples/pkcs1v15_cfrg_rsa_guidance/k2048.pem"), + "k2049.pem" => include_str!("examples/pkcs1v15_cfrg_rsa_guidance/k2049.pem"), + "k4096.pem" => include_str!("examples/pkcs1v15_cfrg_rsa_guidance/k4096.pem"), + _ => panic!("unknown key file {file}"), + } +} + +fn expected_bytes(ex: &Expect) -> Vec { + if ex.empty { + return Vec::new(); + } + if let Some(s) = &ex.ascii { + return s.as_bytes().to_vec(); + } + if let Some(h) = &ex.hex { + return hex::decode(h) + .unwrap_or_else(|e| panic!("bad expect hex {}: {e}", ex.hex.as_deref().unwrap())); + } + panic!("expect exactly one of empty/ascii/hex ({ex:?})"); +} + +#[test] +fn implicit_rejection_draft_irtf_cfrg_rsa_guidance() { + let data: Appendix = serde_json::from_str(include_str!( + "examples/pkcs1v15_cfrg_rsa_guidance/test_cases.json" + )) + .unwrap(); + + for section in [&data.b1, &data.b2, &data.b4] { + let pem = static_key_pem(§ion.key_pem); + let key = RsaPrivateKey::from_pkcs8_pem(pem).unwrap_or_else(|e| { + panic!("parse {}: {e}", section.key_pem); + }); + + for case in §ion.cases { + let ct = hex::decode(&case.ciphertext_hex) + .unwrap_or_else(|e| panic!("{} bad ciphertext hex: {e}", case.id)); + assert_eq!(ct.len(), key.size(), "{} ciphertext length", case.id); + + let got = key + .decrypt(Pkcs1v15EncryptImplicitRejection, &ct) + .unwrap_or_else(|e| panic!("{} decrypt: {e}", case.id)); + let want = expected_bytes(&case.expect); + assert_eq!(got, want, "{}", case.id); + } + } +}