1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-31 09:24:31 +03:00

Codegen enums from IANA registries

This commit is contained in:
Quentin Gliech
2022-01-11 18:46:01 +01:00
parent 97ab75fb15
commit 0e70af0a75
13 changed files with 1159 additions and 2 deletions

View File

@ -233,7 +233,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --offline
args: --offline --workspace
coverage:
@ -284,7 +284,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --all-features --no-fail-fast
args: --all-features --no-fail-fast --workspace
env:
CARGO_INCREMENTAL: '0'
RUSTFLAGS: '-Zinstrument-coverage'

55
Cargo.lock generated
View File

@ -304,7 +304,10 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
dependencies = [
"lazy_static",
"memchr",
"regex-automata",
"serde",
]
[[package]]
@ -478,6 +481,12 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
[[package]]
name = "convert_case"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
[[package]]
name = "cookie"
version = "0.16.0"
@ -617,6 +626,28 @@ dependencies = [
"subtle",
]
[[package]]
name = "csv"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
dependencies = [
"bstr",
"csv-core",
"itoa 0.4.8",
"ryu",
"serde",
]
[[package]]
name = "csv-core"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
dependencies = [
"memchr",
]
[[package]]
name = "darling"
version = "0.13.1"
@ -1563,6 +1594,30 @@ dependencies = [
"warp",
]
[[package]]
name = "mas-iana"
version = "0.1.0"
dependencies = [
"schemars",
"serde",
]
[[package]]
name = "mas-iana-codegen"
version = "0.1.0"
dependencies = [
"anyhow",
"async-trait",
"convert_case",
"csv",
"futures-util",
"reqwest",
"serde",
"tokio",
"tracing",
"tracing-subscriber",
]
[[package]]
name = "mas-jose"
version = "0.1.0"

View File

@ -1,3 +1,4 @@
[workspace]
default-members = ["crates/cli"]
members = ["crates/*"]

View File

@ -120,6 +120,7 @@ COPY . .
COPY --from=static-files /app/crates/static-files/public /app/crates/static-files/public
ENV SQLX_OFFLINE=true
RUN cargo test \
--workspace \
--target $(/docker-arch-to-rust-target.sh "${TARGETPLATFORM}")
## Runtime stage, debug variant ##

View File

@ -0,0 +1,18 @@
[package]
name = "mas-iana-codegen"
version = "0.1.0"
authors = ["Quentin Gliech <quenting@element.io>"]
edition = "2021"
license = "Apache-2.0"
[dependencies]
anyhow = "1.0.51"
async-trait = "0.1.52"
convert_case = "0.4"
csv = "1.1"
futures-util = "0.3.19"
reqwest = { version = "0.11", features = ["blocking", "rustls-tls"], default-features = false }
serde = { version = "1", features = ["derive"] }
tokio = { version = "1.15.0", features = ["full"] }
tracing = "0.1.29"
tracing-subscriber = "0.3.5"

View File

