the_lock_lib/
asymetric_key.rs1use 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}