askar_crypto/jwk/
ops.rs

1use core::{
2    fmt::{self, Debug, Display, Formatter},
3    ops::{BitAnd, BitOr},
4};
5
6use serde::{
7    de::{Deserialize, Deserializer, SeqAccess, Visitor},
8    ser::{Serialize, SerializeSeq, Serializer},
9};
10
11#[cfg(feature = "arbitrary")]
12use arbitrary::Arbitrary;
13
14static OPS: &[KeyOps] = &[
15    KeyOps::Encrypt,
16    KeyOps::Decrypt,
17    KeyOps::Sign,
18    KeyOps::Verify,
19    KeyOps::WrapKey,
20    KeyOps::UnwrapKey,
21    KeyOps::DeriveKey,
22    KeyOps::DeriveBits,
23];
24
25/// Supported JWK key operations
26#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
27#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
28#[repr(usize)]
29pub enum KeyOps {
30    /// Allows encryption
31    Encrypt = 1 << 0,
32    /// Allows decryption
33    Decrypt = 1 << 1,
34    /// Allows signature creation
35    Sign = 1 << 2,
36    /// Allows signature verification
37    Verify = 1 << 3,
38    /// Allows key wrapping
39    WrapKey = 1 << 4,
40    /// Allows key unwrapping
41    UnwrapKey = 1 << 5,
42    /// Allows key derivation
43    DeriveKey = 1 << 6,
44    /// Allows derivation of bytes
45    DeriveBits = 1 << 7,
46}
47
48impl Display for KeyOps {
49    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
50        f.write_str(self.as_str())
51    }
52}
53
54impl KeyOps {
55    /// String representation of the key operation
56    pub fn as_str(&self) -> &'static str {
57        match self {
58            Self::Encrypt => "encrypt",
59            Self::Decrypt => "decrypt",
60            Self::Sign => "sign",
61            Self::Verify => "verify",
62            Self::WrapKey => "wrapKey",
63            Self::UnwrapKey => "unwrapKey",
64            Self::DeriveKey => "deriveKey",
65            Self::DeriveBits => "deriveBits",
66        }
67    }
68
69    /// Parse a key operation from a string reference
70    pub fn try_from_str(key: &str) -> Option<Self> {
71        match key {
72            "sign" => Some(Self::Sign),
73            "verify" => Some(Self::Verify),
74            "encrypt" => Some(Self::Encrypt),
75            "decrypt" => Some(Self::Decrypt),
76            "wrapKey" => Some(Self::WrapKey),
77            "unwrapKey" => Some(Self::UnwrapKey),
78            "deriveKey" => Some(Self::DeriveKey),
79            "deriveBits" => Some(Self::DeriveBits),
80            _ => None,
81        }
82    }
83}
84
85impl BitOr<Self> for KeyOps {
86    type Output = KeyOpsSet;
87
88    fn bitor(self, rhs: Self) -> Self::Output {
89        KeyOpsSet {
90            value: self as usize | rhs as usize,
91        }
92    }
93}
94
95/// A set of key operations
96#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
97#[repr(transparent)]
98#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
99pub struct KeyOpsSet {
100    value: usize,
101}
102
103impl KeyOpsSet {
104    /// Create a new, empty operation set
105    pub const fn new() -> Self {
106        Self { value: 0 }
107    }
108
109    /// Check if an operation set is empty
110    pub fn is_empty(&self) -> bool {
111        self.value == 0
112    }
113}
114
115impl Default for KeyOpsSet {
116    fn default() -> Self {
117        Self::new()
118    }
119}
120
121impl BitOr<Self> for KeyOpsSet {
122    type Output = Self;
123
124    fn bitor(self, rhs: Self) -> Self::Output {
125        KeyOpsSet {
126            value: self.value | rhs.value,
127        }
128    }
129}
130
131impl BitOr<KeyOps> for KeyOpsSet {
132    type Output = KeyOpsSet;
133
134    fn bitor(self, rhs: KeyOps) -> Self::Output {
135        KeyOpsSet {
136            value: self.value | rhs as usize,
137        }
138    }
139}
140
141impl BitAnd<KeyOps> for KeyOpsSet {
142    type Output = bool;
143
144    fn bitand(self, rhs: KeyOps) -> Self::Output {
145        self.value & rhs as usize != 0
146    }
147}
148
149impl BitAnd<Self> for KeyOpsSet {
150    type Output = bool;
151
152    fn bitand(self, rhs: Self) -> Self::Output {
153        self.value & rhs.value != 0
154    }
155}
156
157impl Debug for KeyOpsSet {
158    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
159        let mut vals = &mut f.debug_set();
160        for op in self {
161            vals = vals.entry(&op.as_str());
162        }
163        vals.finish()
164    }
165}
166
167impl From<KeyOps> for KeyOpsSet {
168    fn from(op: KeyOps) -> Self {
169        Self { value: op as usize }
170    }
171}
172
173impl IntoIterator for &KeyOpsSet {
174    type IntoIter = KeyOpsIter;
175    type Item = KeyOps;
176
177    fn into_iter(self) -> Self::IntoIter {
178        KeyOpsIter {
179            index: 0,
180            value: *self,
181        }
182    }
183}
184
185#[derive(Debug)]
186pub struct KeyOpsIter {
187    index: usize,
188    value: KeyOpsSet,
189}
190
191impl Iterator for KeyOpsIter {
192    type Item = KeyOps;
193
194    fn next(&mut self) -> Option<Self::Item> {
195        while self.index < OPS.len() {
196            let op = OPS[self.index];
197            self.index += 1;
198            if self.value & op {
199                return Some(op);
200            }
201        }
202        None
203    }
204}
205
206struct KeyOpsVisitor;
207
208impl<'de> Visitor<'de> for KeyOpsVisitor {
209    type Value = KeyOpsSet;
210
211    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
212        formatter.write_str("an array of key operations")
213    }
214
215    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
216    where
217        A: SeqAccess<'de>,
218    {
219        let mut ops = KeyOpsSet::new();
220        while let Some(op) = seq.next_element()? {
221            if let Some(op) = KeyOps::try_from_str(op) {
222                if ops & op {
223                    return Err(serde::de::Error::duplicate_field(op.as_str()));
224                } else {
225                    ops = ops | op;
226                }
227            }
228        }
229        Ok(ops)
230    }
231}
232
233impl<'de> Deserialize<'de> for KeyOpsSet {
234    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
235    where
236        D: Deserializer<'de>,
237    {
238        deserializer.deserialize_seq(KeyOpsVisitor)
239    }
240}
241
242impl Serialize for KeyOpsSet {
243    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
244    where
245        S: Serializer,
246    {
247        let mut seq = serializer.serialize_seq(None)?;
248        for op in self {
249            seq.serialize_element(op.as_str())?;
250        }
251        seq.end()
252    }
253}
254
255#[cfg(test)]
256mod tests {
257    use super::*;
258
259    #[test]
260    fn invariants() {
261        assert!(KeyOpsSet::new().is_empty());
262        assert!(!KeyOpsSet::from(KeyOps::Decrypt).is_empty());
263        assert_eq!(KeyOpsSet::new(), KeyOpsSet::new());
264        assert_ne!(KeyOpsSet::from(KeyOps::Decrypt), KeyOpsSet::new());
265        assert_ne!(KeyOps::Decrypt, KeyOps::Encrypt);
266        assert_ne!(
267            KeyOpsSet::from(KeyOps::Decrypt),
268            KeyOpsSet::from(KeyOps::Encrypt)
269        );
270        assert_eq!(
271            KeyOps::Decrypt | KeyOps::Encrypt,
272            KeyOps::Encrypt | KeyOps::Decrypt
273        );
274    }
275
276    #[test]
277    fn debug_format() {
278        assert_eq!(
279            format!("{:?}", KeyOps::Decrypt | KeyOps::Encrypt),
280            "{\"encrypt\", \"decrypt\"}"
281        );
282    }
283}