@ -0,0 +1,241 @@
// 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.
use serde::Deserialize;
use crate::EnumEntry;
#[derive(Debug, Deserialize, PartialEq, Eq)]
enum Usage {
#[serde(rename = "alg")]
Alg,
#[serde(rename = "enc")]
Enc,
#[serde(rename = "JWK")]
Jwk,
}
#[derive(Debug, Deserialize)]
enum Requirements {
Required,
#[serde(rename = "Recommended+")]
RecommendedPlus,
Recommended,
#[serde(rename = "Recommended-")]
RecommendedMinus,
Optional,
Prohibited,
}
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct WebEncryptionSignatureAlgorithm {
#[serde(rename = "Algorithm Name")]
name: String,
#[serde(rename = "Algorithm Description")]
description: String,
#[serde(rename = "Algorithm Usage Location(s)")]
usage: Usage,
#[serde(rename = "JOSE Implementation Requirements")]
requirements: Requirements,
#[serde(rename = "Change Controller")]
change_controller: String,
#[serde(rename = "Reference")]
reference: String,
#[serde(rename = "Algorithm Analysis Document(s)")]
analysis: String,
}
impl EnumEntry for WebEncryptionSignatureAlgorithm {
const URL: &'static str =
"https://www.iana.org/assignments/jose/web-signature-encryption-algorithms.csv";
const SECTIONS: &'static [&'static str] =
&["JsonWebSignatureAlgorithm", "JsonWebEncryptionAlgorithm"];
fn key(&self) -> Option<&'static str> {
match self.usage {
Usage::Alg => Some("JsonWebSignatureAlgorithm"),
Usage::Enc => Some("JsonWebEncryptionAlgorithm"),
_ => None,
}
}
fn name(&self) -> &str {
&self.name
}
fn description(&self) -> Option<&str> {
Some(&self.description)
}
}
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct WebEncryptionCompressionAlgorithm {
#[serde(rename = "Compression Algorithm Value")]
value: String,
#[serde(rename = "Compression Algorithm Description")]
description: String,
#[serde(rename = "Change Controller")]
change_controller: String,
#[serde(rename = "Reference")]
reference: String,
}
impl EnumEntry for WebEncryptionCompressionAlgorithm {
const URL: &'static str =
"https://www.iana.org/assignments/jose/web-encryption-compression-algorithms.csv";
const SECTIONS: &'static [&'static str] = &["JsonWebEncryptionCompressionAlgorithm"];
fn key(&self) -> Option<&'static str> {
Some("JsonWebEncryptionCompressionAlgorithm")
}
fn name(&self) -> &str {
&self.value
}
fn description(&self) -> Option<&str> {
Some(&self.description)
}
}
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct WebKeyType {
#[serde(rename = "\"kty\" Parameter Value")]
value: String,
#[serde(rename = "Key Type Description")]
description: String,
#[serde(rename = "JOSE Implementation Requirements")]
requirements: Requirements,
#[serde(rename = "Change Controller")]
change_controller: String,
#[serde(rename = "Reference")]
reference: String,
}
impl EnumEntry for WebKeyType {
const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-types.csv";
const SECTIONS: &'static [&'static str] = &["JsonWebKeyType"];
fn key(&self) -> Option<&'static str> {
Some("JsonWebKeyType")
}
fn name(&self) -> &str {
&self.value
}
fn description(&self) -> Option<&str> {
Some(&self.description)
}
}
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct WebKeyEllipticCurve {
#[serde(rename = "Curve Name")]
name: String,
#[serde(rename = "Curve Description")]
description: String,
#[serde(rename = "JOSE Implementation Requirements")]
requirements: Requirements,
#[serde(rename = "Change Controller")]
change_controller: String,
#[serde(rename = "Reference")]
reference: String,
}
impl EnumEntry for WebKeyEllipticCurve {
const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-elliptic-curve.csv";
const SECTIONS: &'static [&'static str] =
&["JsonWebKeyEcEllipticCurve", "JsonWebKeyOkpEllipticCurve"];
fn key(&self) -> Option<&'static str> {
if self.name.starts_with("P-") || self.name == "secp256k1" {
Some("JsonWebKeyEcEllipticCurve")
} else {
Some("JsonWebKeyOkpEllipticCurve")
}
}
fn name(&self) -> &str {
&self.name
}
fn description(&self) -> Option<&str> {
Some(&self.description)
}
}
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct WebKeyUse {
#[serde(rename = "Use Member Value")]
value: String,
#[serde(rename = "Use Description")]
description: String,
#[serde(rename = "Change Controller")]
change_controller: String,
#[serde(rename = "Reference")]
reference: String,
}
impl EnumEntry for WebKeyUse {
const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-use.csv";
const SECTIONS: &'static [&'static str] = &["JsonWebKeyUse"];
fn key(&self) -> Option<&'static str> {
Some("JsonWebKeyUse")
}
fn name(&self) -> &str {
&self.value
}
fn description(&self) -> Option<&str> {
Some(&self.description)
}
}
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct WebKeyOperation {
#[serde(rename = "Key Operation Value")]
name: String,
#[serde(rename = "Key Operation Description")]
description: String,
#[serde(rename = "Change Controller")]
change_controller: String,
#[serde(rename = "Reference")]
reference: String,
}
impl EnumEntry for WebKeyOperation {
const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-operations.csv";
const SECTIONS: &'static [&'static str] = &["JsonWebKeyOperation"];
fn key(&self) -> Option<&'static str> {
Some("JsonWebKeyOperation")
}
fn name(&self) -> &str {
&self.name
}
fn description(&self) -> Option<&str> {
Some(&self.description)
}
}

