#! [allow(dead_code)]
// TODO: remove
use super ::SymKey;
use crate ::{
err::{Error, Res},
hpke::{Aead, Kdf},
};
use hkdf::Hkdf
as HkdfImpl;
use log::trace;
use sha2::{Sha256, Sha384, Sha512};
#[ derive(Clone, Copy)]
pub enum KeyMechanism {
Aead(Aead),
#[ allow(dead_code)]
// We don't use this one.
Hkdf,
}
impl KeyMechanism {
fn len(
self ) -> usize {
match self {
Self ::Aead(a) => a.n_k(),
Self ::Hkdf =>
0 ,
// Let the underlying module decide.
}
}
}
pub enum Hkdf {
Sha256,
Sha384,
Sha512,
}
impl Hkdf {
pub fn new(kdf: Kdf) ->
Self {
match kdf {
Kdf::HkdfSha256 =>
Self ::Sha256,
Kdf::HkdfSha384 =>
Self ::Sha384,
Kdf::HkdfSha512 =>
Self ::Sha512,
}
}
#[ cfg(test)]
#[ allow(clippy::unnecessary_wraps)]
pub fn import_ikm(ikm: &[u8]) -> Res<SymKey> {
Ok(SymKey::from(ikm))
}
#[ allow(clippy::unnecessary_wraps)]
pub fn extract(&
self , salt: &[u8], ikm: &SymKey) -> Res<SymKey> {
let prk =
match self {
Self ::Sha256 => {
SymKey::from(HkdfImpl::<Sha256>::extract(Some(salt), &ikm.
0 ).
0 .as_slice())
}
Self ::Sha384 => {
SymKey::from(HkdfImpl::<Sha384>::extract(Some(salt), &ikm.0 ).0 .as_slice())
}
Self ::Sha512 => {
SymKey::from(HkdfImpl::<Sha512>::extract(Some(salt), &ikm.0 ).0 .as_slice())
}
};
trace!(
"HKDF extract: salt={} ikm={:?} prk={:?}" ,
hex::encode(salt),
ikm,
prk
);
Ok(prk)
}
pub fn expand_key(&self , prk: &SymKey, info: &[u8], key_mech: KeyMechanism) -> Res<SymKey> {
let okm = SymKey::from(self .expand_data(prk, info, key_mech.len())?);
trace!(
"HKDF expand_key: prk={:?} info={} okm={:?}" ,
prk,
hex::encode(info),
okm,
);
Ok(okm)
}
pub fn expand_data(&self , prk: &SymKey, info: &[u8], len: usize) -> Res<Vec<u8>> {
let mut okm = vec![0 ; len];
match self {
Self ::Sha256 => {
let h = HkdfImpl::<Sha256>::from_prk(&prk.0 ).map_err(|_| Error::Internal)?;
h.expand(info, &mut okm).map_err(|_| Error::Internal)?;
}
Self ::Sha384 => {
let h = HkdfImpl::<Sha384>::from_prk(&prk.0 ).map_err(|_| Error::Internal)?;
h.expand(info, &mut okm).map_err(|_| Error::Internal)?;
}
Self ::Sha512 => {
let h = HkdfImpl::<Sha512>::from_prk(&prk.0 ).map_err(|_| Error::Internal)?;
h.expand(info, &mut okm).map_err(|_| Error::Internal)?;
}
}
trace!(
"HKDF expand_data: prk={:?} info={} len={} okm={:?}" ,
prk,
hex::encode(info),
len,
hex::encode(&okm),
);
Ok(okm)
}
}
#[ cfg(test)]
mod test {
use super ::{super ::super ::hpke::Kdf, Hkdf};
use crate ::init;
fn sha256_example(
ikm: &[u8],
salt: &[u8],
info: &[u8],
l: usize,
expected_prk: &[u8],
expected_okm: &[u8],
) {
init();
let hkdf = Hkdf::new(Kdf::HkdfSha256);
let k_ikm = Hkdf::import_ikm(ikm).unwrap();
let prk = hkdf.extract(salt, &k_ikm).unwrap();
let prk_data = prk.key_data().unwrap();
assert_eq!(prk_data, expected_prk);
let out = hkdf.expand_data(&prk, info, l).unwrap();
assert_eq!(&out[..], expected_okm);
}
/// Example 1 from <https://tools.ietf.org/html/rfc5869#appendix-A.1 >
#[ test]
fn example1() {
const IKM: &[u8] = &[
0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b,
0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b,
];
const SALT: &[u8] = &[
0 x00, 0 x01, 0 x02, 0 x03, 0 x04, 0 x05, 0 x06, 0 x07, 0 x08, 0 x09, 0 x0a, 0 x0b, 0 x0c,
];
const INFO: &[u8] = &[0 xf0, 0 xf1, 0 xf2, 0 xf3, 0 xf4, 0 xf5, 0 xf6, 0 xf7, 0 xf8, 0 xf9];
const L: usize = 42 ;
const PRK: &[u8] = &[
0 x07, 0 x77, 0 x09, 0 x36, 0 x2c, 0 x2e, 0 x32, 0 xdf, 0 x0d, 0 xdc, 0 x3f, 0 x0d, 0 xc4, 0 x7b,
0 xba, 0 x63, 0 x90, 0 xb6, 0 xc7, 0 x3b, 0 xb5, 0 x0f, 0 x9c, 0 x31, 0 x22, 0 xec, 0 x84, 0 x4a,
0 xd7, 0 xc2, 0 xb3, 0 xe5,
];
const OKM: &[u8] = &[
0 x3c, 0 xb2, 0 x5f, 0 x25, 0 xfa, 0 xac, 0 xd5, 0 x7a, 0 x90, 0 x43, 0 x4f, 0 x64, 0 xd0, 0 x36,
0 x2f, 0 x2a, 0 x2d, 0 x2d, 0 x0a, 0 x90, 0 xcf, 0 x1a, 0 x5a, 0 x4c, 0 x5d, 0 xb0, 0 x2d, 0 x56,
0 xec, 0 xc4, 0 xc5, 0 xbf, 0 x34, 0 x00, 0 x72, 0 x08, 0 xd5, 0 xb8, 0 x87, 0 x18, 0 x58, 0 x65,
];
sha256_example(IKM, SALT, INFO, L, PRK, OKM);
}
/// Example 2 from <https://tools.ietf.org/html/rfc5869#appendix-A.2 >
#[ test]
fn example2() {
const IKM: &[u8] = &[
0 x00, 0 x01, 0 x02, 0 x03, 0 x04, 0 x05, 0 x06, 0 x07, 0 x08, 0 x09, 0 x0a, 0 x0b, 0 x0c, 0 x0d,
0 x0e, 0 x0f, 0 x10, 0 x11, 0 x12, 0 x13, 0 x14, 0 x15, 0 x16, 0 x17, 0 x18, 0 x19, 0 x1a, 0 x1b,
0 x1c, 0 x1d, 0 x1e, 0 x1f, 0 x20, 0 x21, 0 x22, 0 x23, 0 x24, 0 x25, 0 x26, 0 x27, 0 x28, 0 x29,
0 x2a, 0 x2b, 0 x2c, 0 x2d, 0 x2e, 0 x2f, 0 x30, 0 x31, 0 x32, 0 x33, 0 x34, 0 x35, 0 x36, 0 x37,
0 x38, 0 x39, 0 x3a, 0 x3b, 0 x3c, 0 x3d, 0 x3e, 0 x3f, 0 x40, 0 x41, 0 x42, 0 x43, 0 x44, 0 x45,
0 x46, 0 x47, 0 x48, 0 x49, 0 x4a, 0 x4b, 0 x4c, 0 x4d, 0 x4e, 0 x4f,
];
const SALT: &[u8] = &[
0 x60, 0 x61, 0 x62, 0 x63, 0 x64, 0 x65, 0 x66, 0 x67, 0 x68, 0 x69, 0 x6a, 0 x6b, 0 x6c, 0 x6d,
0 x6e, 0 x6f, 0 x70, 0 x71, 0 x72, 0 x73, 0 x74, 0 x75, 0 x76, 0 x77, 0 x78, 0 x79, 0 x7a, 0 x7b,
0 x7c, 0 x7d, 0 x7e, 0 x7f, 0 x80, 0 x81, 0 x82, 0 x83, 0 x84, 0 x85, 0 x86, 0 x87, 0 x88, 0 x89,
0 x8a, 0 x8b, 0 x8c, 0 x8d, 0 x8e, 0 x8f, 0 x90, 0 x91, 0 x92, 0 x93, 0 x94, 0 x95, 0 x96, 0 x97,
0 x98, 0 x99, 0 x9a, 0 x9b, 0 x9c, 0 x9d, 0 x9e, 0 x9f, 0 xa0, 0 xa1, 0 xa2, 0 xa3, 0 xa4, 0 xa5,
0 xa6, 0 xa7, 0 xa8, 0 xa9, 0 xaa, 0 xab, 0 xac, 0 xad, 0 xae, 0 xaf,
];
const INFO: &[u8] = &[
0 xb0, 0 xb1, 0 xb2, 0 xb3, 0 xb4, 0 xb5, 0 xb6, 0 xb7, 0 xb8, 0 xb9, 0 xba, 0 xbb, 0 xbc, 0 xbd,
0 xbe, 0 xbf, 0 xc0, 0 xc1, 0 xc2, 0 xc3, 0 xc4, 0 xc5, 0 xc6, 0 xc7, 0 xc8, 0 xc9, 0 xca, 0 xcb,
0 xcc, 0 xcd, 0 xce, 0 xcf, 0 xd0, 0 xd1, 0 xd2, 0 xd3, 0 xd4, 0 xd5, 0 xd6, 0 xd7, 0 xd8, 0 xd9,
0 xda, 0 xdb, 0 xdc, 0 xdd, 0 xde, 0 xdf, 0 xe0, 0 xe1, 0 xe2, 0 xe3, 0 xe4, 0 xe5, 0 xe6, 0 xe7,
0 xe8, 0 xe9, 0 xea, 0 xeb, 0 xec, 0 xed, 0 xee, 0 xef, 0 xf0, 0 xf1, 0 xf2, 0 xf3, 0 xf4, 0 xf5,
0 xf6, 0 xf7, 0 xf8, 0 xf9, 0 xfa, 0 xfb, 0 xfc, 0 xfd, 0 xfe, 0 xff,
];
const L: usize = 82 ;
const PRK: &[u8] = &[
0 x06, 0 xa6, 0 xb8, 0 x8c, 0 x58, 0 x53, 0 x36, 0 x1a, 0 x06, 0 x10, 0 x4c, 0 x9c, 0 xeb, 0 x35,
0 xb4, 0 x5c, 0 xef, 0 x76, 0 x00, 0 x14, 0 x90, 0 x46, 0 x71, 0 x01, 0 x4a, 0 x19, 0 x3f, 0 x40,
0 xc1, 0 x5f, 0 xc2, 0 x44,
];
const OKM: &[u8] = &[
0 xb1, 0 x1e, 0 x39, 0 x8d, 0 xc8, 0 x03, 0 x27, 0 xa1, 0 xc8, 0 xe7, 0 xf7, 0 x8c, 0 x59, 0 x6a,
0 x49, 0 x34, 0 x4f, 0 x01, 0 x2e, 0 xda, 0 x2d, 0 x4e, 0 xfa, 0 xd8, 0 xa0, 0 x50, 0 xcc, 0 x4c,
0 x19, 0 xaf, 0 xa9, 0 x7c, 0 x59, 0 x04, 0 x5a, 0 x99, 0 xca, 0 xc7, 0 x82, 0 x72, 0 x71, 0 xcb,
0 x41, 0 xc6, 0 x5e, 0 x59, 0 x0e, 0 x09, 0 xda, 0 x32, 0 x75, 0 x60, 0 x0c, 0 x2f, 0 x09, 0 xb8,
0 x36, 0 x77, 0 x93, 0 xa9, 0 xac, 0 xa3, 0 xdb, 0 x71, 0 xcc, 0 x30, 0 xc5, 0 x81, 0 x79, 0 xec,
0 x3e, 0 x87, 0 xc1, 0 x4c, 0 x01, 0 xd5, 0 xc1, 0 xf3, 0 x43, 0 x4f, 0 x1d, 0 x87,
];
sha256_example(IKM, SALT, INFO, L, PRK, OKM);
}
/// Example 3 from <https://tools.ietf.org/html/rfc5869#appendix-A.3 >
#[ test]
fn example3() {
const IKM: &[u8] = &[
0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b,
0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b,
];
const SALT: &[u8] = &[];
const INFO: &[u8] = &[];
const L: usize = 42 ;
const PRK: &[u8] = &[
0 x19, 0 xef, 0 x24, 0 xa3, 0 x2c, 0 x71, 0 x7b, 0 x16, 0 x7f, 0 x33, 0 xa9, 0 x1d, 0 x6f, 0 x64,
0 x8b, 0 xdf, 0 x96, 0 x59, 0 x67, 0 x76, 0 xaf, 0 xdb, 0 x63, 0 x77, 0 xac, 0 x43, 0 x4c, 0 x1c,
0 x29, 0 x3c, 0 xcb, 0 x04,
];
const OKM: &[u8] = &[
0 x8d, 0 xa4, 0 xe7, 0 x75, 0 xa5, 0 x63, 0 xc1, 0 x8f, 0 x71, 0 x5f, 0 x80, 0 x2a, 0 x06, 0 x3c,
0 x5a, 0 x31, 0 xb8, 0 xa1, 0 x1f, 0 x5c, 0 x5e, 0 xe1, 0 x87, 0 x9e, 0 xc3, 0 x45, 0 x4e, 0 x5f,
0 x3c, 0 x73, 0 x8d, 0 x2d, 0 x9d, 0 x20, 0 x13, 0 x95, 0 xfa, 0 xa4, 0 xb6, 0 x1a, 0 x96, 0 xc8,
];
sha256_example(IKM, SALT, INFO, L, PRK, OKM);
}
}
Messung V0.5 in Prozent C=78 H=100 G=89
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-06-19)
¤
*© Formatika GbR, Deutschland