age/
keys.rs

1//! Key structs and serialization.
2
3use age_core::{
4    format::FileKey,
5    primitives::hkdf,
6    secrecy::{ExposeSecret, SecretBox},
7};
8use rand::{rngs::OsRng, RngCore};
9
10use crate::{
11    error::DecryptError,
12    format::HeaderV1,
13    primitives::{stream::PayloadKey, HmacKey},
14    protocol::Nonce,
15};
16
17const HEADER_KEY_LABEL: &[u8] = b"header";
18const PAYLOAD_KEY_LABEL: &[u8] = b"payload";
19
20pub(crate) fn new_file_key() -> FileKey {
21    FileKey::init_with_mut(|file_key| OsRng.fill_bytes(file_key))
22}
23
24pub(crate) fn mac_key(file_key: &FileKey) -> HmacKey {
25    HmacKey(SecretBox::new(Box::new(hkdf(
26        &[],
27        HEADER_KEY_LABEL,
28        file_key.expose_secret(),
29    ))))
30}
31
32pub(crate) fn v1_payload_key(
33    file_key: &FileKey,
34    header: &HeaderV1,
35    nonce: &Nonce,
36) -> Result<PayloadKey, DecryptError> {
37    // Verify the MAC
38    header.verify_mac(mac_key(file_key))?;
39
40    // Return the payload key
41    Ok(PayloadKey(
42        hkdf(nonce.as_ref(), PAYLOAD_KEY_LABEL, file_key.expose_secret()).into(),
43    ))
44}