bitwarden_core/client/
encryption_settings.rsuse std::collections::HashMap;
use bitwarden_crypto::{AsymmetricCryptoKey, CryptoError, KeyContainer, SymmetricCryptoKey};
#[cfg(feature = "internal")]
use bitwarden_crypto::{AsymmetricEncString, EncString, MasterKey};
use thiserror::Error;
use uuid::Uuid;
#[cfg(feature = "internal")]
use crate::error::Result;
use crate::VaultLocked;
#[derive(Debug, Error)]
pub enum EncryptionSettingsError {
    #[error("Cryptography error, {0}")]
    Crypto(#[from] bitwarden_crypto::CryptoError),
    #[error(transparent)]
    InvalidBase64(#[from] base64::DecodeError),
    #[error(transparent)]
    VaultLocked(#[from] VaultLocked),
    #[error("Invalid private key")]
    InvalidPrivateKey,
    #[error("Missing private key")]
    MissingPrivateKey,
}
#[derive(Clone)]
pub struct EncryptionSettings {
    user_key: SymmetricCryptoKey,
    pub(crate) private_key: Option<AsymmetricCryptoKey>,
    org_keys: HashMap<Uuid, SymmetricCryptoKey>,
}
impl std::fmt::Debug for EncryptionSettings {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("EncryptionSettings").finish()
    }
}
impl EncryptionSettings {
    #[cfg(feature = "internal")]
    pub(crate) fn new(
        master_key: MasterKey,
        user_key: EncString,
        private_key: EncString,
    ) -> Result<Self, EncryptionSettingsError> {
        let user_key = master_key.decrypt_user_key(user_key)?;
        Self::new_decrypted_key(user_key, private_key)
    }
    #[cfg(feature = "internal")]
    pub(crate) fn new_decrypted_key(
        user_key: SymmetricCryptoKey,
        private_key: EncString,
    ) -> Result<Self, EncryptionSettingsError> {
        use bitwarden_crypto::KeyDecryptable;
        use log::warn;
        let private_key = {
            let dec: Vec<u8> = private_key.decrypt_with_key(&user_key)?;
            AsymmetricCryptoKey::from_der(&dec)
                .map_err(|_| {
                    warn!("Invalid private key");
                })
                .ok()
            };
        Ok(EncryptionSettings {
            user_key,
            private_key,
            org_keys: HashMap::new(),
        })
    }
    #[cfg(feature = "secrets")]
    pub(crate) fn new_single_key(key: SymmetricCryptoKey) -> Self {
        EncryptionSettings {
            user_key: key,
            private_key: None,
            org_keys: HashMap::new(),
        }
    }
    #[cfg(feature = "internal")]
    pub(crate) fn set_org_keys(
        &mut self,
        org_enc_keys: Vec<(Uuid, AsymmetricEncString)>,
    ) -> Result<&Self, EncryptionSettingsError> {
        use bitwarden_crypto::KeyDecryptable;
        self.org_keys.clear();
        if org_enc_keys.is_empty() {
            return Ok(self);
        }
        let private_key = self
            .private_key
            .as_ref()
            .ok_or(EncryptionSettingsError::MissingPrivateKey)?;
        for (org_id, org_enc_key) in org_enc_keys {
            let mut dec: Vec<u8> = org_enc_key.decrypt_with_key(private_key)?;
            let org_key = SymmetricCryptoKey::try_from(dec.as_mut_slice())?;
            self.org_keys.insert(org_id, org_key);
        }
        Ok(self)
    }
    pub fn get_key(&self, org_id: &Option<Uuid>) -> Result<&SymmetricCryptoKey, CryptoError> {
        if self.private_key.is_none() {
            return Ok(&self.user_key);
        }
        match org_id {
            Some(org_id) => self
                .org_keys
                .get(org_id)
                .ok_or(CryptoError::MissingKey(*org_id)),
            None => Ok(&self.user_key),
        }
    }
}
impl KeyContainer for EncryptionSettings {
    fn get_key(&self, org_id: &Option<Uuid>) -> Result<&SymmetricCryptoKey, CryptoError> {
        EncryptionSettings::get_key(self, org_id)
    }
}