bitwarden_crypto/keys/
key_id.rs1use rand::Rng;
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::thread_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] {
39 &self.0
40 }
41}
42
43impl TryFrom<&[u8]> for KeyId {
44 type Error = &'static str;
45
46 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
47 if value.len() != KEY_ID_SIZE {
48 return Err("Invalid length for KeyId");
49 }
50 let mut key_id = [0u8; KEY_ID_SIZE];
51 key_id.copy_from_slice(value);
52 Ok(Self(key_id))
53 }
54}
55
56impl From<KeyId> for [u8; KEY_ID_SIZE] {
57 fn from(key_id: KeyId) -> Self {
58 key_id.0
59 }
60}
61
62impl From<&KeyId> for Vec<u8> {
63 fn from(key_id: &KeyId) -> Self {
64 key_id.0.as_slice().to_vec()
65 }
66}
67
68impl From<[u8; KEY_ID_SIZE]> for KeyId {
69 fn from(bytes: [u8; KEY_ID_SIZE]) -> Self {
70 Self(bytes)
71 }
72}
73
74impl std::fmt::Debug for KeyId {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 write!(f, "KeyId({})", hex::encode(self.0))
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 #[ignore = "Manual test to verify debug format"]
86 fn test_key_id_debug() {
87 let key_id = KeyId::make();
88 println!("{:?}", key_id);
89 }
90}