bitwarden_crypto/keys/
pin_key.rs

1use super::{
2    kdf::{Kdf, KdfDerivedKeyMaterial},
3    master_key::decrypt_user_key,
4    utils::stretch_key,
5};
6use crate::{
7    EncString, KeyDecryptable, KeyEncryptable, Result, SymmetricCryptoKey,
8    keys::key_encryptable::CryptoKey,
9};
10
11/// Pin Key.
12///
13/// Derived from a specific password, used for pin encryption and exports.
14pub struct PinKey(KdfDerivedKeyMaterial);
15
16impl PinKey {
17    /// Derives a users pin key from their password, email and KDF.
18    pub fn derive(password: &[u8], email: &[u8], kdf: &Kdf) -> Result<Self> {
19        KdfDerivedKeyMaterial::derive_kdf_key(password, email, kdf).map(Self)
20    }
21
22    /// Encrypt the users user key
23    pub fn encrypt_user_key(&self, user_key: &SymmetricCryptoKey) -> Result<EncString> {
24        user_key.encrypt_with_key(self)
25    }
26
27    /// Decrypt the users user key
28    pub fn decrypt_user_key(&self, user_key: EncString) -> Result<SymmetricCryptoKey> {
29        decrypt_user_key(&self.0.0, user_key)
30    }
31}
32
33impl CryptoKey for PinKey {}
34
35impl KeyEncryptable<PinKey, EncString> for &SymmetricCryptoKey {
36    fn encrypt_with_key(self, key: &PinKey) -> Result<EncString> {
37        let stretched_key = SymmetricCryptoKey::Aes256CbcHmacKey(stretch_key(&key.0.0));
38        // The (stretched) pin key is currently always an AES-256-CBC-HMAC key, and wraps a
39        // bitwarden legacy encoded symmetric key
40        self.to_encoded().encrypt_with_key(&stretched_key)
41    }
42}
43
44impl KeyEncryptable<PinKey, EncString> for String {
45    fn encrypt_with_key(self, key: &PinKey) -> Result<EncString> {
46        self.encrypt_with_key(&SymmetricCryptoKey::Aes256CbcHmacKey(stretch_key(&key.0.0)))
47    }
48}
49
50impl KeyDecryptable<PinKey, String> for EncString {
51    fn decrypt_with_key(&self, key: &PinKey) -> Result<String> {
52        let stretched_key = SymmetricCryptoKey::Aes256CbcHmacKey(stretch_key(&key.0.0));
53        self.decrypt_with_key(&stretched_key)
54    }
55}