1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-29 22:01:14 +03:00

Multiple IANA codegen enhancement

- JWS/JWE algorithms are properly splitted
 - Enums now have a proper description
 - They implement FromStr and Display
 - mas-jose does not reexport mas-iana anymore
This commit is contained in:
Quentin Gliech
2022-01-12 10:58:27 +01:00
parent d9b1ef3ded
commit 2844706bb1
21 changed files with 401 additions and 497 deletions

1
Cargo.lock generated
View File

@ -1599,6 +1599,7 @@ dependencies = [
name = "mas-iana" name = "mas-iana"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"parse-display",
"schemars", "schemars",
"serde", "serde",
] ]

View File

@ -15,7 +15,8 @@
use std::collections::HashSet; use std::collections::HashSet;
use mas_config::OAuth2Config; use mas_config::OAuth2Config;
use mas_jose::{JsonWebSignatureAlgorithm, SigningKeystore}; use mas_iana::jose::JsonWebSignatureAlg;
use mas_jose::SigningKeystore;
use oauth2_types::{ use oauth2_types::{
oidc::{ClaimType, Metadata, SubjectType}, oidc::{ClaimType, Metadata, SubjectType},
pkce::CodeChallengeMethod, pkce::CodeChallengeMethod,
@ -43,12 +44,12 @@ pub(super) fn filter(
let client_auth_signing_alg_values_supported = Some({ let client_auth_signing_alg_values_supported = Some({
let mut s = HashSet::new(); let mut s = HashSet::new();
s.insert(JsonWebSignatureAlgorithm::Hs256); s.insert(JsonWebSignatureAlg::Hs256);
s.insert(JsonWebSignatureAlgorithm::Hs384); s.insert(JsonWebSignatureAlg::Hs384);
s.insert(JsonWebSignatureAlgorithm::Hs512); s.insert(JsonWebSignatureAlg::Hs512);
s.insert(JsonWebSignatureAlgorithm::Rs256); s.insert(JsonWebSignatureAlg::Rs256);
s.insert(JsonWebSignatureAlgorithm::Rs384); s.insert(JsonWebSignatureAlg::Rs384);
s.insert(JsonWebSignatureAlgorithm::Rs512); s.insert(JsonWebSignatureAlg::Rs512);
s s
}); });

View File

@ -21,9 +21,10 @@ use headers::{CacheControl, Pragma};
use hyper::StatusCode; use hyper::StatusCode;
use mas_config::{OAuth2ClientConfig, OAuth2Config}; use mas_config::{OAuth2ClientConfig, OAuth2Config};
use mas_data_model::{AuthorizationGrantStage, TokenType}; use mas_data_model::{AuthorizationGrantStage, TokenType};
use mas_iana::jose::JsonWebSignatureAlg;
use mas_jose::{ use mas_jose::{
claims::{AT_HASH, AUD, AUTH_TIME, C_HASH, EXP, IAT, ISS, NONCE, SUB}, claims::{AT_HASH, AUD, AUTH_TIME, C_HASH, EXP, IAT, ISS, NONCE, SUB},
DecodedJsonWebToken, JsonWebSignatureAlgorithm, SigningKeystore, StaticKeystore, DecodedJsonWebToken, SigningKeystore, StaticKeystore,
}; };
use mas_storage::{ use mas_storage::{
oauth2::{ oauth2::{
@ -288,7 +289,7 @@ async fn authorization_code_grant(
.wrap_error()?; .wrap_error()?;
let header = key_store let header = key_store
.prepare_header(JsonWebSignatureAlgorithm::Rs256) .prepare_header(JsonWebSignatureAlg::Rs256)
.await .await
.wrap_error()?; .wrap_error()?;
let id_token = DecodedJsonWebToken::new(header, claims); let id_token = DecodedJsonWebToken::new(header, claims);

View File

@ -14,7 +14,10 @@
use serde::Deserialize; use serde::Deserialize;
use crate::EnumEntry; use crate::{
traits::{s, Section},
EnumEntry,
};
#[derive(Debug, Deserialize, PartialEq, Eq)] #[derive(Debug, Deserialize, PartialEq, Eq)]
enum Usage { enum Usage {
@ -60,13 +63,41 @@ pub struct WebEncryptionSignatureAlgorithm {
impl EnumEntry for WebEncryptionSignatureAlgorithm { impl EnumEntry for WebEncryptionSignatureAlgorithm {
const URL: &'static str = const URL: &'static str =
"https://www.iana.org/assignments/jose/web-signature-encryption-algorithms.csv"; "https://www.iana.org/assignments/jose/web-signature-encryption-algorithms.csv";
const SECTIONS: &'static [&'static str] = const SECTIONS: &'static [Section] = &[
&["JsonWebSignatureAlgorithm", "JsonWebEncryptionAlgorithm"]; s(
"JsonWebSignatureAlg",
r#"JSON Web Signature "alg" parameter"#,
),
s(
"JsonWebEncryptionAlg",
r#"JSON Web Encryption "alg" parameter"#,
),
s(
"JsonWebEncryptionEnc",
r#"JSON Web Encryption "enc" parameter"#,
),
];
fn key(&self) -> Option<&'static str> { fn key(&self) -> Option<&'static str> {
match self.usage { match self.usage {
Usage::Alg => Some("JsonWebSignatureAlgorithm"), Usage::Alg => {
Usage::Enc => Some("JsonWebEncryptionAlgorithm"), // RFC7518 has one for signature algs and one for encryption algs. The other two
// RFCs are additional Elliptic curve signature algs
if self.reference.contains("RFC7518, Section 3")
|| self.reference.contains("RFC8037")
|| self.reference.contains("RFC8812")
{
Some("JsonWebSignatureAlg")
} else if self.reference.contains("RFC7518, Section 4")
|| self.reference.contains("WebCryptoAPI")
{
Some("JsonWebEncryptionAlg")
} else {
tracing::warn!("Unknown reference {} for JWA", self.reference);
None
}
}
Usage::Enc => Some("JsonWebEncryptionEnc"),
_ => None, _ => None,
} }
} }
@ -96,7 +127,10 @@ pub struct WebEncryptionCompressionAlgorithm {
impl EnumEntry for WebEncryptionCompressionAlgorithm { impl EnumEntry for WebEncryptionCompressionAlgorithm {
const URL: &'static str = const URL: &'static str =
"https://www.iana.org/assignments/jose/web-encryption-compression-algorithms.csv"; "https://www.iana.org/assignments/jose/web-encryption-compression-algorithms.csv";
const SECTIONS: &'static [&'static str] = &["JsonWebEncryptionCompressionAlgorithm"]; const SECTIONS: &'static [Section] = &[s(
"JsonWebEncryptionCompressionAlgorithm",
"JSON Web Encryption Compression Algorithm",
)];
fn key(&self) -> Option<&'static str> { fn key(&self) -> Option<&'static str> {
Some("JsonWebEncryptionCompressionAlgorithm") Some("JsonWebEncryptionCompressionAlgorithm")
@ -128,7 +162,7 @@ pub struct WebKeyType {
impl EnumEntry for WebKeyType { impl EnumEntry for WebKeyType {
const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-types.csv"; const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-types.csv";
const SECTIONS: &'static [&'static str] = &["JsonWebKeyType"]; const SECTIONS: &'static [Section] = &[s("JsonWebKeyType", "JSON Web Key Type")];
fn key(&self) -> Option<&'static str> { fn key(&self) -> Option<&'static str> {
Some("JsonWebKeyType") Some("JsonWebKeyType")
@ -160,8 +194,16 @@ pub struct WebKeyEllipticCurve {
impl EnumEntry for WebKeyEllipticCurve { impl EnumEntry for WebKeyEllipticCurve {
const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-elliptic-curve.csv"; const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-elliptic-curve.csv";
const SECTIONS: &'static [&'static str] = const SECTIONS: &'static [Section] = &[
&["JsonWebKeyEcEllipticCurve", "JsonWebKeyOkpEllipticCurve"]; s(
"JsonWebKeyEcEllipticCurve",
"JSON Web Key EC Elliptic Curve",
),
s(
"JsonWebKeyOkpEllipticCurve",
"JSON Web Key OKP Elliptic Curve",
),
];
fn key(&self) -> Option<&'static str> { fn key(&self) -> Option<&'static str> {
if self.name.starts_with("P-") || self.name == "secp256k1" { if self.name.starts_with("P-") || self.name == "secp256k1" {
@ -195,7 +237,7 @@ pub struct WebKeyUse {
impl EnumEntry for WebKeyUse { impl EnumEntry for WebKeyUse {
const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-use.csv"; const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-use.csv";
const SECTIONS: &'static [&'static str] = &["JsonWebKeyUse"]; const SECTIONS: &'static [Section] = &[s("JsonWebKeyUse", "JSON Web Key Use")];
fn key(&self) -> Option<&'static str> { fn key(&self) -> Option<&'static str> {
Some("JsonWebKeyUse") Some("JsonWebKeyUse")
@ -225,7 +267,7 @@ pub struct WebKeyOperation {
impl EnumEntry for WebKeyOperation { impl EnumEntry for WebKeyOperation {
const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-operations.csv"; const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-operations.csv";
const SECTIONS: &'static [&'static str] = &["JsonWebKeyOperation"]; const SECTIONS: &'static [Section] = &[s("JsonWebKeyOperation", "JSON Web Key Operation")];
fn key(&self) -> Option<&'static str> { fn key(&self) -> Option<&'static str> {
Some("JsonWebKeyOperation") Some("JsonWebKeyOperation")

View File

@ -27,8 +27,7 @@ struct File {
client: Arc<Client>, client: Arc<Client>,
registry_name: &'static str, registry_name: &'static str,
registry_url: &'static str, registry_url: &'static str,
sections: Vec<&'static str>, sections: Vec<Section>,
sources: Vec<&'static str>,
items: HashMap<&'static str, Vec<EnumMember>>, items: HashMap<&'static str, Vec<EnumMember>>,
} }
@ -46,7 +45,6 @@ impl File {
client, client,
registry_name, registry_name,
registry_url, registry_url,
sources: Vec::new(),
sections: Vec::new(), sections: Vec::new(),
items: HashMap::new(), items: HashMap::new(),
} }
@ -55,8 +53,7 @@ impl File {
#[tracing::instrument(skip_all, fields(url))] #[tracing::instrument(skip_all, fields(url))]
async fn load<T: EnumEntry>(mut self) -> anyhow::Result<Self> { async fn load<T: EnumEntry>(mut self) -> anyhow::Result<Self> {
tracing::Span::current().record("url", &T::URL); tracing::Span::current().record("url", &T::URL);
self.sections.extend_from_slice(T::SECTIONS); self.sections.extend(T::sections());
self.sources.push(T::URL);
for (key, value) in T::fetch(&self.client).await? { for (key, value) in T::fetch(&self.client).await? {
self.items.entry(key).or_default().push(value); self.items.entry(key).or_default().push(value);
} }
@ -99,43 +96,43 @@ impl Display for File {
//! Enums from the {:?} IANA registry //! Enums from the {:?} IANA registry
//! See <{}> //! See <{}>
//!
//! Generated from:"#, // Do not edit this file manually
use parse_display::{{Display, FromStr}};
use schemars::JsonSchema;
use serde::{{Deserialize, Serialize}};"#,
self.registry_name, self.registry_url, self.registry_name, self.registry_url,
)?; )?;
for source in &self.sources { for section in &self.sections {
writeln!(f, "//! - <{}>", source)?; let list = if let Some(list) = self.items.get(section.key) {
}
writeln!(
f,
r#"
// Do not edit this file manually
use schemars::JsonSchema;
use serde::{{Deserialize, Serialize}};"#
)?;
for key in &self.sections {
let list = if let Some(list) = self.items.get(key) {
list list
} else { } else {
continue; continue;
}; };
writeln!(f)?; write!(
writeln!(
f, f,
"#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]" r#"
/// {}
///
/// Source: <{}>
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum {} {{"#,
section.doc,
section.url.unwrap(),
section.key,
)?; )?;
write!(f, "pub enum {} {{", key)?;
for member in list { for member in list {
writeln!(f)?; writeln!(f)?;
if let Some(description) = &member.description { if let Some(description) = &member.description {
writeln!(f, " /// {}", description)?; writeln!(f, " /// {}", description)?;
} }
writeln!(f, " #[serde(rename = \"{}\")]", member.value)?; writeln!(f, " #[serde(rename = \"{}\")]", member.value)?;
writeln!(f, " #[display(\"{}\")]", member.value)?;
writeln!(f, " {},", member.enum_name)?; writeln!(f, " {},", member.enum_name)?;
} }
writeln!(f, "}}")?; writeln!(f, "}}")?;

View File

@ -14,7 +14,10 @@
use serde::Deserialize; use serde::Deserialize;
use crate::EnumEntry; use crate::{
traits::{s, Section},
EnumEntry,
};
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -30,7 +33,7 @@ pub struct TokenTypeHint {
impl EnumEntry for TokenTypeHint { impl EnumEntry for TokenTypeHint {
const URL: &'static str = const URL: &'static str =
"https://www.iana.org/assignments/oauth-parameters/token-type-hint.csv"; "https://www.iana.org/assignments/oauth-parameters/token-type-hint.csv";
const SECTIONS: &'static [&'static str] = &["OAuthTokenTypeHint"]; const SECTIONS: &'static [Section] = &[s("OAuthTokenTypeHint", "OAuth Token Type Hint")];
fn key(&self) -> Option<&'static str> { fn key(&self) -> Option<&'static str> {
Some("OAuthTokenTypeHint") Some("OAuthTokenTypeHint")
@ -54,7 +57,10 @@ pub struct AuthorizationEndpointResponseType {
impl EnumEntry for AuthorizationEndpointResponseType { impl EnumEntry for AuthorizationEndpointResponseType {
const URL: &'static str = "https://www.iana.org/assignments/oauth-parameters/endpoint.csv"; const URL: &'static str = "https://www.iana.org/assignments/oauth-parameters/endpoint.csv";
const SECTIONS: &'static [&'static str] = &["OAuthAuthorizationEndpointResponseType"]; const SECTIONS: &'static [Section] = &[s(
"OAuthAuthorizationEndpointResponseType",
"OAuth Authorization Endpoint Response Type",
)];
fn key(&self) -> Option<&'static str> { fn key(&self) -> Option<&'static str> {
Some("OAuthAuthorizationEndpointResponseType") Some("OAuthAuthorizationEndpointResponseType")
@ -79,7 +85,10 @@ pub struct TokenEndpointAuthenticationMethod {
impl EnumEntry for TokenEndpointAuthenticationMethod { impl EnumEntry for TokenEndpointAuthenticationMethod {
const URL: &'static str = const URL: &'static str =
"https://www.iana.org/assignments/oauth-parameters/token-endpoint-auth-method.csv"; "https://www.iana.org/assignments/oauth-parameters/token-endpoint-auth-method.csv";
const SECTIONS: &'static [&'static str] = &["OAuthTokenEndpointAuthenticationMethod"]; const SECTIONS: &'static [Section] = &[s(
"OAuthTokenEndpointAuthenticationMethod",
"OAuth Token Endpoint Authentication Method",
)];
fn key(&self) -> Option<&'static str> { fn key(&self) -> Option<&'static str> {
Some("OAuthTokenEndpointAuthenticationMethod") Some("OAuthTokenEndpointAuthenticationMethod")
@ -104,7 +113,8 @@ pub struct PkceCodeChallengeMethod {
impl EnumEntry for PkceCodeChallengeMethod { impl EnumEntry for PkceCodeChallengeMethod {
const URL: &'static str = const URL: &'static str =
"https://www.iana.org/assignments/oauth-parameters/pkce-code-challenge-method.csv"; "https://www.iana.org/assignments/oauth-parameters/pkce-code-challenge-method.csv";
const SECTIONS: &'static [&'static str] = &["PkceCodeChallengeMethod"]; const SECTIONS: &'static [Section] =
&[s("PkceCodeChallengeMethod", "PKCE Code Challenge Method")];
fn key(&self) -> Option<&'static str> { fn key(&self) -> Option<&'static str> {
Some("PkceCodeChallengeMethod") Some("PkceCodeChallengeMethod")

View File

@ -18,6 +18,21 @@ use convert_case::{Case, Casing};
use reqwest::Client; use reqwest::Client;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
#[derive(Debug, Clone)]
pub struct Section {
pub key: &'static str,
pub doc: &'static str,
pub url: Option<&'static str>,
}
pub const fn s(key: &'static str, doc: &'static str) -> Section {
Section {
key,
doc,
url: None,
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct EnumMember { pub struct EnumMember {
pub value: String, pub value: String,
@ -28,7 +43,17 @@ pub struct EnumMember {
#[async_trait] #[async_trait]
pub trait EnumEntry: DeserializeOwned + Send + Sync { pub trait EnumEntry: DeserializeOwned + Send + Sync {
const URL: &'static str; const URL: &'static str;
const SECTIONS: &'static [&'static str]; const SECTIONS: &'static [Section];
fn sections() -> Vec<Section> {
Self::SECTIONS
.iter()
.map(|s| Section {
url: Some(Self::URL),
..*s
})
.collect()
}
fn key(&self) -> Option<&'static str>; fn key(&self) -> Option<&'static str>;
fn name(&self) -> &str; fn name(&self) -> &str;

View File

@ -8,3 +8,4 @@ license = "Apache-2.0"
[dependencies] [dependencies]
serde = "1.0.133" serde = "1.0.133"
schemars = { version = "0.8.8" } schemars = { version = "0.8.8" }
parse-display = "0.5.3"

View File

@ -14,292 +14,396 @@
//! Enums from the "JSON Object Signing and Encryption" IANA registry //! Enums from the "JSON Object Signing and Encryption" IANA registry
//! See <https://www.iana.org/assignments/jose/jose.xhtml> //! See <https://www.iana.org/assignments/jose/jose.xhtml>
//!
//! Generated from:
//! - <https://www.iana.org/assignments/jose/web-signature-encryption-algorithms.csv>
//! - <https://www.iana.org/assignments/jose/web-encryption-compression-algorithms.csv>
//! - <https://www.iana.org/assignments/jose/web-key-types.csv>
//! - <https://www.iana.org/assignments/jose/web-key-elliptic-curve.csv>
//! - <https://www.iana.org/assignments/jose/web-key-use.csv>
//! - <https://www.iana.org/assignments/jose/web-key-operations.csv>
// Do not edit this file manually // Do not edit this file manually
use parse_display::{Display, FromStr};
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] /// JSON Web Signature "alg" parameter
pub enum JsonWebSignatureAlgorithm { ///
/// Source: <https://www.iana.org/assignments/jose/web-signature-encryption-algorithms.csv>
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum JsonWebSignatureAlg {
/// HMAC using SHA-256 /// HMAC using SHA-256
#[serde(rename = "HS256")] #[serde(rename = "HS256")]
#[display("HS256")]
Hs256, Hs256,
/// HMAC using SHA-384 /// HMAC using SHA-384
#[serde(rename = "HS384")] #[serde(rename = "HS384")]
#[display("HS384")]
Hs384, Hs384,
/// HMAC using SHA-512 /// HMAC using SHA-512
#[serde(rename = "HS512")] #[serde(rename = "HS512")]
#[display("HS512")]
Hs512, Hs512,
/// RSASSA-PKCS1-v1_5 using SHA-256 /// RSASSA-PKCS1-v1_5 using SHA-256
#[serde(rename = "RS256")] #[serde(rename = "RS256")]
#[display("RS256")]
Rs256, Rs256,
/// RSASSA-PKCS1-v1_5 using SHA-384 /// RSASSA-PKCS1-v1_5 using SHA-384
#[serde(rename = "RS384")] #[serde(rename = "RS384")]
#[display("RS384")]
Rs384, Rs384,
/// RSASSA-PKCS1-v1_5 using SHA-512 /// RSASSA-PKCS1-v1_5 using SHA-512
#[serde(rename = "RS512")] #[serde(rename = "RS512")]
#[display("RS512")]
Rs512, Rs512,
/// ECDSA using P-256 and SHA-256 /// ECDSA using P-256 and SHA-256
#[serde(rename = "ES256")] #[serde(rename = "ES256")]
#[display("ES256")]
Es256, Es256,
/// ECDSA using P-384 and SHA-384 /// ECDSA using P-384 and SHA-384
#[serde(rename = "ES384")] #[serde(rename = "ES384")]
#[display("ES384")]
Es384, Es384,
/// ECDSA using P-521 and SHA-512 /// ECDSA using P-521 and SHA-512
#[serde(rename = "ES512")] #[serde(rename = "ES512")]
#[display("ES512")]
Es512, Es512,
/// RSASSA-PSS using SHA-256 and MGF1 with SHA-256 /// RSASSA-PSS using SHA-256 and MGF1 with SHA-256
#[serde(rename = "PS256")] #[serde(rename = "PS256")]
#[display("PS256")]
Ps256, Ps256,
/// RSASSA-PSS using SHA-384 and MGF1 with SHA-384 /// RSASSA-PSS using SHA-384 and MGF1 with SHA-384
#[serde(rename = "PS384")] #[serde(rename = "PS384")]
#[display("PS384")]
Ps384, Ps384,
/// RSASSA-PSS using SHA-512 and MGF1 with SHA-512 /// RSASSA-PSS using SHA-512 and MGF1 with SHA-512
#[serde(rename = "PS512")] #[serde(rename = "PS512")]
#[display("PS512")]
Ps512, Ps512,
/// No digital signature or MAC performed /// No digital signature or MAC performed
#[serde(rename = "none")] #[serde(rename = "none")]
#[display("none")]
None, None,
/// EdDSA signature algorithms
#[serde(rename = "EdDSA")]
#[display("EdDSA")]
EdDsa,
/// ECDSA using secp256k1 curve and SHA-256
#[serde(rename = "ES256K")]
#[display("ES256K")]
Es256K,
}
/// JSON Web Encryption "alg" parameter
///
/// Source: <https://www.iana.org/assignments/jose/web-signature-encryption-algorithms.csv>
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum JsonWebEncryptionAlg {
/// RSAES-PKCS1-v1_5 /// RSAES-PKCS1-v1_5
#[serde(rename = "RSA1_5")] #[serde(rename = "RSA1_5")]
#[display("RSA1_5")]
Rsa15, Rsa15,
/// RSAES OAEP using default parameters /// RSAES OAEP using default parameters
#[serde(rename = "RSA-OAEP")] #[serde(rename = "RSA-OAEP")]
#[display("RSA-OAEP")]
RsaOaep, RsaOaep,
/// RSAES OAEP using SHA-256 and MGF1 with SHA-256 /// RSAES OAEP using SHA-256 and MGF1 with SHA-256
#[serde(rename = "RSA-OAEP-256")] #[serde(rename = "RSA-OAEP-256")]
#[display("RSA-OAEP-256")]
RsaOaep256, RsaOaep256,
/// AES Key Wrap using 128-bit key /// AES Key Wrap using 128-bit key
#[serde(rename = "A128KW")] #[serde(rename = "A128KW")]
#[display("A128KW")]
A128Kw, A128Kw,
/// AES Key Wrap using 192-bit key /// AES Key Wrap using 192-bit key
#[serde(rename = "A192KW")] #[serde(rename = "A192KW")]
#[display("A192KW")]
A192Kw, A192Kw,
/// AES Key Wrap using 256-bit key /// AES Key Wrap using 256-bit key
#[serde(rename = "A256KW")] #[serde(rename = "A256KW")]
#[display("A256KW")]
A256Kw, A256Kw,
/// Direct use of a shared symmetric key /// Direct use of a shared symmetric key
#[serde(rename = "dir")] #[serde(rename = "dir")]
#[display("dir")]
Dir, Dir,
/// ECDH-ES using Concat KDF /// ECDH-ES using Concat KDF
#[serde(rename = "ECDH-ES")] #[serde(rename = "ECDH-ES")]
#[display("ECDH-ES")]
EcdhEs, EcdhEs,
/// ECDH-ES using Concat KDF and "A128KW" wrapping /// ECDH-ES using Concat KDF and "A128KW" wrapping
#[serde(rename = "ECDH-ES+A128KW")] #[serde(rename = "ECDH-ES+A128KW")]
#[display("ECDH-ES+A128KW")]
EcdhEsA128Kw, EcdhEsA128Kw,
/// ECDH-ES using Concat KDF and "A192KW" wrapping /// ECDH-ES using Concat KDF and "A192KW" wrapping
#[serde(rename = "ECDH-ES+A192KW")] #[serde(rename = "ECDH-ES+A192KW")]
#[display("ECDH-ES+A192KW")]
EcdhEsA192Kw, EcdhEsA192Kw,
/// ECDH-ES using Concat KDF and "A256KW" wrapping /// ECDH-ES using Concat KDF and "A256KW" wrapping
#[serde(rename = "ECDH-ES+A256KW")] #[serde(rename = "ECDH-ES+A256KW")]
#[display("ECDH-ES+A256KW")]
EcdhEsA256Kw, EcdhEsA256Kw,
/// Key wrapping with AES GCM using 128-bit key /// Key wrapping with AES GCM using 128-bit key
#[serde(rename = "A128GCMKW")] #[serde(rename = "A128GCMKW")]
#[display("A128GCMKW")]
A128Gcmkw, A128Gcmkw,
/// Key wrapping with AES GCM using 192-bit key /// Key wrapping with AES GCM using 192-bit key
#[serde(rename = "A192GCMKW")] #[serde(rename = "A192GCMKW")]
#[display("A192GCMKW")]
A192Gcmkw, A192Gcmkw,
/// Key wrapping with AES GCM using 256-bit key /// Key wrapping with AES GCM using 256-bit key
#[serde(rename = "A256GCMKW")] #[serde(rename = "A256GCMKW")]
#[display("A256GCMKW")]
A256Gcmkw, A256Gcmkw,
/// PBES2 with HMAC SHA-256 and "A128KW" wrapping /// PBES2 with HMAC SHA-256 and "A128KW" wrapping
#[serde(rename = "PBES2-HS256+A128KW")] #[serde(rename = "PBES2-HS256+A128KW")]
#[display("PBES2-HS256+A128KW")]
Pbes2Hs256A128Kw, Pbes2Hs256A128Kw,
/// PBES2 with HMAC SHA-384 and "A192KW" wrapping /// PBES2 with HMAC SHA-384 and "A192KW" wrapping
#[serde(rename = "PBES2-HS384+A192KW")] #[serde(rename = "PBES2-HS384+A192KW")]
#[display("PBES2-HS384+A192KW")]
Pbes2Hs384A192Kw, Pbes2Hs384A192Kw,
/// PBES2 with HMAC SHA-512 and "A256KW" wrapping /// PBES2 with HMAC SHA-512 and "A256KW" wrapping
#[serde(rename = "PBES2-HS512+A256KW")] #[serde(rename = "PBES2-HS512+A256KW")]
#[display("PBES2-HS512+A256KW")]
Pbes2Hs512A256Kw, Pbes2Hs512A256Kw,
/// EdDSA signature algorithms
#[serde(rename = "EdDSA")]
EdDsa,
/// RSA-OAEP using SHA-384 and MGF1 with SHA-384 /// RSA-OAEP using SHA-384 and MGF1 with SHA-384
#[serde(rename = "RSA-OAEP-384")] #[serde(rename = "RSA-OAEP-384")]
#[display("RSA-OAEP-384")]
RsaOaep384, RsaOaep384,
/// RSA-OAEP using SHA-512 and MGF1 with SHA-512 /// RSA-OAEP using SHA-512 and MGF1 with SHA-512
#[serde(rename = "RSA-OAEP-512")] #[serde(rename = "RSA-OAEP-512")]
#[display("RSA-OAEP-512")]
RsaOaep512, RsaOaep512,
/// ECDSA using secp256k1 curve and SHA-256
#[serde(rename = "ES256K")]
Es256K,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] /// JSON Web Encryption "enc" parameter
pub enum JsonWebEncryptionAlgorithm { ///
/// Source: <https://www.iana.org/assignments/jose/web-signature-encryption-algorithms.csv>
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum JsonWebEncryptionEnc {
/// AES_128_CBC_HMAC_SHA_256 authenticated encryption algorithm /// AES_128_CBC_HMAC_SHA_256 authenticated encryption algorithm
#[serde(rename = "A128CBC-HS256")] #[serde(rename = "A128CBC-HS256")]
#[display("A128CBC-HS256")]
A128CbcHs256, A128CbcHs256,
/// AES_192_CBC_HMAC_SHA_384 authenticated encryption algorithm /// AES_192_CBC_HMAC_SHA_384 authenticated encryption algorithm
#[serde(rename = "A192CBC-HS384")] #[serde(rename = "A192CBC-HS384")]
#[display("A192CBC-HS384")]
A192CbcHs384, A192CbcHs384,
/// AES_256_CBC_HMAC_SHA_512 authenticated encryption algorithm /// AES_256_CBC_HMAC_SHA_512 authenticated encryption algorithm
#[serde(rename = "A256CBC-HS512")] #[serde(rename = "A256CBC-HS512")]
#[display("A256CBC-HS512")]
A256CbcHs512, A256CbcHs512,
/// AES GCM using 128-bit key /// AES GCM using 128-bit key
#[serde(rename = "A128GCM")] #[serde(rename = "A128GCM")]
#[display("A128GCM")]
A128Gcm, A128Gcm,
/// AES GCM using 192-bit key /// AES GCM using 192-bit key
#[serde(rename = "A192GCM")] #[serde(rename = "A192GCM")]
#[display("A192GCM")]
A192Gcm, A192Gcm,
/// AES GCM using 256-bit key /// AES GCM using 256-bit key
#[serde(rename = "A256GCM")] #[serde(rename = "A256GCM")]
#[display("A256GCM")]
A256Gcm, A256Gcm,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] /// JSON Web Encryption Compression Algorithm
///
/// Source: <https://www.iana.org/assignments/jose/web-encryption-compression-algorithms.csv>
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum JsonWebEncryptionCompressionAlgorithm { pub enum JsonWebEncryptionCompressionAlgorithm {
/// DEFLATE /// DEFLATE
#[serde(rename = "DEF")] #[serde(rename = "DEF")]
#[display("DEF")]
Def, Def,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] /// JSON Web Key Type
///
/// Source: <https://www.iana.org/assignments/jose/web-key-types.csv>
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum JsonWebKeyType { pub enum JsonWebKeyType {
/// Elliptic Curve /// Elliptic Curve
#[serde(rename = "EC")] #[serde(rename = "EC")]
#[display("EC")]
Ec, Ec,
/// RSA /// RSA
#[serde(rename = "RSA")] #[serde(rename = "RSA")]
#[display("RSA")]
Rsa, Rsa,
/// Octet sequence /// Octet sequence
#[serde(rename = "oct")] #[serde(rename = "oct")]
#[display("oct")]
Oct, Oct,
/// Octet string key pairs /// Octet string key pairs
#[serde(rename = "OKP")] #[serde(rename = "OKP")]
#[display("OKP")]
Okp, Okp,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] /// JSON Web Key EC Elliptic Curve
///
/// Source: <https://www.iana.org/assignments/jose/web-key-elliptic-curve.csv>
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum JsonWebKeyEcEllipticCurve { pub enum JsonWebKeyEcEllipticCurve {
/// P-256 Curve /// P-256 Curve
#[serde(rename = "P-256")] #[serde(rename = "P-256")]
#[display("P-256")]
P256, P256,
/// P-384 Curve /// P-384 Curve
#[serde(rename = "P-384")] #[serde(rename = "P-384")]
#[display("P-384")]
P384, P384,
/// P-521 Curve /// P-521 Curve
#[serde(rename = "P-521")] #[serde(rename = "P-521")]
#[display("P-521")]
P521, P521,
/// SECG secp256k1 curve /// SECG secp256k1 curve
#[serde(rename = "secp256k1")] #[serde(rename = "secp256k1")]
#[display("secp256k1")]
Secp256K1, Secp256K1,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] /// JSON Web Key OKP Elliptic Curve
///
/// Source: <https://www.iana.org/assignments/jose/web-key-elliptic-curve.csv>
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum JsonWebKeyOkpEllipticCurve { pub enum JsonWebKeyOkpEllipticCurve {
/// Ed25519 signature algorithm key pairs /// Ed25519 signature algorithm key pairs
#[serde(rename = "Ed25519")] #[serde(rename = "Ed25519")]
#[display("Ed25519")]
Ed25519, Ed25519,
/// Ed448 signature algorithm key pairs /// Ed448 signature algorithm key pairs
#[serde(rename = "Ed448")] #[serde(rename = "Ed448")]
#[display("Ed448")]
Ed448, Ed448,
/// X25519 function key pairs /// X25519 function key pairs
#[serde(rename = "X25519")] #[serde(rename = "X25519")]
#[display("X25519")]
X25519, X25519,
/// X448 function key pairs /// X448 function key pairs
#[serde(rename = "X448")] #[serde(rename = "X448")]
#[display("X448")]
X448, X448,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] /// JSON Web Key Use
///
/// Source: <https://www.iana.org/assignments/jose/web-key-use.csv>
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum JsonWebKeyUse { pub enum JsonWebKeyUse {
/// Digital Signature or MAC /// Digital Signature or MAC
#[serde(rename = "sig")] #[serde(rename = "sig")]
#[display("sig")]
Sig, Sig,
/// Encryption /// Encryption
#[serde(rename = "enc")] #[serde(rename = "enc")]
#[display("enc")]
Enc, Enc,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] /// JSON Web Key Operation
///
/// Source: <https://www.iana.org/assignments/jose/web-key-operations.csv>
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum JsonWebKeyOperation { pub enum JsonWebKeyOperation {
/// Compute digital signature or MAC /// Compute digital signature or MAC
#[serde(rename = "sign")] #[serde(rename = "sign")]
#[display("sign")]
Sign, Sign,
/// Verify digital signature or MAC /// Verify digital signature or MAC
#[serde(rename = "verify")] #[serde(rename = "verify")]
#[display("verify")]
Verify, Verify,
/// Encrypt content /// Encrypt content
#[serde(rename = "encrypt")] #[serde(rename = "encrypt")]
#[display("encrypt")]
Encrypt, Encrypt,
/// Decrypt content and validate decryption, if applicable /// Decrypt content and validate decryption, if applicable
#[serde(rename = "decrypt")] #[serde(rename = "decrypt")]
#[display("decrypt")]
Decrypt, Decrypt,
/// Encrypt key /// Encrypt key
#[serde(rename = "wrapKey")] #[serde(rename = "wrapKey")]
#[display("wrapKey")]
WrapKey, WrapKey,
/// Decrypt key and validate decryption, if applicable /// Decrypt key and validate decryption, if applicable
#[serde(rename = "unwrapKey")] #[serde(rename = "unwrapKey")]
#[display("unwrapKey")]
UnwrapKey, UnwrapKey,
/// Derive key /// Derive key
#[serde(rename = "deriveKey")] #[serde(rename = "deriveKey")]
#[display("deriveKey")]
DeriveKey, DeriveKey,
/// Derive bits not to be used as a key /// Derive bits not to be used as a key
#[serde(rename = "deriveBits")] #[serde(rename = "deriveBits")]
#[display("deriveBits")]
DeriveBits, DeriveBits,
} }

View File

@ -14,86 +14,121 @@
//! Enums from the "OAuth Parameters" IANA registry //! Enums from the "OAuth Parameters" IANA registry
//! See <https://www.iana.org/assignments/jose/jose.xhtml> //! See <https://www.iana.org/assignments/jose/jose.xhtml>
//!
//! Generated from:
//! - <https://www.iana.org/assignments/oauth-parameters/token-type-hint.csv>
//! - <https://www.iana.org/assignments/oauth-parameters/endpoint.csv>
//! - <https://www.iana.org/assignments/oauth-parameters/token-endpoint-auth-method.csv>
//! - <https://www.iana.org/assignments/oauth-parameters/pkce-code-challenge-method.csv>
// Do not edit this file manually // Do not edit this file manually
use parse_display::{Display, FromStr};
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] /// OAuth Token Type Hint
///
/// Source: <https://www.iana.org/assignments/oauth-parameters/token-type-hint.csv>
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum OAuthTokenTypeHint { pub enum OAuthTokenTypeHint {
#[serde(rename = "access_token")] #[serde(rename = "access_token")]
#[display("access_token")]
AccessToken, AccessToken,
#[serde(rename = "refresh_token")] #[serde(rename = "refresh_token")]
#[display("refresh_token")]
RefreshToken, RefreshToken,
#[serde(rename = "pct")] #[serde(rename = "pct")]
#[display("pct")]
Pct, Pct,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] /// OAuth Authorization Endpoint Response Type
///
/// Source: <https://www.iana.org/assignments/oauth-parameters/endpoint.csv>
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum OAuthAuthorizationEndpointResponseType { pub enum OAuthAuthorizationEndpointResponseType {
#[serde(rename = "code")] #[serde(rename = "code")]
#[display("code")]
Code, Code,
#[serde(rename = "code id_token")] #[serde(rename = "code id_token")]
#[display("code id_token")]
CodeIdToken, CodeIdToken,
#[serde(rename = "code id_token token")] #[serde(rename = "code id_token token")]
#[display("code id_token token")]
CodeIdTokenToken, CodeIdTokenToken,
#[serde(rename = "code token")] #[serde(rename = "code token")]
#[display("code token")]
CodeToken, CodeToken,
#[serde(rename = "id_token")] #[serde(rename = "id_token")]
#[display("id_token")]
IdToken, IdToken,
#[serde(rename = "id_token token")] #[serde(rename = "id_token token")]
#[display("id_token token")]
IdTokenToken, IdTokenToken,
#[serde(rename = "none")] #[serde(rename = "none")]
#[display("none")]
None, None,
#[serde(rename = "token")] #[serde(rename = "token")]
#[display("token")]
Token, Token,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] /// OAuth Token Endpoint Authentication Method
///
/// Source: <https://www.iana.org/assignments/oauth-parameters/token-endpoint-auth-method.csv>
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum OAuthTokenEndpointAuthenticationMethod { pub enum OAuthTokenEndpointAuthenticationMethod {
#[serde(rename = "none")] #[serde(rename = "none")]
#[display("none")]
None, None,
#[serde(rename = "client_secret_post")] #[serde(rename = "client_secret_post")]
#[display("client_secret_post")]
ClientSecretPost, ClientSecretPost,
#[serde(rename = "client_secret_basic")] #[serde(rename = "client_secret_basic")]
#[display("client_secret_basic")]
ClientSecretBasic, ClientSecretBasic,
#[serde(rename = "client_secret_jwt")] #[serde(rename = "client_secret_jwt")]
#[display("client_secret_jwt")]
ClientSecretJwt, ClientSecretJwt,
#[serde(rename = "private_key_jwt")] #[serde(rename = "private_key_jwt")]
#[display("private_key_jwt")]
PrivateKeyJwt, PrivateKeyJwt,
#[serde(rename = "tls_client_auth")] #[serde(rename = "tls_client_auth")]
#[display("tls_client_auth")]
TlsClientAuth, TlsClientAuth,
#[serde(rename = "self_signed_tls_client_auth")] #[serde(rename = "self_signed_tls_client_auth")]
#[display("self_signed_tls_client_auth")]
SelfSignedTlsClientAuth, SelfSignedTlsClientAuth,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] /// PKCE Code Challenge Method
///
/// Source: <https://www.iana.org/assignments/oauth-parameters/pkce-code-challenge-method.csv>
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, Display, FromStr, Serialize, Deserialize, JsonSchema,
)]
pub enum PkceCodeChallengeMethod { pub enum PkceCodeChallengeMethod {
#[serde(rename = "plain")] #[serde(rename = "plain")]
#[display("plain")]
Plain, Plain,
#[serde(rename = "S256")] #[serde(rename = "S256")]
#[display("S256")]
S256, S256,
} }

View File

@ -1,296 +0,0 @@
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Generated enums from the IANA JOSE registry
//!
//! <https://www.iana.org/assignments/jose/jose.xhtml>
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
pub enum JsonWebSignatureAlgorithm {
/// HMAC using SHA-256
#[serde(rename = "HS256")]
Hs256,
/// HMAC using SHA-384
#[serde(rename = "HS384")]
Hs384,
/// HMAC using SHA-512
#[serde(rename = "HS512")]
Hs512,
/// RSASSA-PKCS1-v1_5 using SHA-256
#[serde(rename = "RS256")]
Rs256,
/// RSASSA-PKCS1-v1_5 using SHA-384
#[serde(rename = "RS384")]
Rs384,
/// RSASSA-PKCS1-v1_5 using SHA-512
#[serde(rename = "RS512")]
Rs512,
/// ECDSA using P-256 and SHA-256
#[serde(rename = "ES256")]
Es256,
/// ECDSA using P-384 and SHA-384
#[serde(rename = "ES384")]
Es384,
/// ECDSA using P-521 and SHA-512
#[serde(rename = "ES512")]
Es512,
/// RSASSA-PSS using SHA-256 and MGF1 with SHA-256
#[serde(rename = "PS256")]
Ps256,
/// RSASSA-PSS using SHA-384 and MGF1 with SHA-384
#[serde(rename = "PS384")]
Ps384,
/// RSASSA-PSS using SHA-512 and MGF1 with SHA-512
#[serde(rename = "PS512")]
Ps512,
/// No digital signature or MAC performed
#[serde(rename = "none")]
None,
/// RSAES-PKCS1-v1_5
#[serde(rename = "RSA1_5")]
Rsa15,
/// RSAES OAEP using default parameters
#[serde(rename = "RSA-OAEP")]
RsaOaep,
/// RSAES OAEP using SHA-256 and MGF1 with SHA-256
#[serde(rename = "RSA-OAEP-256")]
RsaOaep256,
/// AES Key Wrap using 128-bit key
#[serde(rename = "A128KW")]
A128Kw,
/// AES Key Wrap using 192-bit key
#[serde(rename = "A192KW")]
A192Kw,
/// AES Key Wrap using 256-bit key
#[serde(rename = "A256KW")]
A256Kw,
/// Direct use of a shared symmetric key
#[serde(rename = "dir")]
Dir,
/// ECDH-ES using Concat KDF
#[serde(rename = "ECDH-ES")]
EcdhEs,
/// ECDH-ES using Concat KDF and "A128KW" wrapping
#[serde(rename = "ECDH-ES+A128KW")]
EcdhEsA128Kw,
/// ECDH-ES using Concat KDF and "A192KW" wrapping
#[serde(rename = "ECDH-ES+A192KW")]
EcdhEsA192Kw,
/// ECDH-ES using Concat KDF and "A256KW" wrapping
#[serde(rename = "ECDH-ES+A256KW")]
EcdhEsA256Kw,
/// Key wrapping with AES GCM using 128-bit key
#[serde(rename = "A128GCMKW")]
A128Gcmkw,
/// Key wrapping with AES GCM using 192-bit key
#[serde(rename = "A192GCMKW")]
A192Gcmkw,
/// Key wrapping with AES GCM using 256-bit key
#[serde(rename = "A256GCMKW")]
A256Gcmkw,
/// PBES2 with HMAC SHA-256 and "A128KW" wrapping
#[serde(rename = "PBES2-HS256+A128KW")]
Pbes2Hs256A128Kw,
/// PBES2 with HMAC SHA-384 and "A192KW" wrapping
#[serde(rename = "PBES2-HS384+A192KW")]
Pbes2Hs384A192Kw,
/// PBES2 with HMAC SHA-512 and "A256KW" wrapping
#[serde(rename = "PBES2-HS512+A256KW")]
Pbes2Hs512A256Kw,
/// EdDSA signature algorithms
#[serde(rename = "EdDSA")]
EdDsa,
/// RSA-OAEP using SHA-384 and MGF1 with SHA-384
#[serde(rename = "RSA-OAEP-384")]
RsaOaep384,
/// RSA-OAEP using SHA-512 and MGF1 with SHA-512
#[serde(rename = "RSA-OAEP-512")]
RsaOaep512,
/// ECDSA using secp256k1 curve and SHA-256
#[serde(rename = "ES256K")]
Es256K,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum JsonWebEncryptionAlgorithm {
/// AES_128_CBC_HMAC_SHA_256 authenticated encryption algorithm
#[serde(rename = "A128CBC-HS256")]
A128CbcHs256,
/// AES_192_CBC_HMAC_SHA_384 authenticated encryption algorithm
#[serde(rename = "A192CBC-HS384")]
A192CbcHs384,
/// AES_256_CBC_HMAC_SHA_512 authenticated encryption algorithm
#[serde(rename = "A256CBC-HS512")]
A256CbcHs512,
/// AES GCM using 128-bit key
#[serde(rename = "A128GCM")]
A128Gcm,
/// AES GCM using 192-bit key
#[serde(rename = "A192GCM")]
A192Gcm,
/// AES GCM using 256-bit key
#[serde(rename = "A256GCM")]
A256Gcm,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum JsonWebEncryptionCompressionAlgorithm {
/// DEFLATE
#[serde(rename = "DEF")]
Def,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum JsonWebKeyType {
/// Elliptic Curve
#[serde(rename = "EC")]
Ec,
/// RSA
#[serde(rename = "RSA")]
Rsa,
/// Octet sequence
#[serde(rename = "oct")]
Oct,
/// Octet string key pairs
#[serde(rename = "OKP")]
Okp,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
pub enum JsonWebKeyEcEllipticCurve {
/// P-256 Curve
#[serde(rename = "P-256")]
P256,
/// P-384 Curve
#[serde(rename = "P-384")]
P384,
/// P-521 Curve
#[serde(rename = "P-521")]
P521,
/// SECG secp256k1 curve
#[serde(rename = "secp256k1")]
Secp256K1,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
pub enum JsonWebKeyOkpEllipticCurve {
/// Ed25519 signature algorithm key pairs
#[serde(rename = "Ed25519")]
Ed25519,
/// Ed448 signature algorithm key pairs
#[serde(rename = "Ed448")]
Ed448,
/// X25519 function key pairs
#[serde(rename = "X25519")]
X25519,
/// X448 function key pairs
#[serde(rename = "X448")]
X448,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
pub enum JsonWebKeyUse {
/// Digital Signature or MAC
#[serde(rename = "sig")]
Sig,
/// Encryption
#[serde(rename = "enc")]
Enc,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
pub enum JsonWebKeyOperation {
/// Compute digital signature or MAC
#[serde(rename = "sign")]
Sign,
/// Verify digital signature or MAC
#[serde(rename = "verify")]
Verify,
/// Encrypt content
#[serde(rename = "encrypt")]
Encrypt,
/// Decrypt content and validate decryption, if applicable
#[serde(rename = "decrypt")]
Decrypt,
/// Encrypt key
#[serde(rename = "wrapKey")]
WrapKey,
/// Decrypt key and validate decryption, if applicable
#[serde(rename = "unwrapKey")]
UnwrapKey,
/// Derive key
#[serde(rename = "deriveKey")]
DeriveKey,
/// Derive bits not to be used as a key
#[serde(rename = "deriveBits")]
DeriveBits,
}

View File

@ -15,6 +15,10 @@
//! Ref: <https://www.rfc-editor.org/rfc/rfc7517.html> //! Ref: <https://www.rfc-editor.org/rfc/rfc7517.html>
use anyhow::bail; use anyhow::bail;
use mas_iana::jose::{
JsonWebKeyEcEllipticCurve, JsonWebKeyOkpEllipticCurve, JsonWebKeyOperation, JsonWebKeyType,
JsonWebKeyUse, JsonWebSignatureAlg,
};
use p256::NistP256; use p256::NistP256;
use rsa::{BigUint, PublicKeyParts}; use rsa::{BigUint, PublicKeyParts};
use schemars::JsonSchema; use schemars::JsonSchema;
@ -26,14 +30,6 @@ use serde_with::{
}; };
use url::Url; use url::Url;
use crate::{
iana::{
JsonWebKeyEcEllipticCurve, JsonWebKeyOkpEllipticCurve, JsonWebKeyOperation, JsonWebKeyUse,
JsonWebSignatureAlgorithm,
},
JsonWebKeyType,
};
#[serde_as] #[serde_as]
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
@ -48,7 +44,7 @@ pub struct JsonWebKey {
key_ops: Option<Vec<JsonWebKeyOperation>>, key_ops: Option<Vec<JsonWebKeyOperation>>,
#[serde(default)] #[serde(default)]
alg: Option<JsonWebSignatureAlgorithm>, alg: Option<JsonWebSignatureAlg>,
#[serde(default)] #[serde(default)]
kid: Option<String>, kid: Option<String>,
@ -102,7 +98,7 @@ impl JsonWebKey {
} }
#[must_use] #[must_use]
pub fn with_alg(mut self, alg: JsonWebSignatureAlgorithm) -> Self { pub fn with_alg(mut self, alg: JsonWebSignatureAlg) -> Self {
self.alg = Some(alg); self.alg = Some(alg);
self self
} }

View File

@ -15,6 +15,9 @@
use std::str::FromStr; use std::str::FromStr;
use base64ct::{Base64UrlUnpadded, Encoding}; use base64ct::{Base64UrlUnpadded, Encoding};
use mas_iana::jose::{
JsonWebEncryptionCompressionAlgorithm, JsonWebEncryptionEnc, JsonWebSignatureAlg,
};
use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_with::{ use serde_with::{
base64::{Base64, Standard, UrlSafe}, base64::{Base64, Standard, UrlSafe},
@ -23,23 +26,16 @@ use serde_with::{
}; };
use url::Url; use url::Url;
use crate::{ use crate::{jwk::JsonWebKey, SigningKeystore, VerifyingKeystore};
iana::{
JsonWebEncryptionAlgorithm, JsonWebEncryptionCompressionAlgorithm,
JsonWebSignatureAlgorithm,
},
jwk::JsonWebKey,
SigningKeystore, VerifyingKeystore,
};
#[serde_as] #[serde_as]
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct JwtHeader { pub struct JwtHeader {
alg: JsonWebSignatureAlgorithm, alg: JsonWebSignatureAlg,
#[serde(default)] #[serde(default)]
enc: Option<JsonWebEncryptionAlgorithm>, enc: Option<JsonWebEncryptionEnc>,
#[serde(default)] #[serde(default)]
jku: Option<Url>, jku: Option<Url>,
@ -85,7 +81,7 @@ impl JwtHeader {
} }
#[must_use] #[must_use]
pub fn new(alg: JsonWebSignatureAlgorithm) -> Self { pub fn new(alg: JsonWebSignatureAlg) -> Self {
Self { Self {
alg, alg,
enc: None, enc: None,
@ -104,7 +100,7 @@ impl JwtHeader {
} }
#[must_use] #[must_use]
pub fn alg(&self) -> JsonWebSignatureAlgorithm { pub fn alg(&self) -> JsonWebSignatureAlg {
self.alg self.alg
} }
@ -254,7 +250,7 @@ mod tests {
jwt.decode_and_verify(&store).await.unwrap(); jwt.decode_and_verify(&store).await.unwrap();
assert_eq!(jwt.header.typ, Some("JWT".to_string())); assert_eq!(jwt.header.typ, Some("JWT".to_string()));
assert_eq!(jwt.header.alg, JsonWebSignatureAlgorithm::Hs256); assert_eq!(jwt.header.alg, JsonWebSignatureAlg::Hs256);
assert_eq!( assert_eq!(
jwt.payload, jwt.payload,
serde_json::json!({ serde_json::json!({

View File

@ -18,15 +18,13 @@ use anyhow::bail;
use async_trait::async_trait; use async_trait::async_trait;
use chrono::{DateTime, Duration, Utc}; use chrono::{DateTime, Duration, Utc};
use digest::Digest; use digest::Digest;
use mas_iana::jose::{JsonWebKeyType, JsonWebSignatureAlg};
use rsa::{PublicKey, RsaPublicKey}; use rsa::{PublicKey, RsaPublicKey};
use sha2::{Sha256, Sha384, Sha512}; use sha2::{Sha256, Sha384, Sha512};
use signature::{Signature, Verifier}; use signature::{Signature, Verifier};
use tokio::sync::RwLock; use tokio::sync::RwLock;
use crate::{ use crate::{ExportJwks, JsonWebKeySet, JwtHeader, VerifyingKeystore};
ExportJwks, JsonWebKeySet, JsonWebKeyType, JsonWebSignatureAlgorithm, JwtHeader,
VerifyingKeystore,
};
pub struct StaticJwksStore { pub struct StaticJwksStore {
key_set: JsonWebKeySet, key_set: JsonWebKeySet,
@ -96,7 +94,7 @@ impl VerifyingKeystore for &StaticJwksStore {
.ok_or_else(|| anyhow::anyhow!("missing kid"))? .ok_or_else(|| anyhow::anyhow!("missing kid"))?
.to_string(); .to_string();
match header.alg() { match header.alg() {
JsonWebSignatureAlgorithm::Rs256 => { JsonWebSignatureAlg::Rs256 => {
let key = self.find_rsa_key(kid)?; let key = self.find_rsa_key(kid)?;
let digest = { let digest = {
@ -112,7 +110,7 @@ impl VerifyingKeystore for &StaticJwksStore {
)?; )?;
} }
JsonWebSignatureAlgorithm::Rs384 => { JsonWebSignatureAlg::Rs384 => {
let key = self.find_rsa_key(kid)?; let key = self.find_rsa_key(kid)?;
let digest = { let digest = {
@ -128,7 +126,7 @@ impl VerifyingKeystore for &StaticJwksStore {
)?; )?;
} }
JsonWebSignatureAlgorithm::Rs512 => { JsonWebSignatureAlg::Rs512 => {
let key = self.find_rsa_key(kid)?; let key = self.find_rsa_key(kid)?;
let digest = { let digest = {
@ -144,7 +142,7 @@ impl VerifyingKeystore for &StaticJwksStore {
)?; )?;
} }
JsonWebSignatureAlgorithm::Es256 => { JsonWebSignatureAlg::Es256 => {
let key = self.find_ecdsa_key(kid)?; let key = self.find_ecdsa_key(kid)?;
let signature = ecdsa::Signature::from_bytes(signature)?; let signature = ecdsa::Signature::from_bytes(signature)?;

View File

@ -17,10 +17,11 @@ use std::collections::HashSet;
use anyhow::bail; use anyhow::bail;
use async_trait::async_trait; use async_trait::async_trait;
use hmac::{Hmac, Mac}; use hmac::{Hmac, Mac};
use mas_iana::jose::JsonWebSignatureAlg;
use sha2::{Sha256, Sha384, Sha512}; use sha2::{Sha256, Sha384, Sha512};
use super::{SigningKeystore, VerifyingKeystore}; use super::{SigningKeystore, VerifyingKeystore};
use crate::{JsonWebSignatureAlgorithm, JwtHeader}; use crate::JwtHeader;
pub struct SharedSecret<'a> { pub struct SharedSecret<'a> {
inner: &'a [u8], inner: &'a [u8],
@ -36,22 +37,20 @@ impl<'a> SharedSecret<'a> {
#[async_trait] #[async_trait]
impl<'a> SigningKeystore for &SharedSecret<'a> { impl<'a> SigningKeystore for &SharedSecret<'a> {
fn supported_algorithms(self) -> HashSet<JsonWebSignatureAlgorithm> { fn supported_algorithms(self) -> HashSet<JsonWebSignatureAlg> {
let mut algorithms = HashSet::with_capacity(3); let mut algorithms = HashSet::with_capacity(3);
algorithms.insert(JsonWebSignatureAlgorithm::Hs256); algorithms.insert(JsonWebSignatureAlg::Hs256);
algorithms.insert(JsonWebSignatureAlgorithm::Hs384); algorithms.insert(JsonWebSignatureAlg::Hs384);
algorithms.insert(JsonWebSignatureAlgorithm::Hs512); algorithms.insert(JsonWebSignatureAlg::Hs512);
algorithms algorithms
} }
async fn prepare_header(self, alg: JsonWebSignatureAlgorithm) -> anyhow::Result<JwtHeader> { async fn prepare_header(self, alg: JsonWebSignatureAlg) -> anyhow::Result<JwtHeader> {
if !matches!( if !matches!(
alg, alg,
JsonWebSignatureAlgorithm::Hs256 JsonWebSignatureAlg::Hs256 | JsonWebSignatureAlg::Hs384 | JsonWebSignatureAlg::Hs512,
| JsonWebSignatureAlgorithm::Hs384
| JsonWebSignatureAlgorithm::Hs512,
) { ) {
bail!("unsupported algorithm") bail!("unsupported algorithm")
} }
@ -63,19 +62,19 @@ impl<'a> SigningKeystore for &SharedSecret<'a> {
// TODO: do the signing in a blocking task // TODO: do the signing in a blocking task
// TODO: should we bail out if the key is too small? // TODO: should we bail out if the key is too small?
let signature = match header.alg() { let signature = match header.alg() {
JsonWebSignatureAlgorithm::Hs256 => { JsonWebSignatureAlg::Hs256 => {
let mut mac = Hmac::<Sha256>::new_from_slice(self.inner)?; let mut mac = Hmac::<Sha256>::new_from_slice(self.inner)?;
mac.update(msg); mac.update(msg);
mac.finalize().into_bytes().to_vec() mac.finalize().into_bytes().to_vec()
} }
JsonWebSignatureAlgorithm::Hs384 => { JsonWebSignatureAlg::Hs384 => {
let mut mac = Hmac::<Sha384>::new_from_slice(self.inner)?; let mut mac = Hmac::<Sha384>::new_from_slice(self.inner)?;
mac.update(msg); mac.update(msg);
mac.finalize().into_bytes().to_vec() mac.finalize().into_bytes().to_vec()
} }
JsonWebSignatureAlgorithm::Hs512 => { JsonWebSignatureAlg::Hs512 => {
let mut mac = Hmac::<Sha512>::new_from_slice(self.inner)?; let mut mac = Hmac::<Sha512>::new_from_slice(self.inner)?;
mac.update(msg); mac.update(msg);
mac.finalize().into_bytes().to_vec() mac.finalize().into_bytes().to_vec()
@ -98,19 +97,19 @@ impl<'a> VerifyingKeystore for &SharedSecret<'a> {
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
// TODO: do the verification in a blocking task // TODO: do the verification in a blocking task
match header.alg() { match header.alg() {
JsonWebSignatureAlgorithm::Hs256 => { JsonWebSignatureAlg::Hs256 => {
let mut mac = Hmac::<Sha256>::new_from_slice(self.inner)?; let mut mac = Hmac::<Sha256>::new_from_slice(self.inner)?;
mac.update(payload); mac.update(payload);
mac.verify(signature.try_into()?)?; mac.verify(signature.try_into()?)?;
} }
JsonWebSignatureAlgorithm::Hs384 => { JsonWebSignatureAlg::Hs384 => {
let mut mac = Hmac::<Sha384>::new_from_slice(self.inner)?; let mut mac = Hmac::<Sha384>::new_from_slice(self.inner)?;
mac.update(payload); mac.update(payload);
mac.verify(signature.try_into()?)?; mac.verify(signature.try_into()?)?;
} }
JsonWebSignatureAlgorithm::Hs512 => { JsonWebSignatureAlg::Hs512 => {
let mut mac = Hmac::<Sha512>::new_from_slice(self.inner)?; let mut mac = Hmac::<Sha512>::new_from_slice(self.inner)?;
mac.update(payload); mac.update(payload);
mac.verify(signature.try_into()?)?; mac.verify(signature.try_into()?)?;
@ -133,9 +132,9 @@ mod tests {
let message = "this is the message to sign".as_bytes(); let message = "this is the message to sign".as_bytes();
let store = SharedSecret::new(&secret); let store = SharedSecret::new(&secret);
for alg in [ for alg in [
JsonWebSignatureAlgorithm::Hs256, JsonWebSignatureAlg::Hs256,
JsonWebSignatureAlgorithm::Hs384, JsonWebSignatureAlg::Hs384,
JsonWebSignatureAlgorithm::Hs512, JsonWebSignatureAlg::Hs512,
] { ] {
let header = store.prepare_header(alg).await.unwrap(); let header = store.prepare_header(alg).await.unwrap();
assert_eq!(header.alg(), alg); assert_eq!(header.alg(), alg);

View File

@ -19,6 +19,7 @@ use async_trait::async_trait;
use base64ct::{Base64UrlUnpadded, Encoding}; use base64ct::{Base64UrlUnpadded, Encoding};
use digest::Digest; use digest::Digest;
use ecdsa::{SigningKey, VerifyingKey}; use ecdsa::{SigningKey, VerifyingKey};
use mas_iana::jose::{JsonWebKeyUse, JsonWebSignatureAlg};
use p256::{NistP256, PublicKey}; use p256::{NistP256, PublicKey};
use pkcs1::{DecodeRsaPrivateKey, EncodeRsaPublicKey}; use pkcs1::{DecodeRsaPrivateKey, EncodeRsaPublicKey};
use pkcs8::{DecodePrivateKey, EncodePublicKey}; use pkcs8::{DecodePrivateKey, EncodePublicKey};
@ -27,7 +28,7 @@ use sha2::{Sha256, Sha384, Sha512};
use signature::{Signature, Signer, Verifier}; use signature::{Signature, Signer, Verifier};
use super::{ExportJwks, SigningKeystore, VerifyingKeystore}; use super::{ExportJwks, SigningKeystore, VerifyingKeystore};
use crate::{iana::JsonWebSignatureAlgorithm, JsonWebKey, JsonWebKeySet, JwtHeader}; use crate::{JsonWebKey, JsonWebKeySet, JwtHeader};
// Generate with // Generate with
// openssl genrsa 2048 // openssl genrsa 2048
@ -126,7 +127,7 @@ impl StaticKeystore {
#[async_trait] #[async_trait]
impl SigningKeystore for &StaticKeystore { impl SigningKeystore for &StaticKeystore {
fn supported_algorithms(self) -> HashSet<JsonWebSignatureAlgorithm> { fn supported_algorithms(self) -> HashSet<JsonWebSignatureAlg> {
let has_rsa = !self.rsa_keys.is_empty(); let has_rsa = !self.rsa_keys.is_empty();
let has_es256 = !self.es256_keys.is_empty(); let has_es256 = !self.es256_keys.is_empty();
@ -134,30 +135,30 @@ impl SigningKeystore for &StaticKeystore {
let mut algorithms = HashSet::with_capacity(capacity); let mut algorithms = HashSet::with_capacity(capacity);
if has_rsa { if has_rsa {
algorithms.insert(JsonWebSignatureAlgorithm::Rs256); algorithms.insert(JsonWebSignatureAlg::Rs256);
algorithms.insert(JsonWebSignatureAlgorithm::Rs384); algorithms.insert(JsonWebSignatureAlg::Rs384);
algorithms.insert(JsonWebSignatureAlgorithm::Rs512); algorithms.insert(JsonWebSignatureAlg::Rs512);
} }
if has_es256 { if has_es256 {
algorithms.insert(JsonWebSignatureAlgorithm::Es256); algorithms.insert(JsonWebSignatureAlg::Es256);
} }
algorithms algorithms
} }
async fn prepare_header(self, alg: JsonWebSignatureAlgorithm) -> anyhow::Result<JwtHeader> { async fn prepare_header(self, alg: JsonWebSignatureAlg) -> anyhow::Result<JwtHeader> {
let header = JwtHeader::new(alg); let header = JwtHeader::new(alg);
let kid = match alg { let kid = match alg {
JsonWebSignatureAlgorithm::Rs256 JsonWebSignatureAlg::Rs256
| JsonWebSignatureAlgorithm::Rs384 | JsonWebSignatureAlg::Rs384
| JsonWebSignatureAlgorithm::Rs512 => self | JsonWebSignatureAlg::Rs512 => self
.rsa_keys .rsa_keys
.keys() .keys()
.next() .next()
.ok_or_else(|| anyhow::anyhow!("no RSA keys in keystore"))?, .ok_or_else(|| anyhow::anyhow!("no RSA keys in keystore"))?,
JsonWebSignatureAlgorithm::Es256 => self JsonWebSignatureAlg::Es256 => self
.es256_keys .es256_keys
.keys() .keys()
.next() .next()
@ -175,7 +176,7 @@ impl SigningKeystore for &StaticKeystore {
// TODO: do the signing in a blocking task // TODO: do the signing in a blocking task
let signature = match header.alg() { let signature = match header.alg() {
JsonWebSignatureAlgorithm::Rs256 => { JsonWebSignatureAlg::Rs256 => {
let key = self let key = self
.rsa_keys .rsa_keys
.get(kid) .get(kid)
@ -193,7 +194,7 @@ impl SigningKeystore for &StaticKeystore {
)? )?
} }
JsonWebSignatureAlgorithm::Rs384 => { JsonWebSignatureAlg::Rs384 => {
let key = self let key = self
.rsa_keys .rsa_keys
.get(kid) .get(kid)
@ -211,7 +212,7 @@ impl SigningKeystore for &StaticKeystore {
)? )?
} }
JsonWebSignatureAlgorithm::Rs512 => { JsonWebSignatureAlg::Rs512 => {
let key = self let key = self
.rsa_keys .rsa_keys
.get(kid) .get(kid)
@ -229,7 +230,7 @@ impl SigningKeystore for &StaticKeystore {
)? )?
} }
JsonWebSignatureAlgorithm::Es256 => { JsonWebSignatureAlg::Es256 => {
let key = self let key = self
.es256_keys .es256_keys
.get(kid) .get(kid)
@ -261,7 +262,7 @@ impl VerifyingKeystore for &StaticKeystore {
// TODO: do the verification in a blocking task // TODO: do the verification in a blocking task
match header.alg() { match header.alg() {
JsonWebSignatureAlgorithm::Rs256 => { JsonWebSignatureAlg::Rs256 => {
let key = self let key = self
.rsa_keys .rsa_keys
.get(kid) .get(kid)
@ -282,7 +283,7 @@ impl VerifyingKeystore for &StaticKeystore {
)?; )?;
} }
JsonWebSignatureAlgorithm::Rs384 => { JsonWebSignatureAlg::Rs384 => {
let key = self let key = self
.rsa_keys .rsa_keys
.get(kid) .get(kid)
@ -303,7 +304,7 @@ impl VerifyingKeystore for &StaticKeystore {
)?; )?;
} }
JsonWebSignatureAlgorithm::Rs512 => { JsonWebSignatureAlg::Rs512 => {
let key = self let key = self
.rsa_keys .rsa_keys
.get(kid) .get(kid)
@ -324,7 +325,7 @@ impl VerifyingKeystore for &StaticKeystore {
)?; )?;
} }
JsonWebSignatureAlgorithm::Es256 => { JsonWebSignatureAlg::Es256 => {
let key = self let key = self
.es256_keys .es256_keys
.get(kid) .get(kid)
@ -349,15 +350,15 @@ impl ExportJwks for StaticKeystore {
let pubkey = RsaPublicKey::from(key); let pubkey = RsaPublicKey::from(key);
JsonWebKey::new(pubkey.into()) JsonWebKey::new(pubkey.into())
.with_kid(kid) .with_kid(kid)
.with_use(crate::JsonWebKeyUse::Sig) .with_use(JsonWebKeyUse::Sig)
}); });
let es256 = self.es256_keys.iter().map(|(kid, key)| { let es256 = self.es256_keys.iter().map(|(kid, key)| {
let pubkey = ecdsa::VerifyingKey::from(key); let pubkey = ecdsa::VerifyingKey::from(key);
JsonWebKey::new(pubkey.into()) JsonWebKey::new(pubkey.into())
.with_kid(kid) .with_kid(kid)
.with_use(crate::JsonWebKeyUse::Sig) .with_use(JsonWebKeyUse::Sig)
.with_alg(JsonWebSignatureAlgorithm::Es256) .with_alg(JsonWebSignatureAlg::Es256)
}); });
let keys = rsa.chain(es256).collect(); let keys = rsa.chain(es256).collect();
@ -380,10 +381,10 @@ mod tests {
}; };
for alg in [ for alg in [
JsonWebSignatureAlgorithm::Rs256, JsonWebSignatureAlg::Rs256,
JsonWebSignatureAlgorithm::Rs384, JsonWebSignatureAlg::Rs384,
JsonWebSignatureAlgorithm::Rs512, JsonWebSignatureAlg::Rs512,
JsonWebSignatureAlgorithm::Es256, JsonWebSignatureAlg::Es256,
] { ] {
let header = store.prepare_header(alg).await.unwrap(); let header = store.prepare_header(alg).await.unwrap();
assert_eq!(header.alg(), alg); assert_eq!(header.alg(), alg);

View File

@ -15,14 +15,15 @@
use std::collections::HashSet; use std::collections::HashSet;
use async_trait::async_trait; use async_trait::async_trait;
use mas_iana::jose::JsonWebSignatureAlg;
use crate::{iana::JsonWebSignatureAlgorithm, JsonWebKeySet, JwtHeader}; use crate::{JsonWebKeySet, JwtHeader};
#[async_trait] #[async_trait]
pub trait SigningKeystore { pub trait SigningKeystore {
fn supported_algorithms(self) -> HashSet<JsonWebSignatureAlgorithm>; fn supported_algorithms(self) -> HashSet<JsonWebSignatureAlg>;
async fn prepare_header(self, alg: JsonWebSignatureAlgorithm) -> anyhow::Result<JwtHeader>; async fn prepare_header(self, alg: JsonWebSignatureAlg) -> anyhow::Result<JwtHeader>;
async fn sign(self, header: &JwtHeader, msg: &[u8]) -> anyhow::Result<Vec<u8>>; async fn sign(self, header: &JwtHeader, msg: &[u8]) -> anyhow::Result<Vec<u8>>;
} }

View File

@ -19,18 +19,12 @@
#![allow(clippy::missing_errors_doc)] #![allow(clippy::missing_errors_doc)]
#![allow(clippy::module_name_repetitions)] #![allow(clippy::module_name_repetitions)]
pub(crate) use mas_iana::jose as iana;
pub mod claims; pub mod claims;
pub(crate) mod jwk; pub(crate) mod jwk;
pub(crate) mod jwt; pub(crate) mod jwt;
mod keystore; mod keystore;
pub use self::{ pub use self::{
iana::{
JsonWebEncryptionAlgorithm, JsonWebEncryptionCompressionAlgorithm, JsonWebKeyOperation,
JsonWebKeyType, JsonWebKeyUse, JsonWebSignatureAlgorithm,
},
jwk::{JsonWebKey, JsonWebKeySet}, jwk::{JsonWebKey, JsonWebKeySet},
jwt::{DecodedJsonWebToken, JsonWebTokenParts, JwtHeader}, jwt::{DecodedJsonWebToken, JsonWebTokenParts, JwtHeader},
keystore::{ keystore::{

View File

@ -14,7 +14,7 @@
use std::collections::HashSet; use std::collections::HashSet;
use mas_iana::jose::{JsonWebEncryptionAlgorithm, JsonWebSignatureAlgorithm}; use mas_iana::jose::{JsonWebEncryptionAlg, JsonWebEncryptionEnc, JsonWebSignatureAlg};
use serde::Serialize; use serde::Serialize;
use serde_with::skip_serializing_none; use serde_with::skip_serializing_none;
use url::Url; use url::Url;
@ -83,8 +83,7 @@ pub struct Metadata {
/// JSON array containing a list of the JWS signing algorithms supported by /// JSON array containing a list of the JWS signing algorithms supported by
/// the token endpoint for the signature on the JWT used to authenticate the /// the token endpoint for the signature on the JWT used to authenticate the
/// client at the token endpoint. /// client at the token endpoint.
pub token_endpoint_auth_signing_alg_values_supported: pub token_endpoint_auth_signing_alg_values_supported: Option<HashSet<JsonWebSignatureAlg>>,
Option<HashSet<JsonWebSignatureAlgorithm>>,
/// URL of a page containing human-readable information that developers /// URL of a page containing human-readable information that developers
/// might want or need to know when using the authorization server. /// might want or need to know when using the authorization server.
@ -115,8 +114,7 @@ pub struct Metadata {
/// JSON array containing a list of the JWS signing algorithms supported by /// JSON array containing a list of the JWS signing algorithms supported by
/// the revocation endpoint for the signature on the JWT used to /// the revocation endpoint for the signature on the JWT used to
/// authenticate the client at the revocation endpoint. /// authenticate the client at the revocation endpoint.
pub revocation_endpoint_auth_signing_alg_values_supported: pub revocation_endpoint_auth_signing_alg_values_supported: Option<HashSet<JsonWebSignatureAlg>>,
Option<HashSet<JsonWebSignatureAlgorithm>>,
/// URL of the authorization server's OAuth 2.0 introspection endpoint. /// URL of the authorization server's OAuth 2.0 introspection endpoint.
pub introspection_endpoint: Option<Url>, pub introspection_endpoint: Option<Url>,
@ -129,7 +127,7 @@ pub struct Metadata {
/// the introspection endpoint for the signature on the JWT used to /// the introspection endpoint for the signature on the JWT used to
/// authenticate the client at the introspection endpoint. /// authenticate the client at the introspection endpoint.
pub introspection_endpoint_auth_signing_alg_values_supported: pub introspection_endpoint_auth_signing_alg_values_supported:
Option<HashSet<JsonWebSignatureAlgorithm>>, Option<HashSet<JsonWebSignatureAlg>>,
/// PKCE code challenge methods supported by this authorization server. /// PKCE code challenge methods supported by this authorization server.
pub code_challenge_methods_supported: Option<HashSet<CodeChallengeMethod>>, pub code_challenge_methods_supported: Option<HashSet<CodeChallengeMethod>>,
@ -147,39 +145,39 @@ pub struct Metadata {
/// JSON array containing a list of the JWS "alg" values supported by the OP /// JSON array containing a list of the JWS "alg" values supported by the OP
/// for the ID Token. /// for the ID Token.
pub id_token_signing_alg_values_supported: Option<HashSet<JsonWebSignatureAlgorithm>>, pub id_token_signing_alg_values_supported: Option<HashSet<JsonWebSignatureAlg>>,
/// JSON array containing a list of the JWE "alg" values supported by the OP /// JSON array containing a list of the JWE "alg" values supported by the OP
/// for the ID Token. /// for the ID Token.
pub id_token_encryption_alg_values_supported: Option<HashSet<JsonWebSignatureAlgorithm>>, pub id_token_encryption_alg_values_supported: Option<HashSet<JsonWebEncryptionAlg>>,
/// JSON array containing a list of the JWE "enc" values supported by the OP /// JSON array containing a list of the JWE "enc" values supported by the OP
/// for the ID Token. /// for the ID Token.
pub id_token_encryption_enc_values_supported: Option<HashSet<JsonWebEncryptionAlgorithm>>, pub id_token_encryption_enc_values_supported: Option<HashSet<JsonWebEncryptionEnc>>,
/// JSON array containing a list of the JWS "alg" values supported by the /// JSON array containing a list of the JWS "alg" values supported by the
/// UserInfo Endpoint. /// UserInfo Endpoint.
pub userinfo_signing_alg_values_supported: Option<HashSet<JsonWebSignatureAlgorithm>>, pub userinfo_signing_alg_values_supported: Option<HashSet<JsonWebSignatureAlg>>,
/// JSON array containing a list of the JWE "alg" values supported by the /// JSON array containing a list of the JWE "alg" values supported by the
/// UserInfo Endpoint. /// UserInfo Endpoint.
pub userinfo_encryption_alg_values_supported: Option<HashSet<JsonWebSignatureAlgorithm>>, pub userinfo_encryption_alg_values_supported: Option<HashSet<JsonWebEncryptionAlg>>,
/// JSON array containing a list of the JWE "enc" values supported by the /// JSON array containing a list of the JWE "enc" values supported by the
/// UserInfo Endpoint. /// UserInfo Endpoint.
pub userinfo_encryption_enc_values_supported: Option<HashSet<JsonWebEncryptionAlgorithm>>, pub userinfo_encryption_enc_values_supported: Option<HashSet<JsonWebEncryptionEnc>>,
/// JSON array containing a list of the JWS "alg" values supported by the OP /// JSON array containing a list of the JWS "alg" values supported by the OP
/// for Request Objects. /// for Request Objects.
pub request_object_signing_alg_values_supported: Option<HashSet<JsonWebSignatureAlgorithm>>, pub request_object_signing_alg_values_supported: Option<HashSet<JsonWebSignatureAlg>>,
/// JSON array containing a list of the JWE "alg" values supported by the OP /// JSON array containing a list of the JWE "alg" values supported by the OP
/// for Request Objects. /// for Request Objects.
pub request_object_encryption_alg_values_supported: Option<HashSet<JsonWebSignatureAlgorithm>>, pub request_object_encryption_alg_values_supported: Option<HashSet<JsonWebEncryptionAlg>>,
/// JSON array containing a list of the JWE "enc" values supported by the OP /// JSON array containing a list of the JWE "enc" values supported by the OP
/// for Request Objects. /// for Request Objects.
pub request_object_encryption_enc_values_supported: Option<HashSet<JsonWebEncryptionAlgorithm>>, pub request_object_encryption_enc_values_supported: Option<HashSet<JsonWebEncryptionEnc>>,
/// JSON array containing a list of the "display" parameter values that the /// JSON array containing a list of the "display" parameter values that the
/// OpenID Provider supports. /// OpenID Provider supports.

View File

@ -33,16 +33,14 @@ use sha2::{Digest, Sha256};
Serialize, Serialize,
Deserialize, Deserialize,
)] )]
#[cfg_attr(feature = "sqlx_type", derive(sqlx::Type))]
#[repr(i8)]
pub enum CodeChallengeMethod { pub enum CodeChallengeMethod {
#[serde(rename = "plain")] #[serde(rename = "plain")]
#[display("plain")] #[display("plain")]
Plain = 0, Plain,
#[serde(rename = "S256")] #[serde(rename = "S256")]
#[display("S256")] #[display("S256")]
S256 = 1, S256,
} }
impl CodeChallengeMethod { impl CodeChallengeMethod {

View File

@ -290,7 +290,7 @@ struct ClientAuthForm<T> {
mod tests { mod tests {
use headers::authorization::Credentials; use headers::authorization::Credentials;
use mas_config::{ConfigurationSection, OAuth2ClientAuthMethodConfig}; use mas_config::{ConfigurationSection, OAuth2ClientAuthMethodConfig};
use mas_jose::{ExportJwks, JsonWebSignatureAlgorithm, SigningKeystore, StaticKeystore}; use mas_jose::{ExportJwks, SigningKeystore, StaticKeystore};
use serde_json::json; use serde_json::json;
use super::*; use super::*;
@ -364,17 +364,17 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn client_secret_jwt_hs256() { async fn client_secret_jwt_hs256() {
client_secret_jwt(JsonWebSignatureAlgorithm::Hs256).await; client_secret_jwt("HS256").await;
} }
#[tokio::test] #[tokio::test]
async fn client_secret_jwt_hs384() { async fn client_secret_jwt_hs384() {
client_secret_jwt(JsonWebSignatureAlgorithm::Hs384).await; client_secret_jwt("HS384").await;
} }
#[tokio::test] #[tokio::test]
async fn client_secret_jwt_hs512() { async fn client_secret_jwt_hs512() {
client_secret_jwt(JsonWebSignatureAlgorithm::Hs512).await; client_secret_jwt("HS512").await;
} }
fn client_claims( fn client_claims(
@ -395,7 +395,8 @@ mod tests {
claims claims
} }
async fn client_secret_jwt(alg: JsonWebSignatureAlgorithm) { async fn client_secret_jwt(alg: &str) {
let alg = alg.parse().unwrap();
let audience = "https://example.com/token"; let audience = "https://example.com/token";
let filter = client_authentication::<Form>(&oauth2_config().await, audience.to_string()); let filter = client_authentication::<Form>(&oauth2_config().await, audience.to_string());
@ -463,25 +464,26 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn client_secret_jwt_rs256() { async fn client_secret_jwt_rs256() {
private_key_jwt(JsonWebSignatureAlgorithm::Rs256).await; private_key_jwt("RS256").await;
} }
#[tokio::test] #[tokio::test]
async fn client_secret_jwt_rs384() { async fn client_secret_jwt_rs384() {
private_key_jwt(JsonWebSignatureAlgorithm::Rs384).await; private_key_jwt("RS384").await;
} }
#[tokio::test] #[tokio::test]
async fn client_secret_jwt_rs512() { async fn client_secret_jwt_rs512() {
private_key_jwt(JsonWebSignatureAlgorithm::Rs512).await; private_key_jwt("RS512").await;
} }
#[tokio::test] #[tokio::test]
async fn client_secret_jwt_es256() { async fn client_secret_jwt_es256() {
private_key_jwt(JsonWebSignatureAlgorithm::Es256).await; private_key_jwt("ES256").await;
} }
async fn private_key_jwt(alg: JsonWebSignatureAlgorithm) { async fn private_key_jwt(alg: &str) {
let alg = alg.parse().unwrap();
let audience = "https://example.com/token"; let audience = "https://example.com/token";
let filter = client_authentication::<Form>(&oauth2_config().await, audience.to_string()); let filter = client_authentication::<Form>(&oauth2_config().await, audience.to_string());