Skip to main content

rsa/oaep/
encrypting_key.rs

1use super::encrypt_digest_into;
2#[cfg(not(feature = "alloc"))]
3use super::Label;
4use crate::traits::{
5    modular::{CtModulusParams, ModulusParams},
6    PublicKeyParts, UnsignedModularInt,
7};
8use crate::{traits::RandomizedEncryptor, GenericRsaPublicKey, Result};
9#[cfg(feature = "alloc")]
10use alloc::{boxed::Box, vec::Vec};
11use core::marker::PhantomData;
12#[cfg(feature = "alloc")]
13use crypto_bigint::{modular::BoxedMontyParams, BoxedUint};
14use digest::{Digest, FixedOutputReset};
15use rand_core::{CryptoRng, TryCryptoRng};
16#[cfg(feature = "serde")]
17use serde::{Deserialize, Serialize};
18
19/// Encryption key for PKCS#1 v1.5 encryption as described in [RFC8017 § 7.1].
20///
21/// [RFC8017 § 7.1]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
22#[derive(Debug, Clone)]
23#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
24#[cfg_attr(
25    feature = "serde",
26    serde(bound(
27        serialize = "GenericRsaPublicKey<T, M>: Serialize",
28        deserialize = "GenericRsaPublicKey<T, M>: serde::de::DeserializeOwned"
29    ))
30)]
31pub struct GenericEncryptingKey<D, MGD, T, M>
32where
33    T: UnsignedModularInt,
34    M: ModulusParams<Modulus = T>,
35{
36    inner: GenericRsaPublicKey<T, M>,
37    #[cfg(feature = "alloc")]
38    label: Option<Box<[u8]>>,
39    #[cfg(not(feature = "alloc"))]
40    label: Option<Label>,
41    phantom: PhantomData<D>,
42    mg_phantom: PhantomData<MGD>,
43}
44
45/// Boxed OAEP encrypting key alias.
46#[cfg(feature = "alloc")]
47pub type EncryptingKey<D, MGD = D> = GenericEncryptingKey<D, MGD, BoxedUint, BoxedMontyParams>;
48
49impl<D, MGD, T, M> GenericEncryptingKey<D, MGD, T, M>
50where
51    T: UnsignedModularInt,
52    M: ModulusParams<Modulus = T>,
53{
54    /// Create a new verifying key from an RSA public key.
55    pub fn new(key: GenericRsaPublicKey<T, M>) -> Self {
56        Self {
57            inner: key,
58            label: None,
59            phantom: Default::default(),
60            mg_phantom: Default::default(),
61        }
62    }
63
64    /// Create a new verifying key from an RSA public key using provided label
65    #[cfg(feature = "alloc")]
66    pub fn new_with_label<S: Into<Box<[u8]>>>(key: GenericRsaPublicKey<T, M>, label: S) -> Self {
67        Self {
68            inner: key,
69            label: Some(label.into()),
70            phantom: Default::default(),
71            mg_phantom: Default::default(),
72        }
73    }
74
75    /// Create a new encrypting key from an RSA public key using provided label.
76    #[cfg(not(feature = "alloc"))]
77    pub fn new_with_label(key: GenericRsaPublicKey<T, M>, label: Label) -> Self {
78        Self {
79            inner: key,
80            label: Some(label),
81            phantom: Default::default(),
82            mg_phantom: Default::default(),
83        }
84    }
85}
86
87impl<D, MGD, T, M> RandomizedEncryptor for GenericEncryptingKey<D, MGD, T, M>
88where
89    D: Digest,
90    MGD: Digest + FixedOutputReset,
91    T: UnsignedModularInt,
92    M: CtModulusParams<Modulus = T>,
93{
94    fn encrypt_with_rng_into<'a, R: TryCryptoRng + ?Sized>(
95        &self,
96        rng: &mut R,
97        msg: &[u8],
98        storage: &'a mut [u8],
99    ) -> Result<&'a [u8]> {
100        let label = self.label.as_deref();
101        encrypt_digest_into::<_, D, MGD, _, T>(rng, &self.inner, msg, label, storage)
102    }
103
104    #[cfg(feature = "alloc")]
105    fn encrypt_with_rng<R: CryptoRng + ?Sized>(&self, rng: &mut R, msg: &[u8]) -> Result<Vec<u8>> {
106        let mut storage = vec![0u8; self.inner.size()];
107        let ciphertext = self.encrypt_with_rng_into(rng, msg, &mut storage)?;
108        Ok(ciphertext.to_vec())
109    }
110}
111
112#[cfg(feature = "alloc")]
113impl<D, MGD, T, M> PartialEq for GenericEncryptingKey<D, MGD, T, M>
114where
115    T: UnsignedModularInt,
116    M: ModulusParams<Modulus = T>,
117    GenericRsaPublicKey<T, M>: PartialEq,
118{
119    fn eq(&self, other: &Self) -> bool {
120        self.inner == other.inner && self.label == other.label
121    }
122}
123
124#[cfg(test)]
125mod tests {
126
127    #[test]
128    #[cfg(all(feature = "hazmat", feature = "serde", feature = "keygen"))]
129    fn test_serde() {
130        use super::*;
131        use rand::rngs::ChaCha8Rng;
132        use rand_core::SeedableRng;
133        use serde_test::{assert_tokens, Configure, Token};
134
135        let mut rng = ChaCha8Rng::from_seed([42; 32]);
136        let priv_key =
137            crate::RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
138        let encrypting_key = EncryptingKey::<sha2::Sha256>::new(priv_key.to_public_key());
139
140        let tokens = [
141            Token::Struct {
142                name: "GenericEncryptingKey",
143                len: 4,
144            },
145            Token::Str("inner"),
146            Token::Str(
147                "3024300d06092a864886f70d01010105000313003010020900ab240c3361d02e370203010001",
148            ),
149            Token::Str("label"),
150            Token::None,
151            Token::Str("phantom"),
152            Token::UnitStruct {
153                name: "PhantomData",
154            },
155            Token::Str("mg_phantom"),
156            Token::UnitStruct {
157                name: "PhantomData",
158            },
159            Token::StructEnd,
160        ];
161        assert_tokens(&encrypting_key.readable(), &tokens);
162    }
163}