bitwarden_crypto/keys/
shareable_key.rs1use std::pin::Pin;
2
3use hmac::{KeyInit, Mac};
4use hybrid_array::Array;
5use typenum::U64;
6use zeroize::Zeroizing;
7
8use super::Aes256CbcHmacKey;
9use crate::util::{PbkdfSha256Hmac, hkdf_expand};
10
11pub fn derive_shareable_key(
16 secret: Zeroizing<[u8; 16]>,
17 name: &str,
18 info: Option<&str>,
19) -> Aes256CbcHmacKey {
20 let res = Zeroizing::new(
22 PbkdfSha256Hmac::new_from_slice(format!("bitwarden-{name}").as_bytes())
23 .expect("hmac new_from_slice should not fail")
24 .chain_update(secret)
25 .finalize()
26 .into_bytes(),
27 );
28
29 let key: Pin<Box<Array<u8, U64>>> = hkdf_expand(&res, info).expect("Input is a valid size");
31 Aes256CbcHmacKey { key }
32}
33
34#[cfg(test)]
35mod tests {
36 use zeroize::Zeroizing;
37
38 use super::derive_shareable_key;
39 use crate::SymmetricCryptoKey;
40
41 #[test]
42 fn test_derive_shareable_key() {
43 let key = derive_shareable_key(Zeroizing::new(*b"&/$%F1a895g67HlX"), "test_key", None);
44 assert_eq!(
45 SymmetricCryptoKey::Aes256CbcHmacKey(key)
46 .to_base64()
47 .to_string(),
48 "4PV6+PcmF2w7YHRatvyMcVQtI7zvCyssv/wFWmzjiH6Iv9altjmDkuBD1aagLVaLezbthbSe+ktR+U6qswxNnQ=="
49 );
50
51 let key = derive_shareable_key(
52 Zeroizing::new(*b"67t9b5g67$%Dh89n"),
53 "test_key",
54 Some("test"),
55 );
56 assert_eq!(
57 SymmetricCryptoKey::Aes256CbcHmacKey(key)
58 .to_base64()
59 .to_string(),
60 "F9jVQmrACGx9VUPjuzfMYDjr726JtL300Y3Yg+VYUnVQtQ1s8oImJ5xtp1KALC9h2nav04++1LDW4iFD+infng=="
61 );
62 }
63}