did_utils/jwk/
prm.rs

1use serde::{Deserialize, Serialize};
2
3extern crate alloc;
4use super::Bytes;
5use alloc::{boxed::Box, collections::BTreeSet, string::String, vec::Vec};
6use base64ct::Base64;
7use core::fmt;
8
9/// JWK parameters unrelated to the key implementation
10#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
11pub struct Parameters {
12    /// The algorithm used with this key.
13    #[serde(skip_serializing_if = "Option::is_none", default)]
14    pub alg: Option<Algorithm>,
15
16    /// The key identifier.
17    #[serde(skip_serializing_if = "Option::is_none", default)]
18    pub kid: Option<String>,
19
20    /// The key class (called `use` in the RFC).
21    #[serde(skip_serializing_if = "Option::is_none", default, rename = "use")]
22    pub cls: Option<Class>,
23
24    /// The key operations (called `key_ops` in the RFC).
25    #[serde(skip_serializing_if = "Option::is_none", default, rename = "key_ops")]
26    pub ops: Option<BTreeSet<Operations>>,
27
28    /// The URL of the X.509 certificate associated with this key.
29    #[serde(skip_serializing_if = "Option::is_none", default)]
30    #[cfg(feature = "url")]
31    pub x5u: Option<url::Url>,
32
33    /// The X.509 certificate associated with this key.
34    #[serde(skip_serializing_if = "Option::is_none", default)]
35    pub x5c: Option<Vec<Bytes<Box<[u8]>, Base64>>>, // base64, not base64url
36
37    /// The X.509 thumbprint associated with this key.
38    #[serde(flatten)]
39    pub x5t: Thumbprint,
40}
41
42impl<T: Into<Algorithm>> From<T> for Parameters {
43    fn from(value: T) -> Self {
44        let alg = Some(value.into());
45
46        let cls = match alg {
47            Some(Algorithm::Signing(..)) => Some(Class::Signing),
48            _ => None,
49        };
50
51        Self {
52            alg,
53            cls,
54            ..Default::default()
55        }
56    }
57}
58
59/// Key Class (i.e. `use` in the RFC)
60#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
61#[allow(missing_docs)]
62#[non_exhaustive]
63pub enum Class {
64    #[serde(rename = "enc")]
65    Encryption,
66
67    #[serde(rename = "sig")]
68    Signing,
69}
70
71/// Key operations (i.e. `key_use` in the RFC)
72// NOTE: Keep in lexicographical order.
73#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
74#[serde(rename_all = "camelCase")]
75#[allow(missing_docs)]
76#[non_exhaustive]
77pub enum Operations {
78    Decrypt,
79    DeriveBits,
80    DeriveKey,
81    Encrypt,
82    Sign,
83    UnwrapKey,
84    Verify,
85    WrapKey,
86}
87
88/// An X.509 thumbprint.
89#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
90pub struct Thumbprint {
91    /// An X.509 thumbprint (SHA-1).
92    #[serde(skip_serializing_if = "Option::is_none", rename = "x5t", default)]
93    pub s1: Option<Bytes<[u8; 20]>>,
94
95    /// An X.509 thumbprint (SHA-2 256).
96    #[serde(skip_serializing_if = "Option::is_none", rename = "x5t#S256", default)]
97    pub s256: Option<Bytes<[u8; 32]>>,
98}
99
100/// Possible types of algorithms that can exist in an "alg" descriptor.
101///
102/// Currently only signing algorithms are represented.
103#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
104#[allow(missing_docs)]
105#[serde(untagged)]
106#[non_exhaustive]
107pub enum Algorithm {
108    /// Algorithms used for digital signatures and MACs
109    Signing(Signing),
110}
111
112impl From<Signing> for Algorithm {
113    #[inline(always)]
114    fn from(alg: Signing) -> Self {
115        Self::Signing(alg)
116    }
117}
118
119/// Algorithms used for signing, as defined in [RFC7518] section 3.1.
120///
121/// [RFC7518]: https://www.rfc-editor.org/rfc/rfc7518
122#[non_exhaustive]
123#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
124#[serde(rename_all = "UPPERCASE")]
125pub enum Signing {
126    /// EdDSA signature algorithms (Optional)
127    #[serde(rename = "EdDSA")]
128    EdDsa,
129
130    /// ECDSA using P-256 and SHA-256 (Recommended+)
131    Es256,
132
133    /// ECDSA using secp256k1 curve and SHA-256 (Optional)
134    Es256K,
135
136    /// ECDSA using P-384 and SHA-384 (Optional)
137    Es384,
138
139    /// ECDSA using P-521 and SHA-512 (Optional)
140    Es512,
141
142    /// HMAC using SHA-256 (Required)
143    Hs256,
144
145    /// HMAC using SHA-384 (Optional)
146    Hs384,
147
148    /// HMAC using SHA-512 (Optional)
149    Hs512,
150
151    /// RSASSA-PSS using SHA-256 and MGF1 with SHA-256 (Optional)
152    Ps256,
153
154    /// RSASSA-PSS using SHA-384 and MGF1 with SHA-384 (Optional)
155    Ps384,
156
157    /// RSASSA-PSS using SHA-512 and MGF1 with SHA-512 (Optional)
158    Ps512,
159
160    /// RSASSA-PKCS1-v1_5 using SHA-256 (Recommended)
161    Rs256,
162
163    /// RSASSA-PKCS1-v1_5 using SHA-384 (Optional)
164    Rs384,
165
166    /// RSASSA-PKCS1-v1_5 using SHA-512 (Optional)
167    Rs512,
168
169    /// No digital signature or MAC performed (Optional)
170    ///
171    /// This variant is renamed as `Null` to avoid colliding with `Option::None`.
172    #[serde(rename = "none")]
173    Null,
174}
175
176impl fmt::Display for Signing {
177    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178        self.serialize(f)
179    }
180}
181
182#[cfg(test)]
183mod tests {
184    extern crate std;
185
186    use std::prelude::rust_2021::*;
187    use std::vec;
188
189    use super::*;
190
191    #[test]
192    fn signing_algs() {
193        use Signing::*;
194
195        let input = vec![
196            EdDsa, Es256, Es256K, Es384, Es512, Hs256, Hs384, Hs512, Ps256, Ps384, Ps512, Rs256, Rs384, Rs512, Null,
197        ];
198        let ser = serde_json::to_string(&input).expect("serialization failed");
199
200        assert_eq!(
201            ser,
202            r#"["EdDSA","ES256","ES256K","ES384","ES512","HS256","HS384","HS512","PS256","PS384","PS512","RS256","RS384","RS512","none"]"#
203        );
204
205        assert_eq!(serde_json::from_str::<Vec<Signing>>(&ser).expect("deserialization failed"), input);
206    }
207}