Menu
Public repository / master
AkurAI-Framework / crates/crypto/src/hmac.rs
Latest change 3aae9f4e85241bcb775c31f5c03094becd3da56a - Pure-Rust UI layer: akurai-ui, akurai-crypto, Tailwind-grade akurai-css by Ólafur Búi Ólafsson
//! HMAC-SHA-256 (RFC 2104).
use crate::sha256::{sha256, Sha256, BLOCK_LEN};
/// HMAC-SHA-256 of `msg` under `key`.
pub fn hmac_sha256(key: &[u8], msg: &[u8]) -> [u8; 32] {
HmacKey::new(key).mac(msg)
}
/// A key with its inner/outer pads already absorbed, so repeated MACs under
/// the same key (PBKDF2) skip two compressions each.
pub(crate) struct HmacKey {
inner: Sha256,
outer: Sha256,
}
impl HmacKey {
pub(crate) fn new(key: &[u8]) -> Self {
let block = key_block(key);
Self {
inner: padded(&block, 0x36),
outer: padded(&block, 0x5c),
}
}
pub(crate) fn mac(&self, msg: &[u8]) -> [u8; 32] {
let mut inner = self.inner.clone();
inner.update(msg);
let mut outer = self.outer.clone();
outer.update(&inner.finalize());
outer.finalize()
}
}
/// The key zero-padded to one block, hashed first if it is longer.
fn key_block(key: &[u8]) -> [u8; BLOCK_LEN] {
let mut block = [0u8; BLOCK_LEN];
if key.len() > BLOCK_LEN {
block[..32].copy_from_slice(&sha256(key));
} else {
block[..key.len()].copy_from_slice(key);
}
block
}
fn padded(block: &[u8; BLOCK_LEN], pad: u8) -> Sha256 {
let mut h = Sha256::new();
h.update(&block.map(|b| b ^ pad));
h
}