From 84ee604e882b77d406166be7de8c4463bc15eec2 Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Sun, 16 Jun 2019 17:51:43 +0200 Subject: [PATCH] trait -> enum --- README.md | 11 +- examples/custom_header.rs | 6 +- examples/validation.rs | 6 +- src/algorithms.rs | 48 +++++++ src/crypto.rs | 265 ++++++++++---------------------------- src/header.rs | 2 +- src/keys.rs | 13 ++ src/lib.rs | 17 ++- src/validation.rs | 3 +- tests/ecdsa.rs | 12 +- tests/lib.rs | 28 ++-- tests/rsa.rs | 12 +- 12 files changed, 175 insertions(+), 248 deletions(-) create mode 100644 src/algorithms.rs create mode 100644 src/keys.rs diff --git a/README.md b/README.md index 269c1a4..41aa215 100644 --- a/README.md +++ b/README.md @@ -8,20 +8,11 @@ Add the following to Cargo.toml: ```toml -jsonwebtoken = "6" +jsonwebtoken = "7" serde_derive = "1" serde = "1" ``` -## Help wanted for v7 - -v6 was released as a stopgap version to update Ring and add a couple of features like ES256/384. -The results are not very ergonomic once we factor in all the possible ways to load a RSA key for example. -A possible solution is to have decoder types as described in https://github.com/Keats/jsonwebtoken/issues/76 -but I currently do not have the time to implement it myself. -I will take any better idea as well of course! - - ## How to use Complete examples are available in the examples directory: a basic one and one with a custom header. diff --git a/examples/custom_header.rs b/examples/custom_header.rs index d43ae50..cdcf38b 100644 --- a/examples/custom_header.rs +++ b/examples/custom_header.rs @@ -3,7 +3,7 @@ extern crate jsonwebtoken as jwt; extern crate serde_derive; use jwt::errors::ErrorKind; -use jwt::{decode, encode, Algorithm, Header, Validation}; +use jwt::{decode, encode, Algorithm, Header, Validation, Key}; #[derive(Debug, Serialize, Deserialize)] struct Claims { @@ -21,14 +21,14 @@ fn main() { header.kid = Some("signing_key".to_owned()); header.alg = Algorithm::HS512; - let token = match encode(&header, &my_claims, jwt::Der::from(key)) { + let token = match encode(&header, &my_claims, Key::Hmac(key)) { Ok(t) => t, Err(_) => panic!(), // in practice you would return the error }; println!("{:?}", token); let token_data = - match decode::(&token, key.as_ref(), &Validation::new(Algorithm::HS512)) { + match decode::(&token, Key::Hmac(key), &Validation::new(Algorithm::HS512)) { Ok(c) => c, Err(err) => match *err.kind() { ErrorKind::InvalidToken => panic!(), // Example on how to handle a specific error diff --git a/examples/validation.rs b/examples/validation.rs index 6b2435a..71c95b5 100644 --- a/examples/validation.rs +++ b/examples/validation.rs @@ -3,7 +3,7 @@ extern crate jsonwebtoken as jwt; extern crate serde_derive; use jwt::errors::ErrorKind; -use jwt::{decode, encode, Header, Validation}; +use jwt::{decode, encode, Header, Validation, Key}; #[derive(Debug, Serialize, Deserialize)] struct Claims { @@ -16,13 +16,13 @@ fn main() { let my_claims = Claims { sub: "b@b.com".to_owned(), company: "ACME".to_owned(), exp: 10000000000 }; let key = b"secret"; - let token = match encode(&Header::default(), &my_claims, jwt::Hmac::from(key)) { + let token = match encode(&Header::default(), &my_claims, Key::Hmac(key)) { Ok(t) => t, Err(_) => panic!(), // in practice you would return the error }; let validation = Validation { sub: Some("b@b.com".to_string()), ..Validation::default() }; - let token_data = match decode::(&token, key.as_ref(), &validation) { + let token_data = match decode::(&token, Key::Hmac(key), &validation) { Ok(c) => c, Err(err) => match *err.kind() { ErrorKind::InvalidToken => panic!("Token is invalid"), // Example on how to handle a specific error diff --git a/src/algorithms.rs b/src/algorithms.rs new file mode 100644 index 0000000..0e172f3 --- /dev/null +++ b/src/algorithms.rs @@ -0,0 +1,48 @@ +use errors::{new_error, Error, ErrorKind, Result}; +use std::str::FromStr; + +/// The algorithms supported for signing/verifying +#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)] +pub enum Algorithm { + /// HMAC using SHA-256 + HS256, + /// HMAC using SHA-384 + HS384, + /// HMAC using SHA-512 + HS512, + + /// ECDSA using SHA-256 + ES256, + /// ECDSA using SHA-384 + ES384, + + /// RSASSA-PKCS1-v1_5 using SHA-256 + RS256, + /// RSASSA-PKCS1-v1_5 using SHA-384 + RS384, + /// RSASSA-PKCS1-v1_5 using SHA-512 + RS512, +} + +impl Default for Algorithm { + fn default() -> Self { + Algorithm::HS256 + } +} + +impl FromStr for Algorithm { + type Err = Error; + fn from_str(s: &str) -> Result { + match s { + "HS256" => Ok(Algorithm::HS256), + "HS384" => Ok(Algorithm::HS384), + "HS512" => Ok(Algorithm::HS512), + "ES256" => Ok(Algorithm::ES256), + "ES384" => Ok(Algorithm::ES384), + "RS256" => Ok(Algorithm::RS256), + "RS384" => Ok(Algorithm::RS384), + "RS512" => Ok(Algorithm::RS512), + _ => Err(new_error(ErrorKind::InvalidAlgorithmName)), + } + } +} diff --git a/src/crypto.rs b/src/crypto.rs index cab93e7..741585c 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -3,82 +3,35 @@ use std::sync::Arc; use base64; use ring::constant_time::verify_slices_are_equal; use ring::{digest, hmac, rand, signature}; -use std::str::FromStr; use untrusted; -use errors::{new_error, Error, ErrorKind, Result}; - -/// The algorithms supported for signing/verifying -#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)] -pub enum Algorithm { - /// HMAC using SHA-256 - HS256, - /// HMAC using SHA-384 - HS384, - /// HMAC using SHA-512 - HS512, - - /// ECDSA using SHA-256 - ES256, - - /// ECDSA using SHA-384 - ES384, - - /// RSASSA-PKCS1-v1_5 using SHA-256 - RS256, - /// RSASSA-PKCS1-v1_5 using SHA-384 - RS384, - /// RSASSA-PKCS1-v1_5 using SHA-512 - RS512, -} - -impl Default for Algorithm { - fn default() -> Self { - Algorithm::HS256 - } -} - -impl FromStr for Algorithm { - type Err = Error; - fn from_str(s: &str) -> Result { - match s { - "HS256" => Ok(Algorithm::HS256), - "HS384" => Ok(Algorithm::HS384), - "HS512" => Ok(Algorithm::HS512), - "ES256" => Ok(Algorithm::ES256), - "ES384" => Ok(Algorithm::ES384), - "RS256" => Ok(Algorithm::RS256), - "RS384" => Ok(Algorithm::RS384), - "RS512" => Ok(Algorithm::RS512), - _ => Err(new_error(ErrorKind::InvalidAlgorithmName)), - } - } -} +use algorithms::Algorithm; +use errors::{new_error, ErrorKind, Result}; +use keys::Key; /// The actual HS signing + encoding -fn sign_hmac( - alg: &'static digest::Algorithm, - key: K, - signing_input: &str, -) -> Result { - let signing_key = hmac::SigningKey::new(alg, key.as_ref()); +fn sign_hmac(alg: &'static digest::Algorithm, key: Key, signing_input: &str) -> Result { + let signing_key = match key { + Key::Hmac(bytes) => hmac::SigningKey::new(alg, bytes), + _ => return Err(ErrorKind::InvalidKeyFormat)?, + }; let digest = hmac::sign(&signing_key, signing_input.as_bytes()); Ok(base64::encode_config::(&digest, base64::URL_SAFE_NO_PAD)) } /// The actual ECDSA signing + encoding -fn sign_ecdsa( +fn sign_ecdsa( alg: &'static signature::EcdsaSigningAlgorithm, - key: K, + key: Key, signing_input: &str, ) -> Result { - let signing_key = match key.format() { - KeyFormat::PKCS8 => { - signature::EcdsaKeyPair::from_pkcs8(alg, untrusted::Input::from(key.as_ref()))? + let signing_key = match key { + Key::Pkcs8(bytes) => { + signature::EcdsaKeyPair::from_pkcs8(alg, untrusted::Input::from(bytes))? } _ => { - return Err(ErrorKind::InvalidKeyFormat)?; + return Err(new_error(ErrorKind::InvalidKeyFormat)); } }; @@ -89,19 +42,12 @@ fn sign_ecdsa( /// The actual RSA signing + encoding /// Taken from Ring doc https://briansmith.org/rustdoc/ring/signature/index.html -fn sign_rsa( - alg: &'static signature::RsaEncoding, - key: K, - signing_input: &str, -) -> Result { - let key_bytes = untrusted::Input::from(key.as_ref()); - let key_pair = match key.format() { - KeyFormat::DER => { - signature::RsaKeyPair::from_der(key_bytes).map_err(|_| ErrorKind::InvalidRsaKey)? - } - KeyFormat::PKCS8 => { - signature::RsaKeyPair::from_pkcs8(key_bytes).map_err(|_| ErrorKind::InvalidRsaKey)? - } +fn sign_rsa(alg: &'static signature::RsaEncoding, key: Key, signing_input: &str) -> Result { + let key_pair = match key { + Key::Der(bytes) => signature::RsaKeyPair::from_der(untrusted::Input::from(bytes)) + .map_err(|_| ErrorKind::InvalidRsaKey)?, + Key::Pkcs8(bytes) => signature::RsaKeyPair::from_pkcs8(untrusted::Input::from(bytes)) + .map_err(|_| ErrorKind::InvalidRsaKey)?, _ => { return Err(ErrorKind::InvalidKeyFormat)?; } @@ -121,7 +67,7 @@ fn sign_rsa( /// the base64 url safe encoded of the result. /// /// Only use this function if you want to do something other than JWT. -pub fn sign(signing_input: &str, key: K, algorithm: Algorithm) -> Result { +pub fn sign(signing_input: &str, key: Key, algorithm: Algorithm) -> Result { match algorithm { Algorithm::HS256 => sign_hmac(&digest::SHA256, key, signing_input), Algorithm::HS384 => sign_hmac(&digest::SHA384, key, signing_input), @@ -157,6 +103,36 @@ fn verify_ring( Ok(res.is_ok()) } +fn verify_ring_es( + alg: &dyn signature::VerificationAlgorithm, + signature: &str, + signing_input: &str, + key: Key, +) -> Result { + let bytes = match key { + Key::Pkcs8(bytes) => bytes, + _ => { + return Err(ErrorKind::InvalidKeyFormat)?; + } + }; + verify_ring(alg, signature, signing_input, bytes) +} + +fn verify_ring_rsa( + alg: &dyn signature::VerificationAlgorithm, + signature: &str, + signing_input: &str, + key: Key, +) -> Result { + let bytes = match key { + Key::Der(bytes) | Key::Pkcs8(bytes) => bytes, + _ => { + return Err(ErrorKind::InvalidKeyFormat)?; + } + }; + verify_ring(alg, signature, signing_input, bytes) +} + /// Compares the signature given with a re-computed signature for HMAC or using the public key /// for RSA. /// @@ -168,34 +144,40 @@ fn verify_ring( pub fn verify( signature: &str, signing_input: &str, - public_key: &[u8], + public_key: Key, algorithm: Algorithm, ) -> Result { match algorithm { Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => { // we just re-sign the data with the key and compare if they are equal - let signed = sign(signing_input, Hmac::from(&public_key), algorithm)?; + let signed = sign(signing_input, public_key, algorithm)?; Ok(verify_slices_are_equal(signature.as_ref(), signed.as_ref()).is_ok()) } - Algorithm::ES256 => { - verify_ring(&signature::ECDSA_P256_SHA256_FIXED, signature, signing_input, public_key) - } - Algorithm::ES384 => { - verify_ring(&signature::ECDSA_P384_SHA384_FIXED, signature, signing_input, public_key) - } - Algorithm::RS256 => verify_ring( + Algorithm::ES256 => verify_ring_es( + &signature::ECDSA_P256_SHA256_FIXED, + signature, + signing_input, + public_key, + ), + Algorithm::ES384 => verify_ring_es( + &signature::ECDSA_P384_SHA384_FIXED, + signature, + signing_input, + public_key, + ), + Algorithm::RS256 => verify_ring_rsa( &signature::RSA_PKCS1_2048_8192_SHA256, signature, signing_input, public_key, ), - Algorithm::RS384 => verify_ring( + Algorithm::RS384 => verify_ring_rsa( &signature::RSA_PKCS1_2048_8192_SHA384, signature, signing_input, public_key, ), - Algorithm::RS512 => verify_ring( + Algorithm::RS512 => verify_ring_rsa( &signature::RSA_PKCS1_2048_8192_SHA512, signature, signing_input, @@ -203,114 +185,3 @@ pub fn verify( ), } } - -/// The supported RSA key formats, see the documentation for ring::signature::RsaKeyPair -/// for more information -pub enum KeyFormat { - /// An unencrypted PKCS#8-encoded key. Can be used with both ECDSA and RSA - /// algorithms when signing. See ring for information. - PKCS8, - /// A binary DER-encoded ASN.1 key. Can only be used with RSA algorithms - /// when signing. See ring for more information - DER, - /// This is not a key format, but provided for convenience since HMAC is - /// a supported signing algorithm. - HMAC, -} - -/// A tiny abstraction on top of raw key buffers to add key format -/// information -pub trait Key: AsRef<[u8]> { - /// The format of the key - fn format(&self) -> KeyFormat; -} - -/// This blanket implementation aligns with the key loading as of version 6.0.0 -// impl Key for T -// where -// T: AsRef<[u8]>, -// { -// fn format(&self) -> KeyFormat { -// KeyFormat::DER -// } -// } - -/// A convenience wrapper for a key buffer as an unencrypted PKCS#8-encoded, -/// see ring for more details -pub struct Pkcs8<'a> { - key_bytes: &'a [u8], -} - -impl<'a> Key for Pkcs8<'a> { - fn format(&self) -> KeyFormat { - KeyFormat::PKCS8 - } -} - -impl<'a> AsRef<[u8]> for Pkcs8<'a> { - fn as_ref(&self) -> &[u8] { - self.key_bytes - } -} - -impl<'a, T> From<&'a T> for Pkcs8<'a> -where - T: AsRef<[u8]>, -{ - fn from(key: &'a T) -> Self { - Self { key_bytes: key.as_ref() } - } -} - -/// A convenience wrapper for a key buffer as a binary DER-encoded ASN.1 key, -/// see ring for more details -pub struct Der<'a> { - key_bytes: &'a [u8], -} - -impl<'a> Key for Der<'a> { - fn format(&self) -> KeyFormat { - KeyFormat::DER - } -} - -impl<'a> AsRef<[u8]> for Der<'a> { - fn as_ref(&self) -> &[u8] { - self.key_bytes - } -} - -impl<'a, T> From<&'a T> for Der<'a> -where - T: AsRef<[u8]>, -{ - fn from(key: &'a T) -> Self { - Self { key_bytes: key.as_ref() } - } -} - -/// Convenience wrapper for an HMAC key -pub struct Hmac<'a> { - key_bytes: &'a [u8], -} - -impl<'a> Key for Hmac<'a> { - fn format(&self) -> KeyFormat { - KeyFormat::HMAC - } -} - -impl<'a> AsRef<[u8]> for Hmac<'a> { - fn as_ref(&self) -> &[u8] { - self.key_bytes - } -} - -impl<'a, T> From<&'a T> for Hmac<'a> -where - T: AsRef<[u8]>, -{ - fn from(key: &'a T) -> Self { - Self { key_bytes: key.as_ref() } - } -} diff --git a/src/header.rs b/src/header.rs index 0db2614..2620519 100644 --- a/src/header.rs +++ b/src/header.rs @@ -1,4 +1,4 @@ -use crypto::Algorithm; +use algorithms::Algorithm; /// A basic JWT header, the alg defaults to HS256 and typ is automatically /// set to `JWT`. All the other fields are optional. diff --git a/src/keys.rs b/src/keys.rs new file mode 100644 index 0000000..7024daa --- /dev/null +++ b/src/keys.rs @@ -0,0 +1,13 @@ +/// The supported RSA key formats, see the documentation for ring::signature::RsaKeyPair +/// for more information +pub enum Key<'a> { + /// An unencrypted PKCS#8-encoded key. Can be used with both ECDSA and RSA + /// algorithms when signing. See ring for information. + Pkcs8(&'a [u8]), + /// A binary DER-encoded ASN.1 key. Can only be used with RSA algorithms + /// when signing. See ring for more information + Der(&'a [u8]), + /// This is not a key format, but provided for convenience since HMAC is + /// a supported signing algorithm. + Hmac(&'a [u8]), +} diff --git a/src/lib.rs b/src/lib.rs index 35217f8..b0a9073 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ //! Create and parses JWT (JSON Web Tokens) //! //! Documentation: [stable](https://docs.rs/jsonwebtoken/) -#![recursion_limit = "300"] #![deny(missing_docs)] #[macro_use] @@ -13,15 +12,19 @@ extern crate serde; extern crate serde_json; extern crate untrusted; +mod algorithms; mod crypto; -/// All the errors, generated using error-chain +/// All the errors pub mod errors; mod header; +mod keys; mod serialization; mod validation; -pub use crypto::{sign, verify, Algorithm, Der, Hmac, Key, KeyFormat, Pkcs8}; +pub use algorithms::Algorithm; +pub use crypto::{sign, verify}; pub use header::Header; +pub use keys::Key; pub use serialization::TokenData; pub use validation::Validation; @@ -52,9 +55,9 @@ use validation::validate; /// /// // my_claims is a struct that implements Serialize /// // This will create a JWT using HS256 as algorithm -/// let token = encode(&Header::default(), &my_claims, "secret".as_ref()).unwrap(); +/// let token = encode(&Header::default(), &my_claims, Key::Hmac("secret".as_ref())).unwrap(); /// ``` -pub fn encode(header: &Header, claims: &T, key: K) -> Result { +pub fn encode(header: &Header, claims: &T, key: Key) -> Result { let encoded_header = to_jwt_part(&header)?; let encoded_claims = to_jwt_part(&claims)?; let signing_input = [encoded_header.as_ref(), encoded_claims.as_ref()].join("."); @@ -92,11 +95,11 @@ macro_rules! expect_two { /// /// let token = "a.jwt.token".to_string(); /// // Claims is a struct that implements Deserialize -/// let token_data = decode::(&token, "secret", &Validation::new(Algorithm::HS256)); +/// let token_data = decode::(&token, Key::Hmac("secret"), &Validation::new(Algorithm::HS256)); /// ``` pub fn decode( token: &str, - key: &[u8], + key: Key, validation: &Validation, ) -> Result> { let (signature, signing_input) = expect_two!(token.rsplitn(2, '.')); diff --git a/src/validation.rs b/src/validation.rs index 293147a..5798c01 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -3,7 +3,7 @@ use serde::ser::Serialize; use serde_json::map::Map; use serde_json::{from_value, to_value, Value}; -use crypto::Algorithm; +use algorithms::Algorithm; use errors::{new_error, ErrorKind, Result}; /// Contains the various validations that are applied after decoding a token. @@ -78,6 +78,7 @@ impl Validation { /// Since `aud` can be either a String or an array of String in the JWT spec, this method will take /// care of serializing the value. pub fn set_audience(&mut self, audience: &T) { + // TODO: check if the value is a string or an array and error if not self.aud = Some(to_value(audience).unwrap()); } } diff --git a/tests/ecdsa.rs b/tests/ecdsa.rs index 5c1b315..c11c0fd 100644 --- a/tests/ecdsa.rs +++ b/tests/ecdsa.rs @@ -4,7 +4,7 @@ extern crate serde_derive; extern crate chrono; use chrono::Utc; -use jsonwebtoken::{decode, encode, sign, verify, Algorithm, Der, Header, Pkcs8, Validation}; +use jsonwebtoken::{decode, encode, sign, verify, Algorithm, Key, Header, Validation}; #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] struct Claims { @@ -16,9 +16,9 @@ struct Claims { #[test] fn round_trip_sign_verification() { let privkey = include_bytes!("private_ecdsa_key.pk8"); - let encrypted = sign("hello world", Pkcs8::from(&&privkey[..]), Algorithm::ES256).unwrap(); + let encrypted = sign("hello world", Key::Pkcs8(&privkey[..]), Algorithm::ES256).unwrap(); let pubkey = include_bytes!("public_ecdsa_key.pk8"); - let is_valid = verify(&encrypted, "hello world", pubkey, Algorithm::ES256).unwrap(); + let is_valid = verify(&encrypted, "hello world", Key::Pkcs8(pubkey), Algorithm::ES256).unwrap(); assert!(is_valid); } @@ -31,9 +31,9 @@ fn round_trip_claim() { }; let privkey = include_bytes!("private_ecdsa_key.pk8"); let token = - encode(&Header::new(Algorithm::ES256), &my_claims, Pkcs8::from(&&privkey[..])).unwrap(); + encode(&Header::new(Algorithm::ES256), &my_claims, Key::Pkcs8(&privkey[..])).unwrap(); let pubkey = include_bytes!("public_ecdsa_key.pk8"); - let token_data = decode::(&token, pubkey, &Validation::new(Algorithm::ES256)).unwrap(); + let token_data = decode::(&token, Key::Pkcs8(pubkey), &Validation::new(Algorithm::ES256)).unwrap(); assert_eq!(my_claims, token_data.claims); assert!(token_data.header.kid.is_none()); } @@ -42,5 +42,5 @@ fn round_trip_claim() { #[should_panic(expected = "InvalidKeyFormat")] fn fails_with_non_pkcs8_key_format() { let privkey = include_bytes!("private_rsa_key.der"); - let _encrypted = sign("hello world", Der::from(&&privkey[..]), Algorithm::ES256).unwrap(); + let _encrypted = sign("hello world", Key::Der(&privkey[..]), Algorithm::ES256).unwrap(); } diff --git a/tests/lib.rs b/tests/lib.rs index f489477..6a4e328 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -5,7 +5,7 @@ extern crate chrono; use chrono::Utc; use jsonwebtoken::{ - dangerous_unsafe_decode, decode, decode_header, encode, sign, verify, Algorithm, Header, Hmac, + dangerous_unsafe_decode, decode, decode_header, encode, sign, verify, Algorithm, Header, Key, Validation, }; use std::str::FromStr; @@ -19,7 +19,7 @@ struct Claims { #[test] fn sign_hs256() { - let result = sign("hello world", Hmac::from(b"secret"), Algorithm::HS256).unwrap(); + let result = sign("hello world", Key::Hmac(b"secret"), Algorithm::HS256).unwrap(); let expected = "c0zGLzKEFWj0VxWuufTXiRMk5tlI5MbGDAYhzaxIYjo"; assert_eq!(result, expected); } @@ -27,7 +27,7 @@ fn sign_hs256() { #[test] fn verify_hs256() { let sig = "c0zGLzKEFWj0VxWuufTXiRMk5tlI5MbGDAYhzaxIYjo"; - let valid = verify(sig, "hello world", b"secret", Algorithm::HS256).unwrap(); + let valid = verify(sig, "hello world", Key::Hmac(b"secret"), Algorithm::HS256).unwrap(); assert!(valid); } @@ -40,8 +40,8 @@ fn encode_with_custom_header() { }; let mut header = Header::default(); header.kid = Some("kid".to_string()); - let token = encode(&header, &my_claims, Hmac::from(b"secret")).unwrap(); - let token_data = decode::(&token, "secret".as_ref(), &Validation::default()).unwrap(); + let token = encode(&header, &my_claims, Key::Hmac(b"secret")).unwrap(); + let token_data = decode::(&token, Key::Hmac(b"secret"), &Validation::default()).unwrap(); assert_eq!(my_claims, token_data.claims); assert_eq!("kid", token_data.header.kid.unwrap()); } @@ -53,8 +53,8 @@ fn round_trip_claim() { company: "ACME".to_string(), exp: Utc::now().timestamp() + 10000, }; - let token = encode(&Header::default(), &my_claims, Hmac::from(b"secret")).unwrap(); - let token_data = decode::(&token, "secret".as_ref(), &Validation::default()).unwrap(); + let token = encode(&Header::default(), &my_claims, Key::Hmac(b"secret")).unwrap(); + let token_data = decode::(&token, Key::Hmac(b"secret"), &Validation::default()).unwrap(); assert_eq!(my_claims, token_data.claims); assert!(token_data.header.kid.is_none()); } @@ -62,7 +62,7 @@ fn round_trip_claim() { #[test] fn decode_token() { let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.9r56oF7ZliOBlOAyiOFperTGxBtPykRQiWNFxhDCW98"; - let claims = decode::(token, "secret".as_ref(), &Validation::default()); + let claims = decode::(token, Key::Hmac(b"secret"), &Validation::default()); println!("{:?}", claims); claims.unwrap(); } @@ -71,7 +71,7 @@ fn decode_token() { #[should_panic(expected = "InvalidToken")] fn decode_token_missing_parts() { let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"; - let claims = decode::(token, "secret".as_ref(), &Validation::default()); + let claims = decode::(token, Key::Hmac(b"secret"), &Validation::default()); claims.unwrap(); } @@ -80,7 +80,7 @@ fn decode_token_missing_parts() { fn decode_token_invalid_signature() { let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.wrong"; - let claims = decode::(token, "secret".as_ref(), &Validation::default()); + let claims = decode::(token, Key::Hmac(b"secret"), &Validation::default()); claims.unwrap(); } @@ -88,14 +88,14 @@ fn decode_token_invalid_signature() { #[should_panic(expected = "InvalidAlgorithm")] fn decode_token_wrong_algorithm() { let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.I1BvFoHe94AFf09O6tDbcSB8-jp8w6xZqmyHIwPeSdY"; - let claims = decode::(token, "secret".as_ref(), &Validation::new(Algorithm::RS512)); + let claims = decode::(token, Key::Hmac(b"secret"), &Validation::new(Algorithm::RS512)); claims.unwrap(); } #[test] fn decode_token_with_bytes_secret() { let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.Hm0yvKH25TavFPz7J_coST9lZFYH1hQo0tvhvImmaks"; - let claims = decode::(token, b"\x01\x02\x03", &Validation::default()); + let claims = decode::(token, Key::Hmac(b"\x01\x02\x03"), &Validation::default()); assert!(claims.is_ok()); } @@ -144,7 +144,7 @@ fn does_validation_in_right_order() { company: "ACME".to_string(), exp: Utc::now().timestamp() + 10000, }; - let token = encode(&Header::default(), &my_claims, Hmac::from(b"secret")).unwrap(); + let token = encode(&Header::default(), &my_claims, Key::Hmac(b"secret")).unwrap(); let v = Validation { leeway: 5, validate_exp: true, @@ -152,7 +152,7 @@ fn does_validation_in_right_order() { sub: Some("sub no check".to_string()), ..Validation::default() }; - let res = decode::(&token, "secret".as_ref(), &v); + let res = decode::(&token, Key::Hmac(b"secret"), &v); assert!(res.is_err()); println!("{:?}", res); //assert!(res.is_ok()); diff --git a/tests/rsa.rs b/tests/rsa.rs index 4f2111a..20ee7f7 100644 --- a/tests/rsa.rs +++ b/tests/rsa.rs @@ -4,7 +4,7 @@ extern crate serde_derive; extern crate chrono; use chrono::Utc; -use jsonwebtoken::{decode, encode, sign, verify, Algorithm, Der, Header, Pkcs8, Validation}; +use jsonwebtoken::{decode, encode, sign, verify, Algorithm, Key, Header, Validation}; #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] struct Claims { @@ -16,9 +16,9 @@ struct Claims { #[test] fn round_trip_sign_verification() { let privkey = include_bytes!("private_rsa_key.der"); - let encrypted = sign("hello world", Der::from(&&privkey[..]), Algorithm::RS256).unwrap(); + let encrypted = sign("hello world", Key::Der(&privkey[..]), Algorithm::RS256).unwrap(); let is_valid = - verify(&encrypted, "hello world", include_bytes!("public_rsa_key.der"), Algorithm::RS256) + verify(&encrypted, "hello world", Key::Der(include_bytes!("public_rsa_key.der")), Algorithm::RS256) .unwrap(); assert!(is_valid); } @@ -32,10 +32,10 @@ fn round_trip_claim() { }; let privkey = include_bytes!("private_rsa_key.der"); let token = - encode(&Header::new(Algorithm::RS256), &my_claims, Der::from(&&privkey[..])).unwrap(); + encode(&Header::new(Algorithm::RS256), &my_claims, Key::Der(&privkey[..])).unwrap(); let token_data = decode::( &token, - include_bytes!("public_rsa_key.der"), + Key::Der(include_bytes!("public_rsa_key.der")), &Validation::new(Algorithm::RS256), ) .unwrap(); @@ -47,5 +47,5 @@ fn round_trip_claim() { #[should_panic(expected = "InvalidRsaKey")] fn fails_with_different_key_format() { let privkey = include_bytes!("private_rsa_key.der"); - sign("hello world", Pkcs8::from(&&privkey[..]), Algorithm::RS256).unwrap(); + sign("hello world", Key::Pkcs8(&privkey[..]), Algorithm::RS256).unwrap(); }