jwtea 0.1.0

Lean JWT library
Documentation
//! Types mirroring the JWK(S) structures.

use std::{borrow::Cow, fmt};

use serde::Deserialize;

use crate::{Alg, Error, VerifyingKey};


/// A JSON Web Key Set, defined by RFC 7517 (section 5).
#[derive(Debug, Deserialize)]
pub struct Jwks<'a> {
    pub keys: Vec<Jwk<'a>>,
}

/// Single key in a JWKS, defined by RFC 7517 (section 4).
#[derive(Debug, Deserialize)]
pub struct Jwk<'a> {
    /// The `use` field (see RFC 7517 section 4.2).
    #[serde(rename = "use")]
    pub usage: Option<KeyUsage<'a>>,

    /// The `key_ops` field (see RFC 7517 section 4.3).
    pub key_ops: Option<Vec<KeyOp<'a>>>,

    /// The `alg` field (see RFC 7517 section 4.4).
    pub alg: Option<Alg<'a>>,

    /// The `kid` field (see RFC 7517 section 4.5).
    pub kid: Option<Cow<'a, str>>,

    /// The `kty` (key type) with the actual cryptographic key data.
    #[serde(flatten)]
    pub key_data: KeyData<'a>,

    // Ignoring: x5u, x5c, x5t, x5t#S256
}

/// Cryptographic key data of a JWK + the `kty` field.
///
/// See RFC 7517 section 4.1 and RFC 7518 section 6.
#[derive(Deserialize)]
#[serde(tag = "kty")]
pub enum KeyData<'a> {
    /// Elliptic curves, see RFC 7518 section 6.2.
    #[serde(rename = "EC")]
    Ec {
        crv: EcCurve<'a>,
        x: Cow<'a, str>,
        y: Option<Cow<'a, str>>,
        d: Option<Cow<'a, str>>,
    },

    /// RSA keys, see RFC 7518 section 6.3.
    #[serde(rename = "RSA")]
    Rsa {
        n: Cow<'a, str>,
        e: Cow<'a, str>,
        d: Option<Cow<'a, str>>,
        // Ignoring: p, q, dp, dq, qi, oth
    },

    /// Symmetric keys, see RFC 7518 section 6.4.
    #[serde(rename = "oct")]
    Oct {
        k: Cow<'a, str>,
    },

    /// EdDSA, see RFC 8037.
    #[serde(rename = "OKP")]
    Okp {
        crv: OkpCurve<'a>,
        x: Cow<'a, str>,
        d: Option<Cow<'a, str>>,
    },
}

/// Values for the `use` field of a JWK.
#[derive(Debug, Deserialize, PartialEq, Eq)]
pub enum KeyUsage<'a> {
    #[serde(rename = "sig")]
    Signature,
    #[serde(rename = "enc")]
    Encryption,
    #[serde(untagged)]
    Other(Cow<'a, str>),
}


/// Values for `key_ops` field of a JWK.
#[derive(Debug, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub enum KeyOp<'a> {
    Sign,
    Verify,
    Encrypt,
    Decrypt,
    WrapKey,
    UnwrapKey,
    DeriveKey,
    DeriveBits,
    #[serde(untagged)]
    Other(Cow<'a, str>),
}

crate::make_string_enum!(
    /// Values for the `crv` field for `kty == "EC"`.
    #[derive(Debug, Deserialize, PartialEq, Eq)]
    pub enum EcCurve<'a> {
        P256 = "P-256",
        P384 = "P-384",
        P521 = "P-521",
    }
);

crate::make_string_enum!(
    /// Values for the `crv` field for `kty == "OKP"`.
    #[derive(Debug, Deserialize, PartialEq, Eq)]
    pub enum OkpCurve<'a> {
        Ed25519,
        Ed448,
    }
);


impl<'a> Jwk<'a> {
    /// Deserializes a JWK from the given string (which should be JSON).
    pub fn from_str(s: &str) -> Result<Self, serde_json::Error> {
        serde_json::from_str(s)
    }

    /// Calls [`VerifyingKey::from_jwk`].
    pub fn to_verifying_key(&self) -> Result<VerifyingKey, Error> {
        VerifyingKey::from_jwk(self)
    }
}

impl<'a> Jwks<'a> {
    /// Deserializes a JWK from the given string (which should be JSON).
    pub fn from_str(s: &str) -> Result<Self, serde_json::Error> {
        serde_json::from_str(s)
    }

    /// Returns the keys in this JWKS as verifying keys.
    pub fn to_verifying_keys(&self) -> impl Iterator<Item = Result<VerifyingKey, Error>> {
        self.keys.iter().map(VerifyingKey::from_jwk)
    }
}

impl fmt::Debug for KeyData<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        struct Redacted;
        impl fmt::Debug for Redacted {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                write!(f, "REDACTED")
            }
        }

        match self {
            Self::Ec { crv, x, y, .. } => f.debug_struct("Ec")
                .field("crv", crv)
                .field("x", x)
                .field("y", y)
                .field("d", &Redacted)
                .finish(),
            Self::Rsa { n, e, .. } => f.debug_struct("Rsa")
                .field("n", n)
                .field("e", e)
                .field("d", &Redacted)
                .finish(),
            Self::Oct { .. } => f.debug_struct("Oct")
                .field("k", &Redacted)
                .finish(),
            Self::Okp { crv, x, .. } => f.debug_struct("Okp")
                .field("crv", crv)
                .field("x", x)
                .field("d", &Redacted)
                .finish(),
        }
    }
}