View File

@ -0,0 +1,219 @@
// 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.
use std::{collections::HashMap, fmt::Display, path::PathBuf, sync::Arc};
use reqwest::Client;
use tokio::io::AsyncWriteExt;
use tracing::Level;
pub mod jose;
pub mod oauth;
pub mod traits;
#[derive(Debug)]
struct File {
client: Arc<Client>,
registry_name: &'static str,
registry_url: &'static str,
sections: Vec<&'static str>,
sources: Vec<&'static str>,
items: HashMap<&'static str, Vec<EnumMember>>,
}
fn resolve_path(relative: PathBuf) -> PathBuf {
let crate_root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let workspace_root = crate_root.parent().unwrap().parent().unwrap();
workspace_root.join(relative)
}
impl File {
#[tracing::instrument(skip(client))]
fn new(registry_name: &'static str, registry_url: &'static str, client: Arc<Client>) -> Self {
tracing::info!("Generating file from IANA registry");
Self {
client,
registry_name,
registry_url,
sources: Vec::new(),
sections: Vec::new(),
items: HashMap::new(),
}
}
#[tracing::instrument(skip_all, fields(url))]
async fn load<T: EnumEntry>(mut self) -> anyhow::Result<Self> {
tracing::Span::current().record("url", &T::URL);
self.sections.extend_from_slice(T::SECTIONS);
self.sources.push(T::URL);
for (key, value) in T::fetch(&self.client).await? {
self.items.entry(key).or_default().push(value);
}
Ok(self)
}
#[tracing::instrument(skip_all)]
async fn write(&self, path: PathBuf) -> anyhow::Result<()> {
let mut file = tokio::fs::OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(path)
.await?;
tracing::info!("Writing file");
file.write_all(format!("{}", self).as_bytes()).await?;
Ok(())
}
}
impl Display for File {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(
f,
r#"// 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.
//! Enums from the {:?} IANA registry
//! See <{}>
//!
//! Generated from:"#,
self.registry_name, self.registry_url,
)?;
for source in &self.sources {
writeln!(f, "//! - <{}>", source)?;
}
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
} else {
continue;
};
writeln!(
f,
"#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]"
)?;
write!(f, "pub enum {} {{", key)?;
for member in list {
writeln!(f)?;
if let Some(description) = &member.description {
writeln!(f, " /// {}", description)?;
}
writeln!(f, " #[serde(rename = \"{}\")]", member.value)?;
writeln!(f, " {},", member.enum_name)?;
}
writeln!(f, "}}")?;
writeln!(f)?;
}
Ok(())
}
}
use self::{jose::*, oauth::*, traits::*};
#[tracing::instrument(skip(client))]
async fn generate_jose(client: &Arc<Client>, path: PathBuf) -> anyhow::Result<()> {
let path = resolve_path(path);
let client = client.clone();
let file = File::new(
"JSON Object Signing and Encryption",
"https://www.iana.org/assignments/jose/jose.xhtml",
client.clone(),
)
.load::<WebEncryptionSignatureAlgorithm>()
.await?
.load::<WebEncryptionCompressionAlgorithm>()
.await?
.load::<WebKeyType>()
.await?
.load::<WebKeyEllipticCurve>()
.await?
.load::<WebKeyUse>()
.await?
.load::<WebKeyOperation>()
.await?;
file.write(path).await?;
Ok(())
}
#[tracing::instrument(skip(client))]
async fn generate_oauth(client: &Arc<Client>, path: PathBuf) -> anyhow::Result<()> {
let path = resolve_path(path);
let client = client.clone();
let file = File::new(
"OAuth Parameters",
"https://www.iana.org/assignments/jose/jose.xhtml",
client.clone(),
)
.load::<TokenTypeHint>()
.await?
.load::<AuthorizationEndpointResponseType>()
.await?
.load::<TokenEndpointAuthenticationMethod>()
.await?
.load::<PkceCodeChallengeMethod>()
.await?;
file.write(path).await?;
Ok(())
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt()
.with_max_level(Level::INFO)
.pretty()
.init();
let client = Client::builder().user_agent("iana-parser/0.0.1").build()?;
let client = Arc::new(client);
let iana_crate_root = PathBuf::from("crates/iana/");
generate_jose(&client, iana_crate_root.join("src/jose.rs")).await?;
generate_oauth(&client, iana_crate_root.join("src/oauth.rs")).await?;
Ok(())
}

