Skip to main content

t_rust_less_lib/secrets_store/cipher/
rust_rsa_aes_gcm.rs

1use super::{Cipher, PrivateData, PrivateKey, PublicData, PublicKey, SealKey};
2use crate::{memguard::SecretBytes, secrets_store::SecretStoreResult};
3use crate::{
4  secrets_store::SecretStoreError,
5  secrets_store_capnp::{block, KeyType},
6};
7use aes_gcm::aead::generic_array::GenericArray;
8use aes_gcm::aead::Aead;
9use aes_gcm::{Aes256Gcm, KeyInit};
10use core::convert::TryFrom;
11use rand::{thread_rng, RngCore};
12use rsa::pkcs1::{DecodeRsaPrivateKey, EncodeRsaPrivateKey};
13use rsa::pkcs8::{EncodePublicKey, SubjectPublicKeyInfo};
14use rsa::{oaep::Oaep, RsaPrivateKey, RsaPublicKey};
15
16const RSA_KEY_BITS: usize = 4096;
17
18#[allow(dead_code)]
19pub static RUST_RSA_AES_GCM: RustRsaAesGcmCipher = RustRsaAesGcmCipher();
20
21pub struct RustRsaAesGcmCipher();
22
23impl Cipher for RustRsaAesGcmCipher {
24  fn key_type(&self) -> KeyType {
25    KeyType::RsaAesGcm
26  }
27
28  fn name(&self) -> String {
29    "RustRsaAesGcmCipher".to_string()
30  }
31
32  fn generate_key_pair(&self) -> SecretStoreResult<(PublicKey, PrivateKey)> {
33    let mut rng = thread_rng();
34    let private = RsaPrivateKey::new(&mut rng, RSA_KEY_BITS)?;
35    let private_der = SecretBytes::from_secured(private.to_pkcs1_der()?.as_bytes());
36    let public_der = private.to_public_key().to_public_key_der()?.as_ref().to_vec();
37
38    Ok((public_der, private_der))
39  }
40
41  fn seal_key_length(&self) -> usize {
42    32
43  }
44
45  fn seal_min_nonce_length(&self) -> usize {
46    12
47  }
48
49  fn seal_private_key(
50    &self,
51    seal_key: &SealKey,
52    nonce: &[u8],
53    private_key: &PrivateKey,
54  ) -> SecretStoreResult<PublicData> {
55    let cipher = Aes256Gcm::new(GenericArray::from_slice(&seal_key.borrow()));
56    let encrypted = cipher.encrypt(GenericArray::from_slice(&nonce[0..12]), private_key.borrow().as_bytes())?;
57
58    Ok(encrypted)
59  }
60
61  fn open_private_key(&self, seal_key: &SealKey, nonce: &[u8], crypted_key: &[u8]) -> SecretStoreResult<PrivateKey> {
62    let cipher = Aes256Gcm::new(GenericArray::from_slice(&seal_key.borrow()));
63    let decrypted = cipher.decrypt(GenericArray::from_slice(&nonce[0..12]), crypted_key)?;
64
65    Ok(SecretBytes::from(decrypted))
66  }
67
68  fn encrypt(
69    &self,
70    recipients: &[(&str, PublicKey)],
71    data: &PrivateData,
72    mut header_builder: block::header::Builder,
73  ) -> SecretStoreResult<PublicData> {
74    let mut rng = thread_rng();
75    let seal_key = SecretBytes::random(&mut rng, 32);
76    let mut nonce = [0u8; 12];
77    rng.fill_bytes(&mut nonce[..]);
78
79    let cipher = Aes256Gcm::new(GenericArray::from_slice(&seal_key.borrow()));
80    let public_data = cipher.encrypt(GenericArray::from_slice(&nonce[..]), data.borrow().as_bytes())?;
81
82    header_builder.set_type(self.key_type());
83    header_builder
84      .reborrow()
85      .init_common_key(12)
86      .copy_from_slice(&nonce[..]);
87
88    let mut recipient_keys = header_builder.init_recipients(recipients.len() as u32);
89
90    for (idx, (recipient_id, recipient_public_key)) in recipients.iter().enumerate() {
91      // Note: Parameter check in PKCS8 is slightly too strict and incompatible with previous versions, so this patch becomes necessary
92      let mut s = SubjectPublicKeyInfo::try_from(recipient_public_key.as_ref())?;
93      if s.algorithm.parameters.is_none() {
94        s.algorithm.parameters = Some(rsa::pkcs1::der::asn1::Null.into());
95      }
96      let public_key = RsaPublicKey::try_from(s)?;
97
98      let crypled_key_buffer = public_key.encrypt(&mut rng, Oaep::new::<sha1::Sha1>(), seal_key.borrow().as_bytes())?;
99
100      let mut recipient_key = recipient_keys.reborrow().get(idx as u32);
101
102      recipient_key.set_id(recipient_id);
103      recipient_key
104        .init_crypted_key(crypled_key_buffer.len() as u32)
105        .copy_from_slice(&crypled_key_buffer);
106    }
107
108    Ok(public_data)
109  }
110
111  fn decrypt(
112    &self,
113    user: (&str, &PrivateKey),
114    header: block::header::Reader,
115    crypted: &[u8],
116  ) -> SecretStoreResult<super::PrivateData> {
117    if header.get_type()? != self.key_type() {
118      return Err(SecretStoreError::Cipher("Invalid block header".to_string()));
119    }
120    let nonce = header.get_common_key()?;
121
122    if nonce.len() != 12 {
123      return Err(SecretStoreError::Cipher("Invalid nonce".to_string()));
124    }
125
126    for recipient in header.get_recipients()?.iter() {
127      if user.0 != recipient.get_id()? {
128        continue;
129      }
130      let crypted_key = recipient.get_crypted_key()?;
131      let private_key = RsaPrivateKey::from_pkcs1_der(&user.1.borrow())?;
132      let seal_key = SecretBytes::from(private_key.decrypt(Oaep::new::<sha1::Sha1>(), crypted_key)?);
133
134      let cipher = Aes256Gcm::new(GenericArray::from_slice(&seal_key.borrow()));
135      let decrypted = cipher.decrypt(GenericArray::from_slice(&nonce[0..12]), crypted)?;
136
137      return Ok(SecretBytes::from(decrypted));
138    }
139
140    Err(SecretStoreError::NoRecipient)
141  }
142}