Skip to main content

rsa/oaep/
encrypting_key.rs

1use super::encrypt_digest;
2use crate::{traits::RandomizedEncryptor, Result, RsaPublicKey};
3use alloc::{boxed::Box, vec::Vec};
4use core::marker::PhantomData;
5use digest::{Digest, FixedOutputReset};
6use rand_core::CryptoRng;
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10/// Encryption key for PKCS#1 v1.5 encryption as described in [RFC8017 § 7.1].
11///
12/// [RFC8017 § 7.1]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
13#[derive(Debug, Clone)]
14#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15pub struct EncryptingKey<D, MGD = D>
16where
17    D: Digest,
18    MGD: Digest + FixedOutputReset,
19{
20    inner: RsaPublicKey,
21    label: Option<Box<[u8]>>,
22    phantom: PhantomData<D>,
23    mg_phantom: PhantomData<MGD>,
24}
25
26impl<D, MGD> EncryptingKey<D, MGD>
27where
28    D: Digest,
29    MGD: Digest + FixedOutputReset,
30{
31    /// Create a new verifying key from an RSA public key.
32    pub fn new(key: RsaPublicKey) -> Self {
33        Self {
34            inner: key,
35            label: None,
36            phantom: Default::default(),
37            mg_phantom: Default::default(),
38        }
39    }
40
41    /// Create a new verifying key from an RSA public key using provided label
42    pub fn new_with_label<S: Into<Box<[u8]>>>(key: RsaPublicKey, label: S) -> Self {
43        Self {
44            inner: key,
45            label: Some(label.into()),
46            phantom: Default::default(),
47            mg_phantom: Default::default(),
48        }
49    }
50}
51
52impl<D, MGD> RandomizedEncryptor for EncryptingKey<D, MGD>
53where
54    D: Digest,
55    MGD: Digest + FixedOutputReset,
56{
57    fn encrypt_with_rng<R: CryptoRng + ?Sized>(&self, rng: &mut R, msg: &[u8]) -> Result<Vec<u8>> {
58        encrypt_digest::<_, D, MGD>(rng, &self.inner, msg, self.label.clone())
59    }
60}
61
62impl<D, MGD> PartialEq for EncryptingKey<D, MGD>
63where
64    D: Digest,
65    MGD: Digest + FixedOutputReset,
66{
67    fn eq(&self, other: &Self) -> bool {
68        self.inner == other.inner && self.label == other.label
69    }
70}
71
72#[cfg(test)]
73mod tests {
74
75    #[test]
76    #[cfg(all(feature = "hazmat", feature = "serde"))]
77    fn test_serde() {
78        use super::*;
79        use rand::rngs::ChaCha8Rng;
80        use rand_core::SeedableRng;
81        use serde_test::{assert_tokens, Configure, Token};
82
83        let mut rng = ChaCha8Rng::from_seed([42; 32]);
84        let priv_key =
85            crate::RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
86        let encrypting_key = EncryptingKey::<sha2::Sha256>::new(priv_key.to_public_key());
87
88        let tokens = [
89            Token::Struct {
90                name: "EncryptingKey",
91                len: 4,
92            },
93            Token::Str("inner"),
94            Token::Str(
95                "3024300d06092a864886f70d01010105000313003010020900ab240c3361d02e370203010001",
96            ),
97            Token::Str("label"),
98            Token::None,
99            Token::Str("phantom"),
100            Token::UnitStruct {
101                name: "PhantomData",
102            },
103            Token::Str("mg_phantom"),
104            Token::UnitStruct {
105                name: "PhantomData",
106            },
107            Token::StructEnd,
108        ];
109        assert_tokens(&encrypting_key.readable(), &tokens);
110    }
111}