|
|
@@ -1,12 +1,14 @@
|
|
|
+//! HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
|
|
|
//! https://tools.ietf.org/html/rfc5869
|
|
|
use core::fmt;
|
|
|
-use sha2::{
|
|
|
- digest::{crypto_common::BlockSizeUser, typenum::Unsigned, Output, OutputSizeUser, Update},
|
|
|
- Digest,
|
|
|
+
|
|
|
+use digest::{
|
|
|
+ crypto_common::BlockSizeUser, typenum::Unsigned, Digest, Output, OutputSizeUser, Update,
|
|
|
};
|
|
|
|
|
|
use super::hmac::Hmac;
|
|
|
|
|
|
+/// Structure for InvalidPrkLength, used for output error handling.
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
pub struct InvalidPrkLength;
|
|
|
|
|
|
@@ -16,7 +18,7 @@ impl fmt::Display for InvalidPrkLength {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// Structure for InvalidLength, used for output error handling.
|
|
|
+/// Structure for InvalidLength, used for output error handling.
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
pub struct InvalidLength;
|
|
|
|
|
|
@@ -26,20 +28,26 @@ impl fmt::Display for InvalidLength {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/// HKDF-Extract for arbitrary hash functions implementing `Digest`
|
|
|
+/// and `BlockSizeUser` traits.
|
|
|
#[derive(Clone)]
|
|
|
pub struct HkdfExtract<H: Digest + BlockSizeUser + Clone> {
|
|
|
hmac: Hmac<H>,
|
|
|
}
|
|
|
|
|
|
impl<H: Digest + BlockSizeUser + Clone> HkdfExtract<H> {
|
|
|
+ /// Iniitialize a new `HkdfExtract` with the given salt.
|
|
|
pub fn new(salt: &[u8]) -> Self {
|
|
|
Self { hmac: Hmac::<H>::new_from_slice(salt) }
|
|
|
}
|
|
|
|
|
|
+ /// Feeds in additional input key material to the HKDF-Extract context.
|
|
|
pub fn input_ikm(&mut self, ikm: &[u8]) {
|
|
|
self.hmac.update(ikm);
|
|
|
}
|
|
|
|
|
|
+ /// Completes the HKDF-Extract operation, returning both the generated
|
|
|
+ /// pseudorandom key and `Hkdf` struct for expanding.
|
|
|
pub fn finalize(self) -> (Output<H>, Hkdf<H>) {
|
|
|
let prk = self.hmac.finalize();
|
|
|
let hkdf = Hkdf::from_prk(&prk).expect("PRK size is correct");
|
|
|
@@ -47,23 +55,30 @@ impl<H: Digest + BlockSizeUser + Clone> HkdfExtract<H> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/// Structure representing the HKDF, capable of HKDF-Expand
|
|
|
+/// and HKDF-Extract operations.
|
|
|
#[derive(Clone)]
|
|
|
pub struct Hkdf<H: Digest + BlockSizeUser + Clone> {
|
|
|
hmac: Hmac<H>,
|
|
|
}
|
|
|
|
|
|
impl<H: Digest + BlockSizeUser + Clone> Hkdf<H> {
|
|
|
+ /// Convenience method for `extract` when the generated pseudorandom
|
|
|
+ /// key can be ignored and only the HKDF-Expand operation is needed.
|
|
|
pub fn new(salt: &[u8], ikm: &[u8]) -> Self {
|
|
|
let (_, hkdf) = Self::extract(salt, ikm);
|
|
|
hkdf
|
|
|
}
|
|
|
|
|
|
+ /// HKDF-Extract operation returning both the generated pseudorandom
|
|
|
+ /// key and `Hkdf` struct for expanding.
|
|
|
pub fn extract(salt: &[u8], ikm: &[u8]) -> (Output<H>, Self) {
|
|
|
let mut extract_ctx = HkdfExtract::new(salt);
|
|
|
extract_ctx.input_ikm(ikm);
|
|
|
extract_ctx.finalize()
|
|
|
}
|
|
|
|
|
|
+ /// Create `Hkdf` from an already cryptographically strong pseudorandom key.
|
|
|
pub fn from_prk(prk: &[u8]) -> Result<Self, InvalidPrkLength> {
|
|
|
if prk.len() < <H as OutputSizeUser>::OutputSize::to_usize() {
|
|
|
return Err(InvalidPrkLength)
|
|
|
@@ -72,6 +87,8 @@ impl<H: Digest + BlockSizeUser + Clone> Hkdf<H> {
|
|
|
Ok(Self { hmac: Hmac::<H>::new_from_slice(prk) })
|
|
|
}
|
|
|
|
|
|
+ /// HKDF-Expand operation. If you don't have any `info` to pass, use
|
|
|
+ /// an empty slice.
|
|
|
pub fn expand(&self, info: &[u8], okm: &mut [u8]) -> Result<(), InvalidLength> {
|
|
|
self.expand_multi_info(&[info], okm)
|
|
|
}
|