AkurAI Build
Menu

Public repository / fee5b6c2cde89fa6bf8dc51068af7336b56a88b8

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
}