From fa22e01714e6a892551d2753c7b96713244dcb86 Mon Sep 17 00:00:00 2001 From: Nick Hynes Date: Mon, 13 Jul 2020 22:11:10 +0000 Subject: [PATCH] Add jsonwebtoken conversions --- Cargo.toml | 1 + README.md | 1 + src/lib.rs | 62 ++++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5ae407a..707d79b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ edition = "2018" base64 = "0.12" bitflags = "1.2" derive_more = "0.99" +jsonwebtoken = { version = "7.2", optional = true } num-bigint = { version = "0.2", optional = true } paste = "0.1" serde = { version = "1.0", features = ["derive"] } diff --git a/README.md b/README.md index 1106d1b..84cf456 100644 --- a/README.md +++ b/README.md @@ -40,3 +40,4 @@ fn main() { * `convert` - enables `Key::{to_der, to_pem}`. This pulls in the [yasna](https://crates.io/crates/yasna) crate. +* `jsonwebtoken` - enables conversions to types in the [jsonwebtoken](https://crates.io/crates/jsonwebtoken) crate. diff --git a/src/lib.rs b/src/lib.rs index 7ab5695..04763d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,9 +36,41 @@ pub struct JsonWebKey { } impl JsonWebKey { + pub fn new(key: Key) -> Self { + Self { + key: box key, + key_use: None, + key_ops: KeyOps::empty(), + key_id: None, + algorithm: None, + } + } + + pub fn set_algorithm(&mut self, alg: JsonWebAlgorithm) -> Result<(), Error> { + Self::validate_algorithm(alg, &*self.key)?; + self.algorithm = Some(alg); + Ok(()) + } + pub fn from_slice(bytes: impl AsRef<[u8]>) -> Result { Ok(serde_json::from_slice(bytes.as_ref())?) } + + fn validate_algorithm(alg: JsonWebAlgorithm, key: &Key) -> Result<(), Error> { + use JsonWebAlgorithm::*; + use Key::*; + match (alg, key) { + ( + ES256, + EC { + curve: Curve::P256 { .. }, + }, + ) + | (RS256, RSA { .. }) + | (HS256, Symmetric { .. }) => Ok(()), + _ => Err(Error::MismatchedAlgorithm), + } + } } impl std::str::FromStr for JsonWebKey { @@ -46,24 +78,11 @@ impl std::str::FromStr for JsonWebKey { fn from_str(json: &str) -> Result { let jwk = Self::from_slice(json.as_bytes())?; - // Validate alg. - use JsonWebAlgorithm::*; - use Key::*; - let alg = match &jwk.algorithm { + let alg = match jwk.algorithm { Some(alg) => alg, None => return Ok(jwk), }; - match (alg, &*jwk.key) { - ( - ES256, - EC { - curve: Curve::P256 { .. }, - }, - ) - | (RS256, RSA { .. }) - | (HS256, Symmetric { .. }) => Ok(jwk), - _ => Err(Error::MismatchedAlgorithm), - } + Self::validate_algorithm(alg, &*jwk.key).map(|_| jwk) } } @@ -346,13 +365,24 @@ pub enum KeyUse { Encryption, } -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)] pub enum JsonWebAlgorithm { HS256, RS256, ES256, } +#[cfg(any(test, feature = "jsonwebtoken"))] +impl Into for JsonWebAlgorithm { + fn into(self) -> jsonwebtoken::Algorithm { + match self { + Self::HS256 => jsonwebtoken::Algorithm::HS256, + Self::ES256 => jsonwebtoken::Algorithm::ES256, + Self::RS256 => jsonwebtoken::Algorithm::RS256, + } + } +} + #[derive(Debug, thiserror::Error)] pub enum Error { #[error(transparent)]