crypto_hkdf/material.rs
1// SPDX-FileCopyrightText: Copyright © 2026 ReallyMe LLC. All rights reserved
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use zeroize::{Zeroize, ZeroizeOnDrop};
6
7/// HKDF input keying material, zeroized on drop.
8#[derive(Zeroize, ZeroizeOnDrop)]
9pub struct HkdfInputKeyMaterial {
10 bytes: Vec<u8>,
11}
12
13impl HkdfInputKeyMaterial {
14 /// Build input keying material by copying the given bytes.
15 pub fn from_slice(input: &[u8]) -> Self {
16 Self {
17 bytes: input.to_vec(),
18 }
19 }
20
21 /// Borrow the input keying material bytes.
22 pub fn as_bytes(&self) -> &[u8] {
23 &self.bytes
24 }
25}
26
27/// Optional HKDF salt value, zeroized on drop.
28///
29/// HKDF salts can carry protocol or user correlation material. The wrapper
30/// deliberately has no `Debug` or `Clone` implementation so accidental logs
31/// and unmanaged duplicate buffers are not part of the public API.
32#[derive(Zeroize, ZeroizeOnDrop)]
33pub struct HkdfSalt {
34 bytes: Vec<u8>,
35}
36
37impl HkdfSalt {
38 /// Build an HKDF salt by copying the given bytes.
39 pub fn from_slice(input: &[u8]) -> Self {
40 Self {
41 bytes: input.to_vec(),
42 }
43 }
44
45 /// Borrow the salt bytes.
46 pub fn as_bytes(&self) -> &[u8] {
47 &self.bytes
48 }
49}
50
51/// HKDF `info` context/application-binding value.
52#[derive(Debug, Clone, PartialEq, Eq)]
53pub struct HkdfInfo {
54 bytes: Vec<u8>,
55}
56
57impl HkdfInfo {
58 /// Build an HKDF `info` value by copying the given bytes.
59 pub fn from_slice(input: &[u8]) -> Self {
60 Self {
61 bytes: input.to_vec(),
62 }
63 }
64
65 /// Borrow the `info` bytes.
66 pub fn as_bytes(&self) -> &[u8] {
67 &self.bytes
68 }
69
70 pub(crate) fn from_vec(bytes: Vec<u8>) -> Self {
71 Self { bytes }
72 }
73}
74
75/// Fixed-length HKDF output keying material, zeroized on drop.
76#[derive(Zeroize, ZeroizeOnDrop)]
77pub struct HkdfOutput<const N: usize> {
78 bytes: [u8; N],
79}
80
81impl<const N: usize> HkdfOutput<N> {
82 /// Borrow the `N`-byte derived output.
83 pub fn as_bytes(&self) -> &[u8; N] {
84 &self.bytes
85 }
86
87 /// Consume the output and return its `N`-byte array.
88 ///
89 /// The returned array is no longer zeroized by this type. Callers must wipe
90 /// it as soon as the derived key material is no longer needed.
91 pub fn into_bytes(mut self) -> [u8; N] {
92 let output = self.bytes;
93 self.bytes.zeroize();
94 output
95 }
96
97 pub(crate) fn from_array(bytes: [u8; N]) -> Self {
98 Self { bytes }
99 }
100}