vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
//! HMAC CPU reference helpers.

/// Compute HMAC for an arbitrary byte-returning digest function.
///
/// `block_len` is the digest block size and `digest_len` is the number of
/// bytes consumed from the digest output when assembling the outer hash input.
pub fn hmac<F>(key: &[u8], msg: &[u8], block_len: usize, digest_len: usize, hash: F) -> Vec<u8>
where
    F: Fn(&[u8]) -> Vec<u8>,
{
    let mut key_block = vec![0u8; block_len];
    if key.len() > block_len {
        let key_hash = hash(key);
        key_block[..digest_len].copy_from_slice(&key_hash[..digest_len]);
    } else {
        key_block[..key.len()].copy_from_slice(key);
    }

    let mut inner = Vec::with_capacity(block_len + msg.len());
    inner.extend(key_block.iter().map(|byte| byte ^ 0x36));
    inner.extend_from_slice(msg);
    let inner_hash = hash(&inner);

    let mut outer = Vec::with_capacity(block_len + digest_len);
    outer.extend(key_block.iter().map(|byte| byte ^ 0x5c));
    outer.extend_from_slice(&inner_hash[..digest_len]);
    hash(&outer)
}

// hmac_md5_words.rs
/// Compute HMAC-MD5 and return four big-endian digest words.
#[must_use]
pub(crate) fn hmac_md5_words(key: &[u8], msg: &[u8]) -> [u32; 4] {
    let mac = hmac(key, msg, 64, 16, |bytes| {
        let mut out = Vec::with_capacity(16);
        for word in super::md5::md5_words(bytes) {
            out.extend_from_slice(&word.to_be_bytes());
        }
        out
    });
    words4(&mac)
}

// hmac_sha1_words.rs
/// Compute HMAC-SHA-1 and return five big-endian digest words.
#[must_use]
pub(crate) fn hmac_sha1_words(key: &[u8], msg: &[u8]) -> [u32; 5] {
    let mac = hmac(key, msg, 64, 20, |bytes| {
        let mut out = Vec::with_capacity(20);
        for word in super::sha1::sha1_words(bytes) {
            out.extend_from_slice(&word.to_be_bytes());
        }
        out
    });
    words5(&mac)
}

// hmac_sha256_bytes.rs
/// Compute HMAC-SHA-256 and return bytes.
#[must_use]
pub(crate) fn hmac_sha256_bytes(key: &[u8], msg: &[u8]) -> [u8; 32] {
    let mac = hmac(key, msg, 64, 32, |bytes| {
        let mut out = Vec::with_capacity(32);
        for word in super::sha256::sha256_words(bytes) {
            out.extend_from_slice(&word.to_be_bytes());
        }
        out
    });
    let mut out = [0u8; 32];
    out.copy_from_slice(&mac[..32]);
    out
}

// hmac_sha256_words.rs
/// Compute HMAC-SHA-256 and return eight big-endian digest words.
#[must_use]
pub(crate) fn hmac_sha256_words(key: &[u8], msg: &[u8]) -> [u32; 8] {
    let bytes = hmac_sha256_bytes(key, msg);
    let mut out = [0u32; 8];
    for (slot, chunk) in out.iter_mut().zip(bytes.chunks_exact(4)) {
        *slot = u32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
    }
    out
}

/// Interpret the first four big-endian words from `bytes`.
pub fn words4(bytes: &[u8]) -> [u32; 4] {
    let mut out = [0u32; 4];
    for (slot, chunk) in out.iter_mut().zip(bytes.chunks_exact(4)) {
        *slot = u32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
    }
    out
}

/// Interpret the first five big-endian words from `bytes`.
pub fn words5(bytes: &[u8]) -> [u32; 5] {
    let mut out = [0u32; 5];
    for (slot, chunk) in out.iter_mut().zip(bytes.chunks_exact(4)) {
        *slot = u32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
    }
    out
}