Skip to main content

rsa/oaep/
decrypting_key.rs

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