extern crate alloc;
use alloc::vec::Vec;
use super::sha2::sha256;
pub fn sign(key: &[u8], data: &[u8]) -> [u8; 32] {
const BLOCK_SIZE: usize = 64;
let mut key_block = [0u8; BLOCK_SIZE];
if key.len() > BLOCK_SIZE {
let hashed_key = sha256(key);
key_block[..hashed_key.len()].copy_from_slice(&hashed_key);
} else {
key_block[..key.len()].copy_from_slice(key);
}
let mut inner_pad = [0u8; BLOCK_SIZE];
let mut outer_pad = [0u8; BLOCK_SIZE];
for i in 0..BLOCK_SIZE {
inner_pad[i] = key_block[i] ^ 0x36;
outer_pad[i] = key_block[i] ^ 0x5c;
}
let mut inner_buf = Vec::with_capacity(BLOCK_SIZE + data.len());
inner_buf.extend_from_slice(&inner_pad);
inner_buf.extend_from_slice(data);
let inner_hash = sha256(&inner_buf);
const OUTER_INPUT_SIZE: usize = BLOCK_SIZE + 32;
let mut outer_buf = [0u8; OUTER_INPUT_SIZE];
outer_buf[..BLOCK_SIZE].copy_from_slice(&outer_pad);
outer_buf[BLOCK_SIZE..].copy_from_slice(&inner_hash);
sha256(&outer_buf)
}
#[cfg(test)]
mod tests {
extern crate test;
use crate::net::tls::tests::string_to_bytes;
use test::{Bencher, black_box};
#[test]
fn test_hmac_sha256_short() {
let key = "secret";
let data = "Hello";
let output = super::sign(key.as_bytes(), data.as_bytes());
let expected =
string_to_bytes("0cc692f2177b42b6e5cd82488ee6c5d526a007c571e7de1fec07c1e2b1dfa2e2");
assert_eq!(output, expected);
}
#[test]
fn test_hmac_sha256_long() {
let key = "secret";
let data = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.";
let output = super::sign(key.as_bytes(), data.as_bytes());
let expected =
string_to_bytes("602a9c4d44feea742c6775c21d686ccd899ee4c8363d7c03535b949c16a6b6d8");
assert_eq!(output, expected);
}
#[bench]
fn bench_hmac_short(b: &mut Bencher) {
let key = b"secret";
let data = b"The quick brown fox jumps over the lazy dog";
b.iter(|| {
black_box(super::sign(key, data));
});
}
#[bench]
fn bench_hmac_long(b: &mut Bencher) {
let key = b"secret";
let mut data = [0u8; 448];
crate::syscall::getrandom(&mut data);
b.iter(|| {
black_box(super::sign(key, &data));
});
}
}