View File

@ -0,0 +1,116 @@
// 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.
use serde::Deserialize;
use crate::EnumEntry;
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct TokenTypeHint {
#[serde(rename = "Hint Value")]
name: String,
#[serde(rename = "Change Controller")]
change_controller: String,
#[serde(rename = "Reference")]
reference: String,
}
impl EnumEntry for TokenTypeHint {
const URL: &'static str =
"https://www.iana.org/assignments/oauth-parameters/token-type-hint.csv";
const SECTIONS: &'static [&'static str] = &["OAuthTokenTypeHint"];
fn key(&self) -> Option<&'static str> {
Some("OAuthTokenTypeHint")
}
fn name(&self) -> &str {
&self.name
}
}
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct AuthorizationEndpointResponseType {
#[serde(rename = "Name")]
name: String,
#[serde(rename = "Change Controller")]
change_controller: String,
#[serde(rename = "Reference")]
reference: String,
}
impl EnumEntry for AuthorizationEndpointResponseType {
const URL: &'static str = "https://www.iana.org/assignments/oauth-parameters/endpoint.csv";
const SECTIONS: &'static [&'static str] = &["OAuthAuthorizationEndpointResponseType"];
fn key(&self) -> Option<&'static str> {
Some("OAuthAuthorizationEndpointResponseType")
}
fn name(&self) -> &str {
&self.name
}
}
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct TokenEndpointAuthenticationMethod {
#[serde(rename = "Token Endpoint Authentication Method Name")]
name: String,
#[serde(rename = "Change Controller")]
change_controller: String,
#[serde(rename = "Reference")]
reference: String,
}
impl EnumEntry for TokenEndpointAuthenticationMethod {
const URL: &'static str =
"https://www.iana.org/assignments/oauth-parameters/token-endpoint-auth-method.csv";
const SECTIONS: &'static [&'static str] = &["OAuthTokenEndpointAuthenticationMethod"];
fn key(&self) -> Option<&'static str> {
Some("OAuthTokenEndpointAuthenticationMethod")
}
fn name(&self) -> &str {
&self.name
}
}
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct PkceCodeChallengeMethod {
#[serde(rename = "Code Challenge Method Parameter Name")]
name: String,
#[serde(rename = "Change Controller")]
change_controller: String,
#[serde(rename = "Reference")]
reference: String,
}
impl EnumEntry for PkceCodeChallengeMethod {
const URL: &'static str =
"https://www.iana.org/assignments/oauth-parameters/pkce-code-challenge-method.csv";
const SECTIONS: &'static [&'static str] = &["PkceCodeChallengeMethod"];
fn key(&self) -> Option<&'static str> {
Some("PkceCodeChallengeMethod")
}
fn name(&self) -> &str {
&self.name
}
}

View File

