Add EncodingKey
This commit is contained in:
parent
771f955690
commit
0abeeac25f
|
@ -38,7 +38,7 @@ Complete examples are available in the examples directory: a basic one and one w
|
|||
In terms of imports and structs:
|
||||
```rust
|
||||
use serde::{Serialize, Deserialize};
|
||||
use jsonwebtoken::{encode, decode, Header, Algorithm, Validation};
|
||||
use jsonwebtoken::{encode, decode, Header, Algorithm, Validation, EncodingKey};
|
||||
|
||||
/// Our claims struct, it needs to derive `Serialize` and/or `Deserialize`
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
@ -53,7 +53,7 @@ struct Claims {
|
|||
The default algorithm is HS256, which uses a shared secret.
|
||||
|
||||
```rust
|
||||
let token = encode(&Header::default(), &my_claims, "secret".as_ref())?;
|
||||
let token = encode(&Header::default(), &my_claims, &EncodingKey::from_secret("secret".as_ref()))?;
|
||||
```
|
||||
|
||||
#### Custom headers & changing algorithm
|
||||
|
@ -63,7 +63,7 @@ If you want to set the `kid` parameter or change the algorithm for example:
|
|||
```rust
|
||||
let mut header = Header::new(Algorithm::HS512);
|
||||
header.kid = Some("blabla".to_owned());
|
||||
let token = encode(&header, &my_claims, "secret".as_ref())?;
|
||||
let token = encode(&header, &my_claims, &EncodingKey::from_secret("secret".as_ref()))?;
|
||||
```
|
||||
Look at `examples/custom_header.rs` for a full working example.
|
||||
|
||||
|
@ -71,7 +71,7 @@ Look at `examples/custom_header.rs` for a full working example.
|
|||
|
||||
```rust
|
||||
// HS256
|
||||
let token = encode(&Header::default(), &my_claims, "secret".as_ref())?;
|
||||
let token = encode(&Header::default(), &my_claims, &EncodingKey::from_secret("secret".as_ref()))?;
|
||||
// RSA
|
||||
let token = encode(&Header::new(Algorithm::RS256), &my_claims, include_str!("privkey.pem"))?;
|
||||
```
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use chrono::prelude::*;
|
||||
use jsonwebtoken::{Header, Validation};
|
||||
use jsonwebtoken::{EncodingKey, Header, Validation};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
const SECRET: &str = "some-secret";
|
||||
|
@ -51,8 +51,9 @@ mod jwt_numeric_date {
|
|||
|
||||
let claims = Claims { sub: sub.clone(), iat, exp };
|
||||
|
||||
let token = encode(&Header::default(), &claims, SECRET.as_ref())
|
||||
.expect("Failed to encode claims");
|
||||
let token =
|
||||
encode(&Header::default(), &claims, &EncodingKey::from_secret(SECRET.as_ref()))
|
||||
.expect("Failed to encode claims");
|
||||
|
||||
assert_eq!(&token, EXPECTED_TOKEN);
|
||||
|
||||
|
@ -82,7 +83,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
|
||||
let claims = Claims { sub: sub.clone(), iat, exp };
|
||||
|
||||
let token = jsonwebtoken::encode(&Header::default(), &claims, SECRET.as_ref())?;
|
||||
let token = jsonwebtoken::encode(
|
||||
&Header::default(),
|
||||
&claims,
|
||||
&EncodingKey::from_secret(SECRET.as_ref()),
|
||||
)?;
|
||||
|
||||
println!("serialized token: {}", &token);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use jsonwebtoken::errors::ErrorKind;
|
||||
use jsonwebtoken::{decode, encode, Algorithm, Header, Validation};
|
||||
use jsonwebtoken::{decode, encode, Algorithm, EncodingKey, Header, Validation};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct Claims {
|
||||
|
@ -19,7 +19,7 @@ fn main() {
|
|||
header.kid = Some("signing_key".to_owned());
|
||||
header.alg = Algorithm::HS512;
|
||||
|
||||
let token = match encode(&header, &my_claims, key) {
|
||||
let token = match encode(&header, &my_claims, &EncodingKey::from_secret(key)) {
|
||||
Ok(t) => t,
|
||||
Err(_) => panic!(), // in practice you would return the error
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use jsonwebtoken::errors::ErrorKind;
|
||||
use jsonwebtoken::{decode, encode, Header, Validation};
|
||||
use jsonwebtoken::{decode, encode, EncodingKey, Header, Validation};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
@ -10,10 +10,10 @@ struct Claims {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let key = b"secret";
|
||||
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, key) {
|
||||
let token = match encode(&Header::default(), &my_claims, &EncodingKey::from_secret(key)) {
|
||||
Ok(t) => t,
|
||||
Err(_) => panic!(), // in practice you would return the error
|
||||
};
|
||||
|
|
|
@ -2,7 +2,6 @@ use ring::{rand, signature};
|
|||
|
||||
use crate::algorithms::Algorithm;
|
||||
use crate::errors::Result;
|
||||
use crate::pem::decoder::PemEncodedKey;
|
||||
use crate::serialization::b64_encode;
|
||||
|
||||
/// Only used internally when validating EC, to map from our enum to the Ring EcdsaVerificationAlgorithm structs.
|
||||
|
@ -26,13 +25,13 @@ pub(crate) fn alg_to_ec_signing(alg: Algorithm) -> &'static signature::EcdsaSign
|
|||
}
|
||||
|
||||
/// The actual ECDSA signing + encoding
|
||||
/// The key needs to be in PKCS8 format
|
||||
pub fn sign(
|
||||
alg: &'static signature::EcdsaSigningAlgorithm,
|
||||
key: &[u8],
|
||||
message: &str,
|
||||
) -> Result<String> {
|
||||
let pem_key = PemEncodedKey::new(key)?;
|
||||
let signing_key = signature::EcdsaKeyPair::from_pkcs8(alg, pem_key.as_ec_private_key()?)?;
|
||||
let signing_key = signature::EcdsaKeyPair::from_pkcs8(alg, key)?;
|
||||
let rng = rand::SystemRandom::new();
|
||||
let out = signing_key.sign(&rng, message.as_bytes())?;
|
||||
Ok(b64_encode(out.as_ref()))
|
||||
|
|
|
@ -2,6 +2,7 @@ use ring::constant_time::verify_slices_are_equal;
|
|||
use ring::{hmac, signature};
|
||||
|
||||
use crate::algorithms::Algorithm;
|
||||
use crate::encoding::EncodingKey;
|
||||
use crate::errors::Result;
|
||||
use crate::pem::decoder::PemEncodedKey;
|
||||
use crate::serialization::{b64_decode, b64_encode};
|
||||
|
@ -20,16 +21,14 @@ pub(crate) fn sign_hmac(alg: hmac::Algorithm, key: &[u8], message: &str) -> Resu
|
|||
/// the base64 url safe encoded of the result.
|
||||
///
|
||||
/// If you just want to encode a JWT, use `encode` instead.
|
||||
///
|
||||
/// `key` is the secret for HMAC and a pem encoded string otherwise
|
||||
pub fn sign(message: &str, key: &[u8], algorithm: Algorithm) -> Result<String> {
|
||||
pub fn sign(message: &str, key: &EncodingKey, algorithm: Algorithm) -> Result<String> {
|
||||
match algorithm {
|
||||
Algorithm::HS256 => sign_hmac(hmac::HMAC_SHA256, key, message),
|
||||
Algorithm::HS384 => sign_hmac(hmac::HMAC_SHA384, key, message),
|
||||
Algorithm::HS512 => sign_hmac(hmac::HMAC_SHA512, key, message),
|
||||
Algorithm::HS256 => sign_hmac(hmac::HMAC_SHA256, key.inner(), message),
|
||||
Algorithm::HS384 => sign_hmac(hmac::HMAC_SHA384, key.inner(), message),
|
||||
Algorithm::HS512 => sign_hmac(hmac::HMAC_SHA512, key.inner(), message),
|
||||
|
||||
Algorithm::ES256 | Algorithm::ES384 => {
|
||||
ecdsa::sign(ecdsa::alg_to_ec_signing(algorithm), key, message)
|
||||
ecdsa::sign(ecdsa::alg_to_ec_signing(algorithm), key.inner(), message)
|
||||
}
|
||||
|
||||
Algorithm::RS256
|
||||
|
@ -37,7 +36,7 @@ pub fn sign(message: &str, key: &[u8], algorithm: Algorithm) -> Result<String> {
|
|||
| Algorithm::RS512
|
||||
| Algorithm::PS256
|
||||
| Algorithm::PS384
|
||||
| Algorithm::PS512 => rsa::sign(rsa::alg_to_rsa_signing(algorithm), key, message),
|
||||
| Algorithm::PS512 => rsa::sign(rsa::alg_to_rsa_signing(algorithm), key.inner(), message),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +68,7 @@ pub fn verify(signature: &str, message: &str, key: &[u8], algorithm: Algorithm)
|
|||
match algorithm {
|
||||
Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => {
|
||||
// we just re-sign the message with the key and compare if they are equal
|
||||
let signed = sign(message, key, algorithm)?;
|
||||
let signed = sign(message, &EncodingKey::from_secret(key), algorithm)?;
|
||||
Ok(verify_slices_are_equal(signature.as_ref(), signed.as_ref()).is_ok())
|
||||
}
|
||||
Algorithm::ES256 | Algorithm::ES384 => {
|
||||
|
|
|
@ -3,7 +3,6 @@ use simple_asn1::BigUint;
|
|||
|
||||
use crate::algorithms::Algorithm;
|
||||
use crate::errors::{ErrorKind, Result};
|
||||
use crate::pem::decoder::PemEncodedKey;
|
||||
use crate::serialization::{b64_decode, b64_encode};
|
||||
|
||||
/// Only used internally when validating RSA, to map from our enum to the Ring param structs.
|
||||
|
@ -33,15 +32,14 @@ pub(crate) fn alg_to_rsa_signing(alg: Algorithm) -> &'static dyn signature::RsaE
|
|||
}
|
||||
|
||||
/// The actual RSA signing + encoding
|
||||
/// The key needs to be in PKCS8 format
|
||||
/// Taken from Ring doc https://briansmith.org/rustdoc/ring/signature/index.html
|
||||
pub(crate) fn sign(
|
||||
alg: &'static dyn signature::RsaEncoding,
|
||||
key: &[u8],
|
||||
message: &str,
|
||||
) -> Result<String> {
|
||||
let pem_key = PemEncodedKey::new(key)?;
|
||||
let key_pair = signature::RsaKeyPair::from_der(pem_key.as_rsa_key()?)
|
||||
.map_err(|_| ErrorKind::InvalidRsaKey)?;
|
||||
let key_pair = signature::RsaKeyPair::from_der(key).map_err(|_| ErrorKind::InvalidRsaKey)?;
|
||||
|
||||
let mut signature = vec![0; key_pair.public_modulus_len()];
|
||||
let rng = rand::SystemRandom::new();
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use serde::ser::Serialize;
|
||||
|
||||
use crate::crypto;
|
||||
use crate::errors::Result;
|
||||
use crate::header::Header;
|
||||
use crate::pem::decoder::PemEncodedKey;
|
||||
use crate::serialization::b64_encode_part;
|
||||
|
||||
/// A key to encode a JWT with. Can be a secret, a PEM-encoded key or a DER-encoded key.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct EncodingKey<'a> {
|
||||
content: Cow<'a, [u8]>,
|
||||
}
|
||||
|
||||
impl<'a> EncodingKey<'a> {
|
||||
/// If you're using HMAC, use that.
|
||||
pub fn from_secret(secret: &'a [u8]) -> Self {
|
||||
EncodingKey { content: Cow::Borrowed(secret) }
|
||||
}
|
||||
|
||||
/// If you are loading a RSA key from a .pem file
|
||||
/// This errors if the key is not a valid RSA key
|
||||
pub fn from_rsa_pem(key: &'a [u8]) -> Result<Self> {
|
||||
let pem_key = PemEncodedKey::new(key)?;
|
||||
let content = pem_key.as_rsa_key()?;
|
||||
Ok(EncodingKey { content: Cow::Owned(content.to_vec()) })
|
||||
}
|
||||
|
||||
/// If you are loading a ECDSA key from a .pem file
|
||||
/// This errors if the key is not a valid private EC key
|
||||
pub fn from_ec_pem(key: &'a [u8]) -> Result<Self> {
|
||||
let pem_key = PemEncodedKey::new(key)?;
|
||||
let content = pem_key.as_ec_private_key()?;
|
||||
Ok(EncodingKey { content: Cow::Owned(content.to_vec()) })
|
||||
}
|
||||
|
||||
/// If you know what you're doing and have the DER-encoded key, for RSA or ECDSA
|
||||
pub fn from_der(der: &'a [u8]) -> Self {
|
||||
EncodingKey { content: Cow::Borrowed(der) }
|
||||
}
|
||||
|
||||
/// Access the key, normal users do not need to use that.
|
||||
pub fn inner(&'a self) -> &'a [u8] {
|
||||
&self.content
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode the header and claims given and sign the payload using the algorithm from the header and the key.
|
||||
/// If the algorithm given is RSA or EC, the key needs to be in the PEM format.
|
||||
///
|
||||
/// ```rust
|
||||
/// use serde::{Deserialize, Serialize};
|
||||
/// use jsonwebtoken::{encode, Algorithm, Header, EncodingKey};
|
||||
///
|
||||
/// #[derive(Debug, Serialize, Deserialize)]
|
||||
/// struct Claims {
|
||||
/// sub: String,
|
||||
/// company: String
|
||||
/// }
|
||||
///
|
||||
/// let my_claims = Claims {
|
||||
/// sub: "b@b.com".to_owned(),
|
||||
/// company: "ACME".to_owned()
|
||||
/// };
|
||||
///
|
||||
/// // my_claims is a struct that implements Serialize
|
||||
/// // This will create a JWT using HS256 as algorithm
|
||||
/// let token = encode(&Header::default(), &my_claims, &EncodingKey::from_secret("secret".as_ref())).unwrap();
|
||||
/// ```
|
||||
pub fn encode<T: Serialize>(header: &Header, claims: &T, key: &EncodingKey) -> Result<String> {
|
||||
let encoded_header = b64_encode_part(&header)?;
|
||||
let encoded_claims = b64_encode_part(&claims)?;
|
||||
let message = [encoded_header.as_ref(), encoded_claims.as_ref()].join(".");
|
||||
let signature = crypto::sign(&*message, key, header.alg)?;
|
||||
|
||||
Ok([message, signature].join("."))
|
||||
}
|
38
src/lib.rs
38
src/lib.rs
|
@ -7,6 +7,7 @@ mod algorithms;
|
|||
/// Lower level functions, if you want to do something other than JWTs
|
||||
pub mod crypto;
|
||||
mod decoding;
|
||||
mod encoding;
|
||||
/// All the errors that can be encountered while encoding/decoding JWTs
|
||||
pub mod errors;
|
||||
mod header;
|
||||
|
@ -18,41 +19,6 @@ pub use algorithms::Algorithm;
|
|||
pub use decoding::{
|
||||
dangerous_unsafe_decode, decode, decode_header, decode_rsa_components, TokenData,
|
||||
};
|
||||
pub use encoding::{encode, EncodingKey};
|
||||
pub use header::Header;
|
||||
pub use validation::Validation;
|
||||
|
||||
use serde::ser::Serialize;
|
||||
|
||||
use crate::errors::Result;
|
||||
use crate::serialization::b64_encode_part;
|
||||
|
||||
/// Encode the header and claims given and sign the payload using the algorithm from the header and the key.
|
||||
/// If the algorithm given is RSA or EC, the key needs to be in the PEM format.
|
||||
///
|
||||
/// ```rust
|
||||
/// use serde::{Deserialize, Serialize};
|
||||
/// use jsonwebtoken::{encode, Algorithm, Header};
|
||||
///
|
||||
/// #[derive(Debug, Serialize, Deserialize)]
|
||||
/// struct Claims {
|
||||
/// sub: String,
|
||||
/// company: String
|
||||
/// }
|
||||
///
|
||||
/// let my_claims = Claims {
|
||||
/// sub: "b@b.com".to_owned(),
|
||||
/// company: "ACME".to_owned()
|
||||
/// };
|
||||
///
|
||||
/// // 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();
|
||||
/// ```
|
||||
pub fn encode<T: Serialize>(header: &Header, claims: &T, key: &[u8]) -> Result<String> {
|
||||
let encoded_header = b64_encode_part(&header)?;
|
||||
let encoded_claims = b64_encode_part(&claims)?;
|
||||
let message = [encoded_header.as_ref(), encoded_claims.as_ref()].join(".");
|
||||
let signature = crypto::sign(&*message, key, header.alg)?;
|
||||
|
||||
Ok([message, signature].join("."))
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ pub fn validate(claims: &Map<String, Value>, options: &Validation) -> Result<()>
|
|||
return Err(new_error(ErrorKind::InvalidAudience));
|
||||
}
|
||||
}
|
||||
_ => return Err(new_error(ErrorKind::InvalidAudience))
|
||||
_ => return Err(new_error(ErrorKind::InvalidAudience)),
|
||||
};
|
||||
} else {
|
||||
return Err(new_error(ErrorKind::InvalidAudience));
|
||||
|
@ -447,17 +447,17 @@ mod tests {
|
|||
#[test]
|
||||
fn aud_use_validation_struct() {
|
||||
let mut claims = Map::new();
|
||||
claims.insert("aud".to_string(), to_value("my-googleclientid1234.apps.googleusercontent.com").unwrap());
|
||||
claims.insert(
|
||||
"aud".to_string(),
|
||||
to_value("my-googleclientid1234.apps.googleusercontent.com").unwrap(),
|
||||
);
|
||||
|
||||
let aud = "my-googleclientid1234.apps.googleusercontent.com".to_string();
|
||||
let mut aud_hashset = std::collections::HashSet::new();
|
||||
aud_hashset.insert(aud);
|
||||
|
||||
let validation = Validation {
|
||||
aud: Some(aud_hashset),
|
||||
validate_exp: false,
|
||||
..Validation::default()
|
||||
};
|
||||
let validation =
|
||||
Validation { aud: Some(aud_hashset), validate_exp: false, ..Validation::default() };
|
||||
let res = validate(&claims, &validation);
|
||||
println!("{:?}", res);
|
||||
assert!(res.is_ok());
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use chrono::Utc;
|
||||
use jsonwebtoken::{
|
||||
crypto::{sign, verify},
|
||||
decode, encode, Algorithm, Header, Validation,
|
||||
decode, encode, Algorithm, EncodingKey, Header, Validation,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -26,7 +26,8 @@ pub struct Claims {
|
|||
fn round_trip_sign_verification_pem() {
|
||||
let privkey = include_bytes!("private_ecdsa_key.pem");
|
||||
let pubkey = include_bytes!("public_ecdsa_key.pem");
|
||||
let encrypted = sign("hello world", privkey, Algorithm::ES256).unwrap();
|
||||
let encrypted =
|
||||
sign("hello world", &EncodingKey::from_ec_pem(privkey).unwrap(), Algorithm::ES256).unwrap();
|
||||
let is_valid = verify(&encrypted, "hello world", pubkey, Algorithm::ES256).unwrap();
|
||||
assert!(is_valid);
|
||||
}
|
||||
|
@ -40,7 +41,12 @@ fn round_trip_claim() {
|
|||
company: "ACME".to_string(),
|
||||
exp: Utc::now().timestamp() + 10000,
|
||||
};
|
||||
let token = encode(&Header::new(Algorithm::ES256), &my_claims, privkey).unwrap();
|
||||
let token = encode(
|
||||
&Header::new(Algorithm::ES256),
|
||||
&my_claims,
|
||||
&EncodingKey::from_ec_pem(privkey).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let token_data = decode::<Claims>(&token, pubkey, &Validation::new(Algorithm::ES256)).unwrap();
|
||||
assert_eq!(my_claims, token_data.claims);
|
||||
}
|
||||
|
@ -56,7 +62,12 @@ fn roundtrip_with_jwtio_example() {
|
|||
company: "ACME".to_string(),
|
||||
exp: Utc::now().timestamp() + 10000,
|
||||
};
|
||||
let token = encode(&Header::new(Algorithm::ES384), &my_claims, privkey).unwrap();
|
||||
let token = encode(
|
||||
&Header::new(Algorithm::ES384),
|
||||
&my_claims,
|
||||
&EncodingKey::from_ec_pem(privkey).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let token_data = decode::<Claims>(&token, pubkey, &Validation::new(Algorithm::ES384)).unwrap();
|
||||
assert_eq!(my_claims, token_data.claims);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use chrono::Utc;
|
||||
use jsonwebtoken::{
|
||||
crypto::{sign, verify},
|
||||
dangerous_unsafe_decode, decode, decode_header, encode, Algorithm, Header, Validation,
|
||||
dangerous_unsafe_decode, decode, decode_header, encode, Algorithm, EncodingKey, Header,
|
||||
Validation,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -14,7 +15,8 @@ pub struct Claims {
|
|||
|
||||
#[test]
|
||||
fn sign_hs256() {
|
||||
let result = sign("hello world", b"secret", Algorithm::HS256).unwrap();
|
||||
let result =
|
||||
sign("hello world", &EncodingKey::from_secret(b"secret"), Algorithm::HS256).unwrap();
|
||||
let expected = "c0zGLzKEFWj0VxWuufTXiRMk5tlI5MbGDAYhzaxIYjo";
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
@ -35,7 +37,7 @@ fn encode_with_custom_header() {
|
|||
};
|
||||
let mut header = Header::default();
|
||||
header.kid = Some("kid".to_string());
|
||||
let token = encode(&header, &my_claims, b"secret").unwrap();
|
||||
let token = encode(&header, &my_claims, &EncodingKey::from_secret(b"secret")).unwrap();
|
||||
let token_data = decode::<Claims>(&token, b"secret", &Validation::default()).unwrap();
|
||||
assert_eq!(my_claims, token_data.claims);
|
||||
assert_eq!("kid", token_data.header.kid.unwrap());
|
||||
|
@ -48,7 +50,8 @@ fn round_trip_claim() {
|
|||
company: "ACME".to_string(),
|
||||
exp: Utc::now().timestamp() + 10000,
|
||||
};
|
||||
let token = encode(&Header::default(), &my_claims, b"secret").unwrap();
|
||||
let token =
|
||||
encode(&Header::default(), &my_claims, &EncodingKey::from_secret(b"secret")).unwrap();
|
||||
let token_data = decode::<Claims>(&token, b"secret", &Validation::default()).unwrap();
|
||||
assert_eq!(my_claims, token_data.claims);
|
||||
assert!(token_data.header.kid.is_none());
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use chrono::Utc;
|
||||
use jsonwebtoken::{
|
||||
crypto::{sign, verify},
|
||||
decode, decode_rsa_components, encode, Algorithm, Header, Validation,
|
||||
decode, decode_rsa_components, encode, Algorithm, EncodingKey, Header, Validation,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -27,7 +27,8 @@ fn round_trip_sign_verification_pem_pkcs1() {
|
|||
let pubkey_pem = include_bytes!("public_rsa_key_pkcs1.pem");
|
||||
|
||||
for &alg in RSA_ALGORITHMS {
|
||||
let encrypted = sign("hello world", privkey_pem, alg).unwrap();
|
||||
let encrypted =
|
||||
sign("hello world", &EncodingKey::from_rsa_pem(privkey_pem).unwrap(), alg).unwrap();
|
||||
let is_valid = verify(&encrypted, "hello world", pubkey_pem, alg).unwrap();
|
||||
assert!(is_valid);
|
||||
}
|
||||
|
@ -39,7 +40,8 @@ fn round_trip_sign_verification_pem_pkcs8() {
|
|||
let pubkey_pem = include_bytes!("public_rsa_key_pkcs8.pem");
|
||||
|
||||
for &alg in RSA_ALGORITHMS {
|
||||
let encrypted = sign("hello world", privkey_pem, alg).unwrap();
|
||||
let encrypted =
|
||||
sign("hello world", &EncodingKey::from_rsa_pem(privkey_pem).unwrap(), alg).unwrap();
|
||||
let is_valid = verify(&encrypted, "hello world", pubkey_pem, alg).unwrap();
|
||||
assert!(is_valid);
|
||||
}
|
||||
|
@ -55,7 +57,9 @@ fn round_trip_claim() {
|
|||
let privkey = include_bytes!("private_rsa_key_pkcs1.pem");
|
||||
|
||||
for &alg in RSA_ALGORITHMS {
|
||||
let token = encode(&Header::new(alg), &my_claims, privkey).unwrap();
|
||||
let token =
|
||||
encode(&Header::new(alg), &my_claims, &EncodingKey::from_rsa_pem(privkey).unwrap())
|
||||
.unwrap();
|
||||
let token_data = decode::<Claims>(
|
||||
&token,
|
||||
include_bytes!("public_rsa_key_pkcs1.pem"),
|
||||
|
@ -78,18 +82,16 @@ fn rsa_modulus_exponent() {
|
|||
let n = "yRE6rHuNR0QbHO3H3Kt2pOKGVhQqGZXInOduQNxXzuKlvQTLUTv4l4sggh5_CYYi_cvI-SXVT9kPWSKXxJXBXd_4LkvcPuUakBoAkfh-eiFVMh2VrUyWyj3MFl0HTVF9KwRXLAcwkREiS3npThHRyIxuy0ZMeZfxVL5arMhw1SRELB8HoGfG_AtH89BIE9jDBHZ9dLelK9a184zAf8LwoPLxvJb3Il5nncqPcSfKDDodMFBIMc4lQzDKL5gvmiXLXB1AGLm8KBjfE8s3L5xqi-yUod-j8MtvIj812dkS4QMiRVN_by2h3ZY8LYVGrqZXZTcgn2ujn8uKjXLZVD5TdQ";
|
||||
let e = "AQAB";
|
||||
|
||||
let encrypted = encode(&Header::new(Algorithm::RS256), &my_claims, privkey.as_ref()).unwrap();
|
||||
let encrypted = encode(
|
||||
&Header::new(Algorithm::RS256),
|
||||
&my_claims,
|
||||
&EncodingKey::from_rsa_pem(privkey.as_ref()).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let res = decode_rsa_components::<Claims>(&encrypted, n, e, &Validation::new(Algorithm::RS256));
|
||||
assert!(res.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "InvalidKeyFormat")]
|
||||
fn fails_with_non_pkcs8_key_format() {
|
||||
let _encrypted =
|
||||
sign("hello world", include_bytes!("private_rsa_key_pkcs1.pem"), Algorithm::ES256).unwrap();
|
||||
}
|
||||
|
||||
// https://jwt.io/ is often used for examples so ensure their example works with jsonwebtoken
|
||||
#[test]
|
||||
fn roundtrip_with_jwtio_example_jey() {
|
||||
|
@ -103,7 +105,9 @@ fn roundtrip_with_jwtio_example_jey() {
|
|||
};
|
||||
|
||||
for &alg in RSA_ALGORITHMS {
|
||||
let token = encode(&Header::new(alg), &my_claims, privkey_pem).unwrap();
|
||||
let token =
|
||||
encode(&Header::new(alg), &my_claims, &EncodingKey::from_rsa_pem(privkey_pem).unwrap())
|
||||
.unwrap();
|
||||
let token_data = decode::<Claims>(&token, pubkey_pem, &Validation::new(alg)).unwrap();
|
||||
assert_eq!(my_claims, token_data.claims);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue