Skip to content

Commit

Permalink
Add DecodingKey::from_jwk
Browse files Browse the repository at this point in the history
- ref. #260
  • Loading branch information
cduvray authored and Keats committed Dec 3, 2022
1 parent ee5a2dd commit e1e3e66
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/decoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::algorithms::AlgorithmFamily;
use crate::crypto::verify;
use crate::errors::{new_error, ErrorKind, Result};
use crate::header::Header;
use crate::jwk::{AlgorithmParameters, Jwk};
#[cfg(feature = "use_pem")]
use crate::pem::decoder::PemEncodedKey;
use crate::serialization::{b64_decode, DecodedJwtPartClaims};
Expand Down Expand Up @@ -162,6 +163,24 @@ impl DecodingKey {
})
}

/// If you have a key in Jwk format
pub fn from_jwk(jwk: &Jwk) -> Result<Self> {
match jwk.algorithm {
AlgorithmParameters::RSA(ref params) => {
DecodingKey::from_rsa_components(&params.n, &params.e)
}
AlgorithmParameters::EllipticCurve(ref params) => {
DecodingKey::from_ec_components(&params.x, &params.y)
}
AlgorithmParameters::OctetKeyPair(ref params) => {
DecodingKey::from_ed_components(&params.x)
}
AlgorithmParameters::OctetKey(ref params) => {
DecodingKey::from_base64_secret(&params.value)
}
}
}

pub(crate) fn as_bytes(&self) -> &[u8] {
match &self.kind {
DecodingKeyKind::SecretOrDer(b) => b,
Expand Down
37 changes: 37 additions & 0 deletions tests/ecdsa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,43 @@ fn ec_x_y() {
assert!(res.is_ok());
}

#[cfg(feature = "use_pem")]
#[test]
fn ed_jwk() {
use jsonwebtoken::jwk::Jwk;
use serde_json::json;

let privkey = include_str!("private_ecdsa_key.pem");
let my_claims = Claims {
sub: "b@b.com".to_string(),
company: "ACME".to_string(),
exp: OffsetDateTime::now_utc().unix_timestamp() + 10000,
};
let jwk: Jwk = serde_json::from_value(json!({
"kty": "EC",
"crv": "P-256",
"x": "w7JAoU_gJbZJvV-zCOvU9yFJq0FNC_edCMRM78P8eQQ",
"y": "wQg1EytcsEmGrM70Gb53oluoDbVhCZ3Uq3hHMslHVb4",
"kid": "ec01",
"alg": "ES256",
"use": "sig"
}))
.unwrap();

let encrypted = encode(
&Header::new(Algorithm::ES256),
&my_claims,
&EncodingKey::from_ec_pem(privkey.as_ref()).unwrap(),
)
.unwrap();
let res = decode::<Claims>(
&encrypted,
&DecodingKey::from_jwk(&jwk).unwrap(),
&Validation::new(Algorithm::ES256),
);
assert!(res.is_ok());
}

// https://jwt.io/ is often used for examples so ensure their example works with jsonwebtoken
#[cfg(feature = "use_pem")]
#[test]
Expand Down
36 changes: 36 additions & 0 deletions tests/eddsa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,39 @@ fn ed_x() {
);
assert!(res.is_ok());
}

#[cfg(feature = "use_pem")]
#[test]
fn ed_jwk() {
use jsonwebtoken::jwk::Jwk;
use serde_json::json;

let privkey = include_str!("private_ed25519_key.pem");
let my_claims = Claims {
sub: "b@b.com".to_string(),
company: "ACME".to_string(),
exp: OffsetDateTime::now_utc().unix_timestamp() + 10000,
};
let jwk: Jwk = serde_json::from_value(json!({
"kty": "OKP",
"use": "sig",
"crv": "Ed25519",
"x": "2-Jj2UvNCvQiUPNYRgSi0cJSPiJI6Rs6D0UTeEpQVj8",
"kid": "ed01",
"alg": "EdDSA"
}))
.unwrap();

let encrypted = encode(
&Header::new(Algorithm::EdDSA),
&my_claims,
&EncodingKey::from_ed_pem(privkey.as_ref()).unwrap(),
)
.unwrap();
let res = decode::<Claims>(
&encrypted,
&DecodingKey::from_jwk(&jwk).unwrap(),
&Validation::new(Algorithm::EdDSA),
);
assert!(res.is_ok());
}
35 changes: 35 additions & 0 deletions tests/rsa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,41 @@ fn rsa_modulus_exponent() {
assert!(res.is_ok());
}

#[cfg(feature = "use_pem")]
#[test]
fn rsa_jwk() {
use jsonwebtoken::jwk::Jwk;
use serde_json::json;

let privkey = include_str!("private_rsa_key_pkcs8.pem");
let my_claims = Claims {
sub: "b@b.com".to_string(),
company: "ACME".to_string(),
exp: OffsetDateTime::now_utc().unix_timestamp() + 10000,
};
let jwk:Jwk = serde_json::from_value(json!({
"kty": "RSA",
"n": "yRE6rHuNR0QbHO3H3Kt2pOKGVhQqGZXInOduQNxXzuKlvQTLUTv4l4sggh5_CYYi_cvI-SXVT9kPWSKXxJXBXd_4LkvcPuUakBoAkfh-eiFVMh2VrUyWyj3MFl0HTVF9KwRXLAcwkREiS3npThHRyIxuy0ZMeZfxVL5arMhw1SRELB8HoGfG_AtH89BIE9jDBHZ9dLelK9a184zAf8LwoPLxvJb3Il5nncqPcSfKDDodMFBIMc4lQzDKL5gvmiXLXB1AGLm8KBjfE8s3L5xqi-yUod-j8MtvIj812dkS4QMiRVN_by2h3ZY8LYVGrqZXZTcgn2ujn8uKjXLZVD5TdQ",
"e": "AQAB",
"kid": "rsa01",
"alg": "RS256",
"use": "sig"
})).unwrap();

let encrypted = encode(
&Header::new(Algorithm::RS256),
&my_claims,
&EncodingKey::from_rsa_pem(privkey.as_ref()).unwrap(),
)
.unwrap();
let res = decode::<Claims>(
&encrypted,
&DecodingKey::from_jwk(&jwk).unwrap(),
&Validation::new(Algorithm::RS256),
);
assert!(res.is_ok());
}

// https://jwt.io/ is often used for examples so ensure their example works with jsonwebtoken
#[cfg(feature = "use_pem")]
#[test]
Expand Down

0 comments on commit e1e3e66

Please # to comment.