@ -0,0 +1,74 @@
// 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.
use anyhow::Context;
use async_trait::async_trait;
use convert_case::{Case, Casing};
use reqwest::Client;
use serde::de::DeserializeOwned;
#[derive(Debug)]
pub struct EnumMember {
pub value: String,
pub description: Option<String>,
pub enum_name: String,
}
#[async_trait]
pub trait EnumEntry: DeserializeOwned + Send + Sync {
const URL: &'static str;
const SECTIONS: &'static [&'static str];
fn key(&self) -> Option<&'static str>;
fn name(&self) -> &str;
fn description(&self) -> Option<&str> {
None
}
fn enum_name(&self) -> String {
self.name().replace('+', "_").to_case(Case::Pascal)
}
async fn fetch(client: &Client) -> anyhow::Result<Vec<(&'static str, EnumMember)>> {
tracing::info!("Fetching CSV");
let body = client
.get(Self::URL)
.send()
.await
.context(format!("can't the CSV at {}", Self::URL))?
.bytes()
.await
.context(format!("can't the CSV body at {}", Self::URL))?;
let parsed: Result<Vec<_>, _> = csv::Reader::from_reader(body.as_ref())
.into_deserialize()
.filter_map(|item: Result<Self, _>| {
item.map(|item| {
item.key().map(|key| {
(
key,
EnumMember {
value: item.name().to_string(),
description: item.description().map(ToString::to_string),
enum_name: item.enum_name(),
},
)
})
})
.transpose()
})
.collect();
Ok(parsed.context(format!("can't parse the CSV at {}", Self::URL))?)
}
}

10
crates/iana/Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "mas-iana"
version = "0.1.0"
authors = ["Quentin Gliech <quenting@element.io>"]
edition = "2021"
license = "Apache-2.0"
[dependencies]
serde = "1.0.133"
schemars = { version = "0.8.8" }

306
crates/iana/src/jose.rs Normal file
View File

@ -0,0 +1,306 @@
// 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.
//! Enums from the "JSON Object Signing and Encryption" IANA registry
//! 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
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, JsonSchema)]
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, JsonSchema)]
pub enum JsonWebEncryptionCompressionAlgorithm {
/// DEFLATE
#[serde(rename = "DEF")]
Def,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
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,
}

16
crates/iana/src/lib.rs Normal file
View File

@ -0,0 +1,16 @@
// 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.
pub mod jose;
pub mod oauth;

100
crates/iana/src/oauth.rs Normal file
View File

@ -0,0 +1,100 @@
// 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.
//! Enums from the "OAuth Parameters" IANA registry
//! 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
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
pub enum OAuthTokenTypeHint {
#[serde(rename = "access_token")]
AccessToken,
#[serde(rename = "refresh_token")]
RefreshToken,
#[serde(rename = "pct")]
Pct,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
pub enum OAuthAuthorizationEndpointResponseType {
#[serde(rename = "code")]
Code,
#[serde(rename = "code id_token")]
CodeIdToken,
#[serde(rename = "code id_token token")]
CodeIdTokenToken,
#[serde(rename = "code token")]
CodeToken,
#[serde(rename = "id_token")]
IdToken,
#[serde(rename = "id_token token")]
IdTokenToken,
#[serde(rename = "none")]
None,
#[serde(rename = "token")]
Token,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
pub enum OAuthTokenEndpointAuthenticationMethod {
#[serde(rename = "none")]
None,
#[serde(rename = "client_secret_post")]
ClientSecretPost,
#[serde(rename = "client_secret_basic")]
ClientSecretBasic,
#[serde(rename = "client_secret_jwt")]
ClientSecretJwt,
#[serde(rename = "private_key_jwt")]
PrivateKeyJwt,
#[serde(rename = "tls_client_auth")]
TlsClientAuth,
#[serde(rename = "self_signed_tls_client_auth")]
SelfSignedTlsClientAuth,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
pub enum PkceCodeChallengeMethod {
#[serde(rename = "plain")]
Plain,
#[serde(rename = "S256")]
S256,
}