Add types for JWK/JWKS based on biscuit (#195)

* Add types for JWK/JWKS based on biscuit

* Address comments

* Fix issues
This commit is contained in:
Vincent Prouillet 2021-08-18 10:31:52 +02:00
parent 94fef12259
commit a11106faff
10 changed files with 409 additions and 9 deletions

View File

@ -51,7 +51,7 @@ jobs:
include:
- build: pinned
os: ubuntu-18.04
rust: 1.40.0
rust: 1.46.0
- build: stable
os: ubuntu-18.04
rust: stable

View File

@ -7,7 +7,7 @@ readme = "README.md"
description = "Create and decode JWTs in a strongly typed way."
homepage = "https://github.com/Keats/jsonwebtoken"
repository = "https://github.com/Keats/jsonwebtoken"
keywords = ["jwt", "web", "api", "token", "jwk"]
keywords = ["jwt", "api", "token", "jwk"]
edition = "2018"
include = ["src/**/*", "benches/**/*", "tests/**/*", "LICENSE", "README.md", "CHANGELOG.md"]

View File

@ -14,7 +14,7 @@ jsonwebtoken = "7"
serde = {version = "1.0", features = ["derive"] }
```
The minimum required Rust version is 1.40.
The minimum required Rust version is 1.46.
## Algorithms
This library currently supports the following:

38
examples/auth0.rs Normal file
View File

@ -0,0 +1,38 @@
/// Example for the backend to backend implementation
use std::collections::HashMap;
use jsonwebtoken::jwk::AlgorithmParameters;
use jsonwebtoken::{decode, decode_header, jwk, DecodingKey, Validation};
const TOKEN: &str = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjFaNTdkX2k3VEU2S1RZNTdwS3pEeSJ9.eyJpc3MiOiJodHRwczovL2Rldi1kdXp5YXlrNC5ldS5hdXRoMC5jb20vIiwic3ViIjoiNDNxbW44c281R3VFU0U1N0Fkb3BhN09jYTZXeVNidmRAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vZGV2LWR1enlheWs0LmV1LmF1dGgwLmNvbS9hcGkvdjIvIiwiaWF0IjoxNjIzNTg1MzAxLCJleHAiOjE2MjM2NzE3MDEsImF6cCI6IjQzcW1uOHNvNUd1RVNFNTdBZG9wYTdPY2E2V3lTYnZkIiwic2NvcGUiOiJyZWFkOnVzZXJzIiwiZ3R5IjoiY2xpZW50LWNyZWRlbnRpYWxzIn0.0MpewU1GgvRqn4F8fK_-Eu70cUgWA5JJrdbJhkCPCxXP-8WwfI-qx1ZQg2a7nbjXICYAEl-Z6z4opgy-H5fn35wGP0wywDqZpqL35IPqx6d0wRvpPMjJM75zVXuIjk7cEhDr2kaf1LOY9auWUwGzPiDB_wM-R0uvUMeRPMfrHaVN73xhAuQWVjCRBHvNscYS5-i6qBQKDMsql87dwR72DgHzMlaC8NnaGREBC-xiSamesqhKPVyGzSkFSaF3ZKpGrSDapqmHkNW9RDBE3GQ9OHM33vzUdVKOjU1g9Leb9PDt0o1U4p3NQoGJPShQ6zgWSUEaqvUZTfkbpD_DoYDRxA";
const JWKS_REPLY: &str = r#"
{"keys":[{"alg":"RS256","kty":"RSA","use":"sig","n":"2V31IZF-EY2GxXQPI5OaEE--sezizPamNZDW9AjBE2cCErfufM312nT2jUsCnfjsXnh6Z_b-ncOMr97zIZkq1ofU7avemv8nX7NpKmoPBpVrMPprOax2-e3wt-bSfFLIHyghjFLKpkT0LOL_Fimi7xY-J86R06WHojLo3yGzAgQCswZmD4CFf6NcBWDcb6l6kx5vk_AdzHIkVEZH4aikUL_fn3zq5qbE25oOg6pT7F7Pp4zdHOAEKnIRS8tvP8tvvVRkUCrjBxz_Kx6Ne1YOD-fkIMRk_MgIWeKZZzZOYx4VrC0vqYiM-PcKWbNdt1kNoTHOeL06XZeSE6WPZ3VB1Q","e":"AQAB","kid":"1Z57d_i7TE6KTY57pKzDy","x5t":"1gA-aTE9VglLXZnrqvzwWhHsFdk","x5c":["MIIDDTCCAfWgAwIBAgIJHwhLfcIbNvmkMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMTGWRldi1kdXp5YXlrNC5ldS5hdXRoMC5jb20wHhcNMjEwNjEzMDcxMTQ1WhcNMzUwMjIwMDcxMTQ1WjAkMSIwIAYDVQQDExlkZXYtZHV6eWF5azQuZXUuYXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2V31IZF+EY2GxXQPI5OaEE++sezizPamNZDW9AjBE2cCErfufM312nT2jUsCnfjsXnh6Z/b+ncOMr97zIZkq1ofU7avemv8nX7NpKmoPBpVrMPprOax2+e3wt+bSfFLIHyghjFLKpkT0LOL/Fimi7xY+J86R06WHojLo3yGzAgQCswZmD4CFf6NcBWDcb6l6kx5vk/AdzHIkVEZH4aikUL/fn3zq5qbE25oOg6pT7F7Pp4zdHOAEKnIRS8tvP8tvvVRkUCrjBxz/Kx6Ne1YOD+fkIMRk/MgIWeKZZzZOYx4VrC0vqYiM+PcKWbNdt1kNoTHOeL06XZeSE6WPZ3VB1QIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRPX3shmtgajnR4ly5t9VYB66ufGDAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAHtKpX70WU4uXOMjbFKj0e9HMXyCrdcX6TuYiMFqqlOGWM4yghSM8Bd0HkKcirm4DUoC+1dDMzXMZ+tbntavPt1xG0eRFjeocP+kIYTMQEG2LDM5HQ+Z7bdcwlxnuYOZQfpgKAfYbQ8Cxu38sB6q82I+5NJ0w0VXuG7nUZ1RD+rkXaeMYHNoibAtKBoTWrCaFWGV0E55OM+H0ckcHKUUnNXJOyZ+zEOzPFY5iuYIUmn1LfR1P0SLgIMfiooNC5ZuR/wLdbtyKtor2vzz7niEiewz+aPvfuPnWe/vMtQrfS37/yEhCozFnbIps/+S2Ay78mNBDuOAA9fg5yrnOmjABCU="]},{"alg":"RS256","kty":"RSA","use":"sig","n":"0KDpAuJZyDwPg9CfKi0R3QwDROyH0rvd39lmAoqQNqtYPghDToxFMDLpul0QHttbofHPJMKrPfeEFEOvw7KJgelCHZmckVKaz0e4tfu_2Uvw2kFljCmJGfspUU3mXxLyEea9Ef9JqUru6L8f_0_JIDMT3dceqU5ZqbG8u6-HRgRQ5Jqc_fF29Xyw3gxNP_Q46nsp_0yE68UZE1iPy1om0mpu8mpsY1-Nbvm51C8i4_tFQHdUXbhF4cjAoR0gZFNkzr7FCrL4On0hKeLcvxIHD17SxaBsTuCBGd35g7TmXsA4hSimD9taRHA-SkXh558JG5dr-YV9x80qjeSAvTyjcQ","e":"AQAB","kid":"v2HFn4VqJB-U4vtQRJ3Ql","x5t":"AhUBZjtsFdx7C1PFtWAJ756bo5k","x5c":["MIIDDTCCAfWgAwIBAgIJSSFLkuG8uAM8MA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMTGWRldi1kdXp5YXlrNC5ldS5hdXRoMC5jb20wHhcNMjEwNjEzMDcxMTQ2WhcNMzUwMjIwMDcxMTQ2WjAkMSIwIAYDVQQDExlkZXYtZHV6eWF5azQuZXUuYXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0KDpAuJZyDwPg9CfKi0R3QwDROyH0rvd39lmAoqQNqtYPghDToxFMDLpul0QHttbofHPJMKrPfeEFEOvw7KJgelCHZmckVKaz0e4tfu/2Uvw2kFljCmJGfspUU3mXxLyEea9Ef9JqUru6L8f/0/JIDMT3dceqU5ZqbG8u6+HRgRQ5Jqc/fF29Xyw3gxNP/Q46nsp/0yE68UZE1iPy1om0mpu8mpsY1+Nbvm51C8i4/tFQHdUXbhF4cjAoR0gZFNkzr7FCrL4On0hKeLcvxIHD17SxaBsTuCBGd35g7TmXsA4hSimD9taRHA+SkXh558JG5dr+YV9x80qjeSAvTyjcQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSEkRwvkyYzzzY/jPd1n7/1VRQNdzAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAGtdl7QwzpaWZjbmd6UINAIlpuWIo2v4EJD9kGan/tUZTiUdBaJVwFHOkLRsbZHc5PmBB5IryjOcrqsmKvFdo6wUZA92qTuQVZrOTea07msOKSWE6yRUh1/VCXH2+vAiB9A4DFZ23WpZikBR+DmiD8NGwVgAwWw9jM6pe7ODY+qxFXGjQdTCHcDdbqG2160nKEHCBvjR1Sc/F0pzHPv8CBJCyGAPTCXX42sKZI92pPzdKSmNNijCuIEYLsjzKVxaUuwEqIshk3mYeu6im4VmXXFj+MlyMsusVWi2py7fGFadamzyiV/bxZe+4xzzrRG1Kow/WnVEizfTdEzFXO6YikE="]}]}
"#;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let jwks: jwk::JwkSet = serde_json::from_str(JWKS_REPLY).unwrap();
let header = decode_header(TOKEN)?;
let kid = match header.kid {
Some(k) => k,
None => return Err("Token doesn't have a `kid` header field".into()),
};
if let Some(j) = jwks.find(&kid) {
match j.algorithm {
AlgorithmParameters::RSA(ref rsa) => {
let decoding_key = DecodingKey::from_rsa_components(&rsa.n, &rsa.e).unwrap();
let mut validation = Validation::new(j.common.algorithm.unwrap());
validation.validate_exp = false;
let decoded_token =
decode::<HashMap<String, serde_json::Value>>(TOKEN, &decoding_key, &validation)
.unwrap();
println!("{:?}", decoded_token);
}
_ => unreachable!("this should be a RSA"),
}
} else {
return Err("No matching JWK found for the given kid".into());
}
Ok(())
}

View File

@ -12,7 +12,7 @@ pub(crate) enum AlgorithmFamily {
/// The algorithms supported for signing/verifying JWTs
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug, PartialEq, Hash, Copy, Clone, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize)]
pub enum Algorithm {
/// HMAC using SHA-256
HS256,

View File

@ -79,7 +79,6 @@ impl DecodingKey {
}
/// If you have (n, e) RSA public key components already decoded, use this.
/// TODO: do we need that?
pub fn from_rsa_raw_components(modulus: &[u8], exponent: &[u8]) -> Self {
DecodingKey {
family: AlgorithmFamily::Rsa,
@ -132,7 +131,7 @@ impl DecodingKey {
}
pub(crate) fn as_bytes(&self) -> &[u8] {
match &self.kind {
DecodingKeyKind::SecretOrDer(b) => &b,
DecodingKeyKind::SecretOrDer(b) => b,
DecodingKeyKind::RsaModulusExponent { .. } => unreachable!(),
}
}

View File

@ -4,11 +4,12 @@ use serde::{Deserialize, Serialize};
use crate::algorithms::Algorithm;
use crate::errors::Result;
use crate::jwk::Jwk;
use crate::serialization::b64_decode;
/// A basic JWT header, the alg defaults to HS256 and typ is automatically
/// set to `JWT`. All the other fields are optional.
#[derive(Debug, Clone, PartialEq, Hash, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Header {
/// The type of JWS: it can only be "JWT" here
///
@ -29,6 +30,11 @@ pub struct Header {
/// Defined in [RFC7515#4.1.2](https://tools.ietf.org/html/rfc7515#section-4.1.2).
#[serde(skip_serializing_if = "Option::is_none")]
pub jku: Option<String>,
/// JSON Web Key
///
/// Defined in [RFC7515#4.1.3](https://tools.ietf.org/html/rfc7515#section-4.1.3).
#[serde(skip_serializing_if = "Option::is_none")]
pub jwk: Option<Jwk>,
/// Key ID
///
/// Defined in [RFC7515#4.1.4](https://tools.ietf.org/html/rfc7515#section-4.1.4).
@ -59,6 +65,7 @@ impl Header {
alg: algorithm,
cty: None,
jku: None,
jwk: None,
kid: None,
x5u: None,
x5c: None,

357
src/jwk.rs Normal file
View File

@ -0,0 +1,357 @@
#![allow(missing_docs)]
///! This crate contains types only for working JWK and JWK Sets
///! This is only meant to be used to deal with public JWK, not generate ones.
///! Most of the code in this file is taken from https://github.com/lawliet89/biscuit but
/// tweaked to remove the private bits as it's not the goal for this crate currently.
///!
use crate::Algorithm;
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
/// The intended usage of the public `KeyType`. This enum is serialized `untagged`
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum PublicKeyUse {
/// Indicates a public key is meant for signature verification
Signature,
/// Indicates a public key is meant for encryption
Encryption,
/// Other usage
Other(String),
}
impl Serialize for PublicKeyUse {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let string = match *self {
PublicKeyUse::Signature => "sig",
PublicKeyUse::Encryption => "enc",
PublicKeyUse::Other(ref other) => other,
};
serializer.serialize_str(string)
}
}
impl<'de> Deserialize<'de> for PublicKeyUse {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct PublicKeyUseVisitor;
impl<'de> de::Visitor<'de> for PublicKeyUseVisitor {
type Value = PublicKeyUse;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "a string")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(match v {
"sig" => PublicKeyUse::Signature,
"enc" => PublicKeyUse::Encryption,
other => PublicKeyUse::Other(other.to_string()),
})
}
}
deserializer.deserialize_string(PublicKeyUseVisitor)
}
}
/// Operations that the key is intended to be used for. This enum is serialized `untagged`
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum KeyOperations {
/// Computer digital signature or MAC
Sign,
/// Verify digital signature or MAC
Verify,
/// Encrypt content
Encrypt,
/// Decrypt content and validate decryption, if applicable
Decrypt,
/// Encrypt key
WrapKey,
/// Decrypt key and validate decryption, if applicable
UnwrapKey,
/// Derive key
DeriveKey,
/// Derive bits not to be used as a key
DeriveBits,
/// Other operation
Other(String),
}
impl Serialize for KeyOperations {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let string = match *self {
KeyOperations::Sign => "sign",
KeyOperations::Verify => "verify",
KeyOperations::Encrypt => "encrypt",
KeyOperations::Decrypt => "decrypt",
KeyOperations::WrapKey => "wrapKey",
KeyOperations::UnwrapKey => "unwrapKey",
KeyOperations::DeriveKey => "deriveKey",
KeyOperations::DeriveBits => "deriveBits",
KeyOperations::Other(ref other) => other,
};
serializer.serialize_str(string)
}
}
impl<'de> Deserialize<'de> for KeyOperations {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct KeyOperationsVisitor;
impl<'de> de::Visitor<'de> for KeyOperationsVisitor {
type Value = KeyOperations;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "a string")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(match v {
"sign" => KeyOperations::Sign,
"verify" => KeyOperations::Verify,
"encrypt" => KeyOperations::Encrypt,
"decrypt" => KeyOperations::Decrypt,
"wrapKey" => KeyOperations::WrapKey,
"unwrapKey" => KeyOperations::UnwrapKey,
"deriveKey" => KeyOperations::DeriveKey,
"deriveBits" => KeyOperations::DeriveBits,
other => KeyOperations::Other(other.to_string()),
})
}
}
deserializer.deserialize_string(KeyOperationsVisitor)
}
}
/// Common JWK parameters
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Default)]
pub struct CommonParameters {
/// The intended use of the public key. Should not be specified with `key_operations`.
/// See sections 4.2 and 4.3 of [RFC7517](https://tools.ietf.org/html/rfc7517).
#[serde(rename = "use", skip_serializing_if = "Option::is_none", default)]
pub public_key_use: Option<PublicKeyUse>,
/// The "key_ops" (key operations) parameter identifies the operation(s)
/// for which the key is intended to be used. The "key_ops" parameter is
/// intended for use cases in which public, private, or symmetric keys
/// may be present.
/// Should not be specified with `public_key_use`.
/// See sections 4.2 and 4.3 of [RFC7517](https://tools.ietf.org/html/rfc7517).
#[serde(rename = "key_ops", skip_serializing_if = "Option::is_none", default)]
pub key_operations: Option<Vec<KeyOperations>>,
/// The algorithm intended for use with the key
#[serde(rename = "alg", skip_serializing_if = "Option::is_none", default)]
pub algorithm: Option<Algorithm>,
/// The case sensitive Key ID for the key
#[serde(rename = "kid", skip_serializing_if = "Option::is_none", default)]
pub key_id: Option<String>,
/// X.509 Public key cerfificate URL. This is currently not implemented (correctly).
/// Serialized to `x5u`.
#[serde(rename = "x5u", skip_serializing_if = "Option::is_none")]
pub x509_url: Option<String>,
/// X.509 public key certificate chain. This is currently not implemented (correctly).
/// Serialized to `x5c`.
#[serde(rename = "x5c", skip_serializing_if = "Option::is_none")]
pub x509_chain: Option<Vec<String>>,
/// X.509 Certificate thumbprint. This is currently not implemented (correctly).
/// Also not implemented, is the SHA-256 thumbprint variant of this header.
/// Serialized to `x5t`.
// TODO: How to make sure the headers are mutually exclusive?
#[serde(rename = "x5t", skip_serializing_if = "Option::is_none")]
pub x509_fingerprint: Option<String>,
}
/// Key type value for an Elliptic Curve Key.
/// This single value enum is a workaround for Rust not supporting associated constants.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum EllipticCurveKeyType {
/// Key type value for an Elliptic Curve Key.
EC,
}
impl Default for EllipticCurveKeyType {
fn default() -> Self {
EllipticCurveKeyType::EC
}
}
/// Type of cryptographic curve used by a key. This is defined in
/// [RFC 7518 #7.6](https://tools.ietf.org/html/rfc7518#section-7.6)
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum EllipticCurve {
/// P-256 curve
#[serde(rename = "P-256")]
P256,
/// P-384 curve
#[serde(rename = "P-384")]
P384,
/// P-521 curve -- unsupported by `ring`.
#[serde(rename = "P-521")]
P521,
}
impl Default for EllipticCurve {
fn default() -> Self {
EllipticCurve::P256
}
}
/// Parameters for an Elliptic Curve Key
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default)]
pub struct EllipticCurveKeyParameters {
/// Key type value for an Elliptic Curve Key.
#[serde(rename = "kty")]
pub key_type: EllipticCurveKeyType,
/// The "crv" (curve) parameter identifies the cryptographic curve used
/// with the key.
#[serde(rename = "crv")]
pub curve: EllipticCurve,
/// The "x" (x coordinate) parameter contains the x coordinate for the
/// Elliptic Curve point.
pub x: String,
/// The "y" (y coordinate) parameter contains the y coordinate for the
/// Elliptic Curve point.
pub y: String,
}
/// Key type value for an RSA Key.
/// This single value enum is a workaround for Rust not supporting associated constants.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum RSAKeyType {
/// Key type value for an RSA Key.
RSA,
}
impl Default for RSAKeyType {
fn default() -> Self {
RSAKeyType::RSA
}
}
/// Parameters for a RSA Key
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default)]
pub struct RSAKeyParameters {
/// Key type value for a RSA Key
#[serde(rename = "kty")]
pub key_type: RSAKeyType,
/// The "n" (modulus) parameter contains the modulus value for the RSA
/// public key.
pub n: String,
/// The "e" (exponent) parameter contains the exponent value for the RSA
/// public key.
pub e: String,
}
/// Key type value for an Octet symmetric key.
/// This single value enum is a workaround for Rust not supporting associated constants.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum OctetKeyType {
/// Key type value for an Octet symmetric key.
#[serde(rename = "oct")]
Octet,
}
impl Default for OctetKeyType {
fn default() -> Self {
OctetKeyType::Octet
}
}
/// Parameters for an Octet Key
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default)]
pub struct OctetKeyParameters {
/// Key type value for an Octet Key
#[serde(rename = "kty")]
pub key_type: OctetKeyType,
/// The octet key value
pub value: String,
}
/// Key type value for an Octet Key Pair.
/// This single value enum is a workaround for Rust not supporting associated constants.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum OctetKeyPairType {
/// Key type value for an Octet Key Pair.
#[serde(rename = "OKP")]
OctetKeyPair,
}
impl Default for OctetKeyPairType {
fn default() -> Self {
OctetKeyPairType::OctetKeyPair
}
}
/// Parameters for an Octet Key Pair
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default)]
pub struct OctetKeyPairParameters {
/// Key type value for an Octet Key Pair
#[serde(rename = "kty")]
pub key_type: OctetKeyPairType,
/// The "crv" (curve) parameter identifies the cryptographic curve used
/// with the key.
#[serde(rename = "crv")]
pub curve: EllipticCurve,
/// The "x" parameter contains the base64 encoded public key
pub x: String,
}
/// Algorithm specific parameters
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum AlgorithmParameters {
EllipticCurve(EllipticCurveKeyParameters),
RSA(RSAKeyParameters),
OctetKey(OctetKeyParameters),
OctetKeyPair(OctetKeyPairParameters),
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct Jwk {
#[serde(flatten)]
pub common: CommonParameters,
/// Key algorithm specific parameters
#[serde(flatten)]
pub algorithm: AlgorithmParameters,
}
/// A JWK set
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct JwkSet {
pub keys: Vec<Jwk>,
}
impl JwkSet {
/// Find the key in the set that matches the given key id, if any.
pub fn find(&self, kid: &str) -> Option<&Jwk> {
self.keys
.iter()
.find(|jwk| jwk.common.key_id.is_some() && jwk.common.key_id.as_ref().unwrap() == kid)
}
}

View File

@ -11,6 +11,7 @@ mod encoding;
/// All the errors that can be encountered while encoding/decoding JWTs
pub mod errors;
mod header;
pub mod jwk;
mod pem;
mod serialization;
mod validation;

View File

@ -1,7 +1,5 @@
use crate::errors::{ErrorKind, Result};
use simple_asn1::{BigUint, OID};
/// Supported PEM files for EC and RSA Public and Private Keys
#[derive(Debug, PartialEq)]
enum PemType {