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