#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct Header {
pub alg: Algorithm,
pub typ: String,
}
impl Default for Header {
fn default() -> Self {
Self {
alg: Algorithm::HS256,
typ: String::from("JWT"),
}
}
}
impl Header {
pub fn new(alg: Algorithm) -> Self {
Self {
alg,
typ: String::from("JWT"),
}
}
}
#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum Algorithm {
HS256,
}
impl Algorithm {
pub fn sign_fn(&self) -> impl Fn(&[u8], &[u8]) -> crate::error::Result<Vec<u8>> {
match self {
Self::HS256 => Self::sign_hs256,
}
}
fn sign_hs256(data: &[u8], key: &[u8]) -> crate::error::Result<Vec<u8>> {
use hmac::Mac;
let mut mac = hmac::Hmac::<sha2::Sha256>::new_from_slice(key)
.map_err(crate::error::Error::from)?;
mac.update(data);
Ok(mac.finalize().into_bytes().to_vec())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_header_is_jwt_and_hs256() {
let header = Header::default();
assert_eq!(header.alg, Algorithm::HS256);
assert_eq!(header.typ, "JWT");
}
const SECRET_KEY: &[u8] = b"super_secret_key";
const MESSAGE: &[u8] = b"I love Kvanik";
#[test]
fn hs256_success() {
let hashed = Algorithm::HS256.sign_fn()(MESSAGE, SECRET_KEY);
assert!(hashed.is_ok(), "Should be ok");
assert_eq!(b"65f66e9a84e26aaebcf5189d9986ea32f800dbe1f328d3436bf305707c802799", hex::encode(hashed.unwrap()).as_bytes());
}
}