use hkdf::Hkdf;
use sha2::Sha256;
use zeroize::Zeroize;
const HKDF_INFO: &[u8] = b"TENDERMINT_SECRET_CONNECTION_KEY_AND_CHALLENGE_GEN";
pub struct Kdf {
pub recv_secret: [u8; 32],
pub send_secret: [u8; 32],
pub challenge: [u8; 32],
}
impl Kdf {
#[must_use]
pub fn derive_secrets_and_challenge(shared_secret: &[u8; 32], loc_is_lo: bool) -> Self {
let mut key_material = [0_u8; 96];
Hkdf::<Sha256>::new(None, shared_secret)
.expand(HKDF_INFO, &mut key_material)
.expect("secret expansion failed");
let [mut recv_secret, mut send_secret, mut challenge] = [[0_u8; 32]; 3];
if loc_is_lo {
recv_secret.copy_from_slice(&key_material[0..32]);
send_secret.copy_from_slice(&key_material[32..64]);
} else {
send_secret.copy_from_slice(&key_material[0..32]);
recv_secret.copy_from_slice(&key_material[32..64]);
}
challenge.copy_from_slice(&key_material[64..96]);
key_material.as_mut().zeroize();
Self {
recv_secret,
send_secret,
challenge,
}
}
}
impl Drop for Kdf {
fn drop(&mut self) {
self.recv_secret.zeroize();
self.send_secret.zeroize();
self.challenge.zeroize();
}
}