jose_jwa/
lib.rs

1// SPDX-FileCopyrightText: 2022 Profian Inc. <opensource@profian.com>
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4#![doc = include_str!("../README.md")]
5#![no_std]
6#![cfg_attr(docsrs, feature(doc_auto_cfg))]
7#![doc(
8    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
9    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
10)]
11#![forbid(unsafe_code)]
12#![warn(
13    clippy::panic,
14    clippy::panic_in_result_fn,
15    clippy::unwrap_used,
16    missing_docs,
17    rust_2018_idioms,
18    unused_lifetimes,
19    unused_qualifications
20)]
21
22use core::fmt;
23
24use serde::{Deserialize, Serialize};
25
26/// Possible types of algorithms that can exist in an "alg" descriptor.
27///
28/// Currently only signing algorithms are represented.
29#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
30#[allow(missing_docs)]
31#[serde(untagged)]
32#[non_exhaustive]
33pub enum Algorithm {
34    /// Algorithms used for digital signatures and MACs
35    Signing(Signing),
36}
37
38impl From<Signing> for Algorithm {
39    #[inline(always)]
40    fn from(alg: Signing) -> Self {
41        Self::Signing(alg)
42    }
43}
44
45/// Algorithms used for signing, as defined in [RFC7518] section 3.1.
46///
47/// [RFC7518]: https://www.rfc-editor.org/rfc/rfc7518
48#[non_exhaustive]
49#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
50#[serde(rename_all = "UPPERCASE")]
51pub enum Signing {
52    /// EdDSA signature algorithms (Optional)
53    #[serde(rename = "EdDSA")]
54    EdDsa,
55
56    /// ECDSA using P-256 and SHA-256 (Recommended+)
57    Es256,
58
59    /// ECDSA using secp256k1 curve and SHA-256 (Optional)
60    Es256K,
61
62    /// ECDSA using P-384 and SHA-384 (Optional)
63    Es384,
64
65    /// ECDSA using P-521 and SHA-512 (Optional)
66    Es512,
67
68    /// HMAC using SHA-256 (Required)
69    Hs256,
70
71    /// HMAC using SHA-384 (Optional)
72    Hs384,
73
74    /// HMAC using SHA-512 (Optional)
75    Hs512,
76
77    /// RSASSA-PSS using SHA-256 and MGF1 with SHA-256 (Optional)
78    Ps256,
79
80    /// RSASSA-PSS using SHA-384 and MGF1 with SHA-384 (Optional)
81    Ps384,
82
83    /// RSASSA-PSS using SHA-512 and MGF1 with SHA-512 (Optional)
84    Ps512,
85
86    /// RSASSA-PKCS1-v1_5 using SHA-256 (Recommended)
87    Rs256,
88
89    /// RSASSA-PKCS1-v1_5 using SHA-384 (Optional)
90    Rs384,
91
92    /// RSASSA-PKCS1-v1_5 using SHA-512 (Optional)
93    Rs512,
94
95    /// No digital signature or MAC performed (Optional)
96    ///
97    /// This variant is renamed as `Null` to avoid colliding with `Option::None`.
98    #[serde(rename = "none")]
99    Null,
100}
101
102impl fmt::Display for Signing {
103    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104        self.serialize(f)
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    extern crate std;
111
112    use std::prelude::rust_2021::*;
113    use std::vec;
114
115    use super::*;
116
117    #[test]
118    fn simple_roundtrip() {
119        use Signing::*;
120
121        let input = vec![
122            EdDsa, Es256, Es256K, Es384, Es512, Hs256, Hs384, Hs512, Ps256, Ps384, Ps512, Rs256,
123            Rs384, Rs512, Null,
124        ];
125        let ser = serde_json::to_string(&input).expect("serialization failed");
126
127        assert_eq!(
128            ser,
129            r#"["EdDSA","ES256","ES256K","ES384","ES512","HS256","HS384","HS512","PS256","PS384","PS512","RS256","RS384","RS512","none"]"#
130        );
131
132        assert_eq!(
133            serde_json::from_str::<Vec<Signing>>(&ser).expect("deserialization failed"),
134            input
135        );
136    }
137}