bitwarden_crypto/keys/
key_id.rs1use rand::RngExt;
2use subtle::ConstantTimeEq;
3use zeroize::Zeroize;
4
5pub(crate) const KEY_ID_SIZE: usize = 16;
7
8#[derive(Clone, PartialEq, Zeroize)]
12pub struct KeyId([u8; KEY_ID_SIZE]);
13
14impl ConstantTimeEq for KeyId {
18 fn ct_eq(&self, other: &Self) -> subtle::Choice {
19 self.0.ct_eq(&other.0)
20 }
21}
22
23impl KeyId {
30 pub fn make() -> Self {
32 let mut rng = rand::rng();
33 let mut key_id = [0u8; KEY_ID_SIZE];
34 rng.fill(&mut key_id);
35 Self(key_id)
36 }
37
38 pub fn as_slice(&self) -> &[u8] {
40 &self.0
41 }
42}
43
44impl TryFrom<&[u8]> for KeyId {
45 type Error = &'static str;
46
47 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
48 if value.len() != KEY_ID_SIZE {
49 return Err("Invalid length for KeyId");
50 }
51 let mut key_id = [0u8; KEY_ID_SIZE];
52 key_id.copy_from_slice(value);
53 Ok(Self(key_id))
54 }
55}
56
57impl From<KeyId> for [u8; KEY_ID_SIZE] {
58 fn from(key_id: KeyId) -> Self {
59 key_id.0
60 }
61}
62
63impl From<&KeyId> for Vec<u8> {
64 fn from(key_id: &KeyId) -> Self {
65 key_id.0.as_slice().to_vec()
66 }
67}
68
69impl From<[u8; KEY_ID_SIZE]> for KeyId {
70 fn from(bytes: [u8; KEY_ID_SIZE]) -> Self {
71 Self(bytes)
72 }
73}
74
75impl std::fmt::Debug for KeyId {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 write!(f, "KeyId({})", hex::encode(self.0))
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 #[ignore = "Manual test to verify debug format"]
87 fn test_key_id_debug() {
88 let key_id = KeyId::make();
89 println!("{:?}", key_id);
90 }
91}