bitwarden_crypto/traits/
key_id.rs1use std::{fmt::Debug, hash::Hash};
2
3use zeroize::ZeroizeOnDrop;
4
5use crate::{AsymmetricCryptoKey, CryptoKey, SigningKey, SymmetricCryptoKey};
6
7pub trait KeyId:
19 Debug + Clone + Copy + Hash + Eq + PartialEq + Ord + PartialOrd + Send + Sync + 'static
20{
21 #[allow(missing_docs)]
22 type KeyValue: CryptoKey + Send + Sync + ZeroizeOnDrop;
23
24 fn is_local(&self) -> bool;
27}
28
29pub trait KeyIds {
32 #[allow(missing_docs)]
33 type Symmetric: KeyId<KeyValue = SymmetricCryptoKey>;
34 #[allow(missing_docs)]
35 type Asymmetric: KeyId<KeyValue = AsymmetricCryptoKey>;
36 type Signing: KeyId<KeyValue = SigningKey>;
38}
39
40#[macro_export]
66macro_rules! key_ids {
67 ( $(
68 #[$meta_type:tt]
69 $vis:vis enum $name:ident {
70 $(
71 $( #[$variant_tag:tt] )?
72 $variant:ident $( ( $inner:ty ) )?
73 ),*
74 $(,)?
75 }
76 )+
77 $ids_vis:vis $ids_name:ident => $symm_name:ident, $asymm_name:ident, $signing_name:ident;
78 ) => {
79 $(
80 #[derive(std::fmt::Debug, Clone, Copy, std::hash::Hash, Eq, PartialEq, Ord, PartialOrd)]
81 #[allow(missing_docs)]
82 $vis enum $name { $(
83 $variant $( ($inner) )?,
84 )* }
85
86 impl $crate::KeyId for $name {
87 type KeyValue = key_ids!(@key_type $meta_type);
88
89 fn is_local(&self) -> bool {
90 use $name::*;
91 match self { $(
92 key_ids!(@variant_match $variant $( ( $inner ) )?) =>
93 key_ids!(@variant_value $( $variant_tag )? ),
94 )* }
95 }
96 }
97 )+
98
99 #[allow(missing_docs)]
100 $ids_vis struct $ids_name;
101 impl $crate::KeyIds for $ids_name {
102 type Symmetric = $symm_name;
103 type Asymmetric = $asymm_name;
104 type Signing = $signing_name;
105 }
106 };
107
108 ( @key_type symmetric ) => { $crate::SymmetricCryptoKey };
109 ( @key_type asymmetric ) => { $crate::AsymmetricCryptoKey };
110 ( @key_type signing ) => { $crate::SigningKey };
111
112 ( @variant_match $variant:ident ( $inner:ty ) ) => { $variant (_) };
113 ( @variant_match $variant:ident ) => { $variant };
114
115 ( @variant_value local ) => { true };
116 ( @variant_value ) => { false };
117}
118
119#[cfg(test)]
120pub(crate) mod tests {
121 use crate::{
122 traits::tests::{TestAsymmKey, TestSigningKey, TestSymmKey},
123 KeyId,
124 };
125
126 #[test]
127 fn test_local() {
128 assert!(!TestSymmKey::A(0).is_local());
129 assert!(!TestSymmKey::B((4, 10)).is_local());
130 assert!(TestSymmKey::C(8).is_local());
131
132 assert!(!TestAsymmKey::A(0).is_local());
133 assert!(!TestAsymmKey::B.is_local());
134 assert!(TestAsymmKey::C("test").is_local());
135
136 assert!(!TestSigningKey::A(0).is_local());
137 assert!(!TestSigningKey::B.is_local());
138 assert!(TestSigningKey::C("test").is_local());
139 }
140}