the_lock_lib/
asymetric_key.rs

1use chacha20poly1305::{XChaCha20Poly1305, KeyInit, Key, XNonce, aead::Aead};
2use rsa::{RsaPublicKey, RsaPrivateKey, Oaep};
3use rand::{rngs::OsRng, Rng};
4use crate::error::{AsymetricKeyResult, AsymetricKeyError};
5
6#[cfg(feature = "serde")]
7use serde::{Serialize, Deserialize};
8
9pub const MIN_RSA_KEY_SIZE: usize = 2048;
10const SYMMETRIC_KEY_SIZE: usize = 32;
11const SYMMETRIC_NONE_SIZE: usize = 24;
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15pub struct PrivateKey {
16    rsa_key: RsaPrivateKey,
17    chacha_key: [u8; SYMMETRIC_KEY_SIZE],
18    chacha_nonce: [u8; SYMMETRIC_NONE_SIZE],
19}
20
21impl PrivateKey {
22    #[inline]
23    pub fn new(size: usize) -> AsymetricKeyResult<Self> {
24        if size < MIN_RSA_KEY_SIZE {
25            return Err(AsymetricKeyError::KeySizeIsTooSmall);
26        }
27        let mut chacha_key = [0; SYMMETRIC_KEY_SIZE];
28        OsRng.try_fill(&mut chacha_key)?;
29        let mut chacha_nonce = [0; SYMMETRIC_NONE_SIZE];
30        OsRng.try_fill(&mut chacha_nonce)?;
31        Ok(Self { rsa_key: RsaPrivateKey::new(&mut OsRng, size)?, chacha_key, chacha_nonce })
32    }
33
34    #[inline]
35    pub fn rsa_precomput(&mut self) -> AsymetricKeyResult<()> {
36        Ok(self.rsa_key.precompute()?)
37    }
38
39    #[inline]
40    pub fn get_rsa_private_key(&self) -> &RsaPrivateKey {
41        &self.rsa_key
42    }
43
44    #[inline]
45    pub fn get_rsa_public_key(&self) -> RsaPublicKey {
46        self.rsa_key.to_public_key()
47    }
48
49    #[inline]
50    pub fn get_public_key(&self) -> PublicKey {
51        self.into()
52    }
53
54    #[inline]
55    pub fn decrypt_symmetric_key(&self, data: &[u8]) -> AsymetricKeyResult<Vec<u8>> {
56        Ok(
57            XChaCha20Poly1305::new(&Key::from(self.chacha_key))
58                .decrypt(
59                    &XNonce::from(self.chacha_nonce),
60                    self.rsa_key.decrypt(
61                        Oaep::new::<sha2::Sha256>(),
62                        data
63                    )?.as_ref()
64                )?
65        )
66    }
67}
68
69#[derive(Debug, Clone, PartialEq, Eq)]
70#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
71pub struct PublicKey {
72    rsa_key: RsaPublicKey,
73    chacha_key: [u8; SYMMETRIC_KEY_SIZE],
74    chacha_nonce: [u8; SYMMETRIC_NONE_SIZE],
75}
76
77impl PublicKey {
78    #[inline]
79    pub fn encrypt_symmetric_key(&self, data: &[u8]) -> AsymetricKeyResult<Vec<u8>> {
80        Ok(
81            self.rsa_key.encrypt(
82                &mut OsRng,
83                Oaep::new::<sha2::Sha256>(),
84                &XChaCha20Poly1305::new(&Key::from(self.chacha_key)).encrypt(&XNonce::from(self.chacha_nonce), data)?
85            )?
86        )
87    }
88
89    #[inline]
90    pub fn get_rsa_public_key(&self) -> &RsaPublicKey {
91        &self.rsa_key
92    }
93}
94
95impl From<PrivateKey> for PublicKey {
96    fn from(value: PrivateKey) -> Self {
97        Self::from(&value)
98    }
99}
100
101impl From<&PrivateKey> for PublicKey {
102    fn from(value: &PrivateKey) -> Self {
103        Self { rsa_key: value.get_rsa_public_key(), chacha_key: value.chacha_key, chacha_nonce: value.chacha_nonce }
104    }
105}