use std::sync::OnceLock;
use hkdf::Hkdf;
use sha2::Sha256;
use topcoat::{
context::{Cx, try_context},
cookie::Key,
};
pub(crate) fn derived(cx: &Cx, purpose: &[u8]) -> [u8; 32] {
static PROCESS: OnceLock<[u8; 32]> = OnceLock::new();
let master: &[u8] = match try_context::<Key>(cx) {
Some(cookie) => cookie.master(),
None => PROCESS.get_or_init(|| {
tracing::warn!(
"no cookie `Key` on the router: upload links and carried uploads \
are signed with a key drawn for this process, so another replica or a restart \
refuses them"
);
let mut key = [0; 32];
getrandom::fill(&mut key).expect("the upload key randomness source failed");
key
}),
};
let mut derived = [0; 32];
Hkdf::<Sha256>::new(None, master)
.expand(purpose, &mut derived)
.expect("32 bytes is a valid HKDF-SHA256 output length");
derived
}