Skip to content

Commit b13535e

Browse files
committed
address comments
1 parent 42c6baa commit b13535e

File tree

5 files changed

+21
-32
lines changed

5 files changed

+21
-32
lines changed

benches/jwt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fn bench_encode_custom_extra_headers(c: &mut Criterion) {
2323
let key = EncodingKey::from_secret("secret".as_ref());
2424
let mut extras = HashMap::with_capacity(1);
2525
extras.insert("custom".to_string(), "header".to_string());
26-
let header = &Header { extras: Some(extras), ..Default::default() };
26+
let header = &Header { extras, ..Default::default() };
2727

2828
c.bench_function("bench_encode", |b| {
2929
b.iter(|| encode(black_box(header), black_box(&claim), black_box(&key)))

examples/custom_header.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn main() {
2222
let header = Header {
2323
kid: Some("signing_key".to_owned()),
2424
alg: Algorithm::HS512,
25-
extras: Some(extras),
25+
extras,
2626
..Default::default()
2727
};
2828

src/crypto/mod.rs

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use ring::constant_time::verify_slices_are_equal;
12
use ring::{hmac, signature};
23

34
use crate::algorithms::Algorithm;
@@ -10,16 +11,6 @@ pub(crate) mod ecdsa;
1011
pub(crate) mod eddsa;
1112
pub(crate) mod rsa;
1213

13-
/// Only used internally when signing/verifying with HMAC, to map from our enum to the Ring HMAC structs.
14-
fn alg_to_hmac(alg: Algorithm) -> hmac::Algorithm {
15-
match alg {
16-
Algorithm::HS256 => hmac::HMAC_SHA256,
17-
Algorithm::HS384 => hmac::HMAC_SHA384,
18-
Algorithm::HS512 => hmac::HMAC_SHA512,
19-
_ => unreachable!("Tried to get HMAC alg for a non-HMAC algorithm"),
20-
}
21-
}
22-
2314
/// The actual HS signing + encoding
2415
/// Could be in its own file to match RSA/EC but it's 2 lines...
2516
pub(crate) fn sign_hmac(alg: hmac::Algorithm, key: &[u8], message: &[u8]) -> String {
@@ -33,9 +24,9 @@ pub(crate) fn sign_hmac(alg: hmac::Algorithm, key: &[u8], message: &[u8]) -> Str
3324
/// If you just want to encode a JWT, use `encode` instead.
3425
pub fn sign(message: &[u8], key: &EncodingKey, algorithm: Algorithm) -> Result<String> {
3526
match algorithm {
36-
Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => {
37-
Ok(sign_hmac(alg_to_hmac(algorithm), key.inner(), message))
38-
}
27+
Algorithm::HS256 => Ok(sign_hmac(hmac::HMAC_SHA256, key.inner(), message)),
28+
Algorithm::HS384 => Ok(sign_hmac(hmac::HMAC_SHA384, key.inner(), message)),
29+
Algorithm::HS512 => Ok(sign_hmac(hmac::HMAC_SHA512, key.inner(), message)),
3930

4031
Algorithm::ES256 | Algorithm::ES384 => {
4132
ecdsa::sign(ecdsa::alg_to_ec_signing(algorithm), key.inner(), message)
@@ -83,10 +74,8 @@ pub fn verify(
8374
match algorithm {
8475
Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => {
8576
// we just re-sign the message with the key and compare if they are equal
86-
let encoding_key = &EncodingKey::from_secret(key.as_bytes());
87-
let key = &hmac::Key::new(alg_to_hmac(algorithm), encoding_key.inner());
88-
let digest = hmac::sign(key, message);
89-
Ok(hmac::verify(key, message, digest.as_ref()).is_ok())
77+
let signed = sign(message, &EncodingKey::from_secret(key.as_bytes()), algorithm)?;
78+
Ok(verify_slices_are_equal(signature.as_ref(), signed.as_ref()).is_ok())
9079
}
9180
Algorithm::ES256 | Algorithm::ES384 => verify_ring(
9281
ecdsa::alg_to_ec_verification(algorithm),

src/header.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,8 @@ pub struct Header {
6969
/// Any additional non-standard headers not defined in [RFC7515#4.1](https://datatracker.ietf.org/doc/html/rfc7515#section-4.1).
7070
/// Once serialized, all keys will be converted to fields at the root level of the header payload
7171
/// Ex: Dict("custom" -> "header") will be converted to "{"typ": "JWT", ..., "custom": "header"}"
72-
#[serde(skip_serializing_if = "Option::is_none")]
7372
#[serde(flatten)]
74-
pub extras: Option<HashMap<String, String>>,
73+
pub extras: HashMap<String, String>,
7574
}
7675

7776
impl Header {
@@ -88,7 +87,7 @@ impl Header {
8887
x5c: None,
8988
x5t: None,
9089
x5t_s256: None,
91-
extras: None,
90+
extras: Default::default(),
9291
}
9392
}
9493

tests/hmac.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ fn encode_with_custom_header() {
5252
.unwrap();
5353
assert_eq!(my_claims, token_data.claims);
5454
assert_eq!("kid", token_data.header.kid.unwrap());
55+
assert!(token_data.header.extras.is_empty());
5556
}
5657

5758
#[test]
@@ -62,9 +63,9 @@ fn encode_with_extra_custom_header() {
6263
company: "ACME".to_string(),
6364
exp: OffsetDateTime::now_utc().unix_timestamp() + 10000,
6465
};
65-
let mut extra = HashMap::with_capacity(1);
66-
extra.insert("custom".to_string(), "header".to_string());
67-
let header = Header { kid: Some("kid".to_string()), extras: Some(extra), ..Default::default() };
66+
let mut extras = HashMap::with_capacity(1);
67+
extras.insert("custom".to_string(), "header".to_string());
68+
let header = Header { kid: Some("kid".to_string()), extras, ..Default::default() };
6869
let token = encode(&header, &my_claims, &EncodingKey::from_secret(b"secret")).unwrap();
6970
let token_data = decode::<Claims>(
7071
&token,
@@ -74,7 +75,7 @@ fn encode_with_extra_custom_header() {
7475
.unwrap();
7576
assert_eq!(my_claims, token_data.claims);
7677
assert_eq!("kid", token_data.header.kid.unwrap());
77-
assert_eq!("header", token_data.header.extras.unwrap().get("custom").unwrap().as_str());
78+
assert_eq!("header", token_data.header.extras.get("custom").unwrap().as_str());
7879
}
7980

8081
#[test]
@@ -85,10 +86,10 @@ fn encode_with_multiple_extra_custom_headers() {
8586
company: "ACME".to_string(),
8687
exp: OffsetDateTime::now_utc().unix_timestamp() + 10000,
8788
};
88-
let mut extra = HashMap::with_capacity(1);
89-
extra.insert("custom1".to_string(), "header1".to_string());
90-
extra.insert("custom2".to_string(), "header2".to_string());
91-
let header = Header { kid: Some("kid".to_string()), extras: Some(extra), ..Default::default() };
89+
let mut extras = HashMap::with_capacity(2);
90+
extras.insert("custom1".to_string(), "header1".to_string());
91+
extras.insert("custom2".to_string(), "header2".to_string());
92+
let header = Header { kid: Some("kid".to_string()), extras, ..Default::default() };
9293
let token = encode(&header, &my_claims, &EncodingKey::from_secret(b"secret")).unwrap();
9394
let token_data = decode::<Claims>(
9495
&token,
@@ -98,7 +99,7 @@ fn encode_with_multiple_extra_custom_headers() {
9899
.unwrap();
99100
assert_eq!(my_claims, token_data.claims);
100101
assert_eq!("kid", token_data.header.kid.unwrap());
101-
let extras = token_data.header.extras.unwrap();
102+
let extras = token_data.header.extras;
102103
assert_eq!("header1", extras.get("custom1").unwrap().as_str());
103104
assert_eq!("header2", extras.get("custom2").unwrap().as_str());
104105
}
@@ -151,7 +152,7 @@ fn decode_token_missing_parts() {
151152

152153
#[test]
153154
#[wasm_bindgen_test]
154-
#[should_panic(expected = "missing field `exp`")]
155+
#[should_panic(expected = "InvalidSignature")]
155156
fn decode_token_invalid_signature() {
156157
let token =
157158
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.wrong";

0 commit comments

Comments
 (0)