Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "compact_jwt"
version = "0.5.6"
version = "0.5.7"
edition = "2021"
authors = ["William Brown <william@blackhats.net.au>"]
description = "Minimal implementation of JWT for OIDC and other applications"
Expand Down
54 changes: 51 additions & 3 deletions src/crypto/a256kw.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
use crate::compact::{JweAlg, JweCompact, JweProtectedHeader};
use crate::jwe::Jwe;
use crate::traits::*;
use crate::JwtError;
use crate::{JwtError, KID_LEN};
use crypto_glue::{
aes256::{self, Aes256Key},
aes256kw::{Aes256Kw, Aes256KwWrapped},
hmac_s256::{HmacSha256, HmacSha256Key},
traits::Mac,
};

/// A JWE outer encipher and decipher for RFC3394 AES 256 Key Wrapping.
#[derive(Clone)]
pub struct JweA256KWEncipher {
kid: Option<String>,
wrap_key: Aes256Key,
}

impl From<Aes256Key> for JweA256KWEncipher {
fn from(wrap_key: Aes256Key) -> Self {
JweA256KWEncipher { wrap_key }
JweA256KWEncipher {
wrap_key,
kid: None,
}
}
}

Expand All @@ -28,6 +34,8 @@ impl AsRef<Aes256Key> for JweA256KWEncipher {
impl JweEncipherOuterA256 for JweA256KWEncipher {
fn set_header_alg(&self, hdr: &mut JweProtectedHeader) -> Result<(), JwtError> {
hdr.alg = JweAlg::A256KW;
// KeyID is an option, so only embeds if present.
hdr.kid = self.kid.clone();
Ok(())
}

Expand All @@ -50,7 +58,31 @@ impl JweA256KWEncipher {
/// Generate an ephemeral outer key.
pub fn generate_ephemeral() -> Result<Self, JwtError> {
let wrap_key = aes256::new_key();
Ok(JweA256KWEncipher { wrap_key })
Ok(JweA256KWEncipher {
wrap_key,
kid: None,
})
}

/// Set the key identifier for this wrapping key.
pub fn set_kid(&mut self, kid: Option<String>) {
self.kid = kid;
}

/// Enable or disable the embeddidng of a key id during encryption
pub fn set_sign_option_embed_kid(&mut self, value: bool) {
if value {
if self.kid.is_none() {
self.kid = Some(kid(&self.wrap_key));
}
} else {
self.kid = None
}
}

/// Generate and return a key identifier for this wrapping key
pub fn get_kid(&self) -> String {
self.kid.clone().unwrap_or_else(|| kid(&self.wrap_key))
}

/// Given a JWE, encipher its content to a compact form.
Expand Down Expand Up @@ -85,3 +117,19 @@ impl JweA256KWEncipher {
})
}
}

/// Generate a key identifier for an AES 256 wrapping key
fn kid(wrap_key: &Aes256Key) -> String {
let mut skey = HmacSha256Key::default();
let skey_slice = skey.as_mut_slice();
let wrap_key_slice = wrap_key.as_slice();
let skey_slice_mut = &mut skey_slice[..wrap_key_slice.len()];
skey_slice_mut.copy_from_slice(wrap_key_slice);
// Key is setup
let mut hmac = HmacSha256::new(&skey);
hmac.update(b"key identifier");
let hashout = hmac.finalize();
let mut kid = hex::encode(hashout.into_bytes());
kid.truncate(KID_LEN);
kid
}
9 changes: 5 additions & 4 deletions src/oidc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ impl Serialize for OidcDate {
S: serde::Serializer,
{
match self {
OidcDate::Date(d) => serializer.serialize_str(format!("{}", &d).as_str()),
OidcDate::Date(d) => serializer.serialize_str(format!("{}", d).as_str()),
OidcDate::Year(y) => serializer.serialize_str(&format!("{:04}", y)),
}
}
Expand Down Expand Up @@ -312,7 +312,8 @@ impl OidcExpUnverified {
/// A curtime of `0` means that the exp will not be checked. This is not recommended.
pub fn verify_exp(self, curtime: i64) -> Result<OidcToken, JwtError> {
if self.oidc.exp == 0
|| (self.oidc.nbf.map(|nbf| nbf < curtime).unwrap_or(true) && curtime <= self.oidc.exp)
|| curtime == 0
|| (self.oidc.nbf.map(|nbf| nbf <= curtime).unwrap_or(true) && curtime <= self.oidc.exp)
{
Ok(self.oidc)
} else {
Expand Down Expand Up @@ -505,7 +506,7 @@ mod tests {
.expect("Unable to validate jwt");

// Not before.
assert!(exp_unverified.verify_exp(60).is_err());
assert!(exp_unverified.verify_exp(59).is_err());

let exp_unverified = jwk_es256_verifier
.verify(&jwtu)
Expand All @@ -519,7 +520,7 @@ mod tests {
.expect("Unable to validate jwt");

let released = exp_unverified
.verify_exp(90)
.verify_exp(60)
.expect("Unable to validate oidc exp");

assert!(released == jwt);
Expand Down
Loading