Skip to main content

crypt_io/mac/
mod.rs

1//! Message Authentication Codes (MAC).
2//!
3//! A MAC is a small fixed-size tag computed over `(key, data)` such that
4//! anyone holding the key can verify the tag is intact. Three algorithms
5//! ship in 0.5.0:
6//!
7//! | Algorithm        | One-shot                       | Streaming      | Tag    | Feature       |
8//! |------------------|--------------------------------|----------------|--------|---------------|
9//! | HMAC-SHA256      | [`hmac_sha256()`]              | [`HmacSha256`] | 32 B   | `mac-hmac`    |
10//! | HMAC-SHA512      | [`hmac_sha512()`]              | [`HmacSha512`] | 64 B   | `mac-hmac`    |
11//! | BLAKE3 keyed     | [`blake3_keyed()`]             | [`Blake3Mac`]  | 32 B   | `mac-blake3`  |
12//!
13//! Every algorithm exposes three operations:
14//!
15//! - **Compute** (`hmac_sha256`, `blake3_keyed`, ...): produces the tag.
16//! - **Verify** (`hmac_sha256_verify`, `blake3_keyed_verify`, ...): computes
17//!   the tag for the supplied `(key, data)` and compares it against an
18//!   expected tag in **constant time**.
19//! - **Streaming** (`HmacSha256`, `Blake3Mac`, ...): for inputs that
20//!   arrive in chunks.
21//!
22//! # Constant-time verification — non-negotiable
23//!
24//! Comparing two tags with `==` leaks how many leading bytes matched via
25//! timing. That leak is enough to forge tags one byte at a time. The
26//! `*_verify` functions and the streaming hashers' [`HmacSha256::verify`]
27//! / [`HmacSha512::verify`] / [`Blake3Mac::verify`] methods all use
28//! upstream constant-time comparators ([`subtle::ConstantTimeEq`] via
29//! the `hmac` and `blake3` crates).
30//!
31//! **Never** compare a computed tag to an expected tag with `==`. Use
32//! the `verify` paths in this module.
33//!
34//! # Choosing a MAC
35//!
36//! - **HMAC-SHA256** — universal interop. JWT (HS256), TLS PRF, AWS
37//!   request signing, anything that names HMAC-SHA256 in a spec.
38//! - **HMAC-SHA512** — same as above when the wider tag is required.
39//! - **BLAKE3 keyed** — fastest of the three on modern hardware,
40//!   typically 4–10× faster than HMAC-SHA256 at the same security
41//!   level. Pick this when you control both sides of the wire.
42//!
43//! [`subtle::ConstantTimeEq`]: https://docs.rs/subtle/latest/subtle/trait.ConstantTimeEq.html
44//!
45//! # Example
46//!
47//! ```
48//! # #[cfg(feature = "mac-hmac")] {
49//! use crypt_io::mac;
50//!
51//! let key = b"shared secret";
52//! let data = b"message to authenticate";
53//!
54//! let tag = mac::hmac_sha256(key, data)?;
55//! assert!(mac::hmac_sha256_verify(key, data, &tag)?);
56//! # }
57//! # Ok::<(), crypt_io::Error>(())
58//! ```
59
60#[cfg(feature = "mac-blake3")]
61mod blake3_impl;
62#[cfg(feature = "mac-hmac")]
63mod hmac_impl;
64
65#[cfg(feature = "mac-blake3")]
66pub use self::blake3_impl::{Blake3Mac, blake3_keyed, blake3_keyed_verify};
67#[cfg(feature = "mac-hmac")]
68pub use self::hmac_impl::{
69    HmacSha256, HmacSha512, hmac_sha256, hmac_sha256_verify, hmac_sha512, hmac_sha512_verify,
70};
71
72/// Length of an HMAC-SHA256 tag, in bytes. Equal to `32`.
73#[cfg(feature = "mac-hmac")]
74pub const HMAC_SHA256_OUTPUT_LEN: usize = 32;
75
76/// Length of an HMAC-SHA512 tag, in bytes. Equal to `64`.
77#[cfg(feature = "mac-hmac")]
78pub const HMAC_SHA512_OUTPUT_LEN: usize = 64;
79
80/// Length of a BLAKE3 keyed-mode tag, in bytes. Equal to `32`.
81#[cfg(feature = "mac-blake3")]
82pub const BLAKE3_MAC_OUTPUT_LEN: usize = 32;
83
84/// Required key length for BLAKE3 keyed mode, in bytes. Equal to `32`.
85#[cfg(feature = "mac-blake3")]
86pub const BLAKE3_MAC_KEY_LEN: usize = 32;