Skip to main content

oxicrypto_core/traits/
kdf.rs

1use crate::CryptoError;
2
3/// Key derivation function (HKDF, PBKDF2, …).
4///
5/// # Minimum key / input lengths
6///
7/// | Algorithm | IKM minimum | Notes |
8/// |-----------|------------|-------|
9/// | HKDF-SHA-{256,384,512} | 1 byte (any non-empty IKM) | Salt and info may be empty |
10/// | PBKDF2-SHA-256/512 | 1 byte | Iteration count ≥ 600 000 (SHA-256) or 210 000 (SHA-512) per OWASP 2023 |
11/// | Argon2id | 1 byte password, ≥ 8 bytes salt | Per RFC 9106 §4 |
12/// | scrypt | 1 byte password | Salt recommended ≥ 16 bytes |
13/// | KBKDF (SP 800-108) | 1 byte | PRK derived from a prior HMAC step |
14///
15/// The maximum output length for HKDF-SHA-256 is **255 × 32 = 8 160 bytes**;
16/// for HKDF-SHA-512 it is **255 × 64 = 16 320 bytes**.  Requesting more returns
17/// [`CryptoError::Internal`].
18pub trait Kdf: Send + Sync + crate::traits::MaybeDebug {
19    /// Human-readable algorithm identifier (e.g. `"HKDF-SHA-256"`).
20    #[must_use]
21    fn name(&self) -> &'static str;
22    /// Derive key material and write it into `okm_out`.
23    ///
24    /// - `ikm`: input key material (must be non-empty for most algorithms)
25    /// - `salt`: optional salt (may be empty; HKDF uses a zero-filled salt of hash length)
26    /// - `info`: context/application-specific info (may be empty)
27    /// - `okm_out`: output buffer (length must be ≥ 1 and within the algorithm's limit)
28    #[must_use = "result must be checked"]
29    fn derive(
30        &self,
31        ikm: &[u8],
32        salt: &[u8],
33        info: &[u8],
34        okm_out: &mut [u8],
35    ) -> Result<(), CryptoError>;
36}
37
38/// Parameters for a password-hashing KDF.
39pub trait PasswordHashParams: Send + Sync + crate::traits::MaybeDebug {
40    /// Memory cost in kibibytes (Argon2, scrypt) or `None` if not applicable.
41    #[must_use]
42    fn memory_cost(&self) -> Option<u32>;
43    /// Time cost (iterations for PBKDF2/Argon2) or `None` if not applicable.
44    #[must_use]
45    fn time_cost(&self) -> Option<u32>;
46    /// Degree of parallelism (Argon2/scrypt) or `None` if not applicable.
47    #[must_use]
48    fn parallelism(&self) -> Option<u32>;
49}
50
51/// Password-hashing function (Argon2id, PBKDF2, scrypt, …).
52///
53/// Distinct from [`Kdf`] because password KDFs expose memory/time/parallelism
54/// tuning that is irrelevant for stream KDFs like HKDF.
55pub trait PasswordHash: Send + Sync + crate::traits::MaybeDebug {
56    /// Human-readable algorithm identifier (e.g. `"Argon2id"`).
57    #[must_use]
58    fn name(&self) -> &'static str;
59    /// Hash `password` with `salt` using the given `params`; write output into `out`.
60    #[must_use = "result must be checked"]
61    fn hash_password(
62        &self,
63        password: &[u8],
64        salt: &[u8],
65        params: &dyn PasswordHashParams,
66        out: &mut [u8],
67    ) -> Result<(), CryptoError>;
68}