Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
use super::funejson::Value; ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::crypto_sha256::sha256; ← from crypto.sha256 ^1.0.0 · built alongside by fune
const BLOCK: usize = 64;
fn check_bytes(value: &[i64], name: &str) {
if value.iter().any(|b| !(0..=255).contains(b)) {
panic!("{} must be a list of integers from 0 to 255", name);
}
}
/// HMAC-SHA256 (RFC 2104): H((K ^ opad) || H((K ^ ipad) || message)), with a
/// key longer than the 64-byte block hashed down to 32 bytes first.
///
/// # Panics
/// Panics if any key or message value is outside 0-255.
pub fn hmac_sha256(key: &[i64], message: &[i64]) -> Vec<i64> {
check_bytes(key, "key");
check_bytes(message, "message");
let hashed;
let k: &[i64] = if key.len() > BLOCK {
hashed = sha256(key);
&hashed
} else {
key
};
let mut inner: Vec<i64> = Vec::with_capacity(BLOCK + message.len());
let mut outer: Vec<i64> = Vec::with_capacity(BLOCK + 32);
for i in 0..BLOCK {
let b = if i < k.len() { k[i] } else { 0 };
inner.push(b ^ 0x36);
outer.push(b ^ 0x5c);
}
inner.extend_from_slice(message);
outer.extend(sha256(&inner));
sha256(&outer)
}
fn bytes_from_value(value: &Value, name: &str) -> Vec<i64> {
match value {
Value::Arr(items) => items
.iter()
.map(|item| match item {
Value::Int(i) => *i,
_ => panic!("{} must be a list of integers from 0 to 255", name),
})
.collect(),
_ => panic!("{} must be a list of integers from 0 to 255", name),
}
}
pub fn fune_vector(args: &[Value]) -> Value {
let key = bytes_from_value(&args[0], "key");
let message = bytes_from_value(&args[1], "message");
Value::Arr(hmac_sha256(&key, &message).into_iter().map(Value::Int).collect())
}