Expand description
Time-locked key derivation.
Derives a deterministic 32-byte key from a time value through a three-pass heterogeneous KDF chain:
| Pass | Algorithm | Role |
|---|---|---|
| 1 | Argon2id | PHC winner; sequential- and random-access memory-hard; GPU/ASIC-resistant |
| 2 | scrypt | Independently designed memory-hard function (ROMix); orthogonal to Argon2id |
| 3 | Argon2id | Extends the chain depth with fresh parameters and a distinct salt |
Using two independently designed memory-hard functions ensures the chain remains strong even if a weakness is discovered in either algorithm. Every intermediate KDF output is zeroized from memory before the subsequent pass begins.
§Two entry points
params argument | Path | Intended use |
|---|---|---|
params: None (+ all other Some) | _at — encryption | Caller supplies cadence, time, precision, format, salts, and KDF parameters |
params: Some(p) (rest None) | _now — decryption | All settings are read from TimeLockParams; no additional input required |
Async counterparts (timelock_async) are provided under the
enc-timelock-async-keygen-now and enc-timelock-async-keygen-input features;
they offload blocking KDF work to a dedicated thread, ensuring the calling
executor is never stalled.
§Time input
The KDF input is a short ASCII string derived from the time value at one of three selectable precision levels.
TimePrecision | TimeFormat | Example string | Window | Candidates/day |
|---|---|---|---|---|
Hour | Hour24 | "14" | 60 min | 24 |
Hour | Hour12 | "02PM" | 60 min | 12 unique × 2 |
Quarter | Hour24 | "14:30" | 15 min | 96 |
Quarter | Hour12 | "02:30PM" | 15 min | 48 unique × 2 |
Minute | Hour24 | "14:37" | 1 min | 1440 |
Minute | Hour12 | "02:37PM" | 1 min | 720 unique × 2 |
Hour12note: the same time slot recurs twice daily (AM + PM), making the derived key valid twice per day. UseHour24for a key that is uniquely valid once per day.
Clock skew (
Minuteprecision): if both parties’ clocks may diverge by up to one minute, derive keys fornow() − 1 min,now(), andnow() + 1 minand try each in turn. The additional cost is negligible relative to a single full KDF pass.
§Salts
TimeLockSalts holds three independent 32-byte random values — one per
KDF pass — generated at encryption time via TimeLockSalts::generate.
Salts are not secret; they prevent precomputation attacks and must be
stored in plaintext alongside the ciphertext header. The identical salts
must be provided to the decryption call.
§Memory safety
All intermediate KDF outputs are wrapped in [Zeroizing] and overwritten
upon being dropped. TimeLockKey implements ZeroizeOnDrop; the final
32-byte key material is scrubbed from memory the moment it goes out of scope.
§Quick start
use toolkit_zero::encryption::timelock::*;
// ── Encryption side ───────────────────────────────────────────────────
let salts = TimeLockSalts::generate();
let kdf = KdfPreset::Balanced.params();
let lock_time = TimeLockTime::new(14, 37).unwrap();
// Derive the encryption key (params = None → _at path).
let enc_key = timelock(
Some(TimeLockCadence::None),
Some(lock_time),
Some(TimePrecision::Minute),
Some(TimeFormat::Hour24),
Some(salts.clone()),
Some(kdf),
None,
).unwrap();
// Pack all settings into a header and store alongside the ciphertext.
let header = pack(TimePrecision::Minute, TimeFormat::Hour24,
&TimeLockCadence::None, salts, kdf);
// ── Decryption side ───────────────────────────────────────────────────
// Load header from ciphertext (params = Some → _now path).
// Call at 14:37 local time:
let dec_key = timelock(
None, None, None, None, None, None,
Some(header),
).unwrap();
// enc_key.as_bytes() == dec_key.as_bytes() when called at 14:37 local timeRe-exports§
pub use utility::TimeLockParams;pub use utility::pack;pub use utility::unpack;
Modules§
- backend_
deps - Re-exports all backend dependencies used by the
timelockmodule. - utility
Structs§
- Argon2
Pass Params - Argon2id parameters for one pass of the KDF chain.
- KdfParams
- Combined parameters for the full three-pass Argon2id → scrypt → Argon2id KDF chain.
- Scrypt
Pass Params - scrypt parameters for the second pass of the KDF chain.
- Time
Lock Key - A derived 32-byte time-locked key.
- Time
Lock Salts - Three independent 32-byte random salts — one per KDF pass.
- Time
Lock Time - An explicit time value supplied by the caller for encryption-time key derivation.
- Timelock
Builder - Fluent builder for [
timelock] /timelock_asynckey derivation.
Enums§
- KdfPreset
- Pre-tuned
KdfParamssets. - Month
- Calendar month (January = 1 … December = 12).
- Time
Format - Clock representation used when formatting the time input string.
- Time
Lock Cadence - Calendar cadence for a scheduled time-lock — constrains key derivation to a recurring calendar pattern in addition to the time-of-day window.
- Time
Lock Error - Errors returned by the
derive_key_*functions. - Time
Precision - The granularity at which the time value is quantised when constructing the KDF input string.
- Weekday
- Day of the week, Monday-indexed (Mon = 0 … Sun = 6).
Functions§
- timelock
- Derive a 32-byte time-locked key — unified sync entry point.
- timelock_
async - Derive a 32-byte time-locked key — unified async entry point.
Attribute Macros§
- timelock
- Concise attribute macro for deriving a time-locked key inline.