1use bitwarden_encoding::B64;
2use rsa::{
3 Oaep, RsaPrivateKey, RsaPublicKey,
4 pkcs8::{EncodePrivateKey, EncodePublicKey},
5};
6use sha1::Sha1;
7
8use crate::{
9 CryptoError, EncString, SymmetricCryptoKey,
10 error::{Result, RsaError, UnsupportedOperationError},
11};
12
13#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
17pub struct RsaKeyPair {
18 pub public: B64,
20 pub private: EncString,
22}
23
24pub(crate) fn make_key_pair(key: &SymmetricCryptoKey) -> Result<RsaKeyPair> {
26 let mut rng = bitwarden_random::rng();
27 let bits = 2048;
28 let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
29 let pub_key = RsaPublicKey::from(&priv_key);
30
31 let spki = pub_key
32 .to_public_key_der()
33 .map_err(|_| RsaError::CreatePublicKey)?;
34
35 let pkcs = priv_key
36 .to_pkcs8_der()
37 .map_err(|_| RsaError::CreatePrivateKey)?;
38
39 let protected = match key {
40 SymmetricCryptoKey::Aes256CbcHmacKey(key) => {
41 EncString::encrypt_aes256_hmac(pkcs.as_bytes(), key)
42 }
43 SymmetricCryptoKey::XChaCha20Poly1305Key(_) => Err(CryptoError::OperationNotSupported(
44 UnsupportedOperationError::EncryptionNotImplementedForKey,
45 )),
46 SymmetricCryptoKey::Aes256CbcKey(_) => Err(CryptoError::OperationNotSupported(
47 UnsupportedOperationError::EncryptionNotImplementedForKey,
48 )),
49 SymmetricCryptoKey::Aes256GcmKey(_) => Err(CryptoError::OperationNotSupported(
50 UnsupportedOperationError::EncryptionNotImplementedForKey,
51 )),
52 SymmetricCryptoKey::XAes256GcmKey(_) => Err(CryptoError::OperationNotSupported(
53 UnsupportedOperationError::EncryptionNotImplementedForKey,
54 )),
55 }?;
56
57 Ok(RsaKeyPair {
58 public: spki.as_ref().into(),
59 private: protected,
60 })
61}
62
63pub(super) fn encrypt_rsa2048_oaep_sha1(public_key: &RsaPublicKey, data: &[u8]) -> Result<Vec<u8>> {
65 let mut rng = bitwarden_random::rng();
66
67 let padding = Oaep::<Sha1>::new();
68 public_key
69 .encrypt(&mut rng, padding, data)
70 .map_err(|e| CryptoError::Rsa(e.into()))
71}