1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//! `crypto_auth`/`crypto_onetimeauth` equivalent (`docs/dstu-crypto-project.md` "Mapping onto the
//! libsodium API", `docs/TASKS.md` T-105, roadmap Step 3 item 2 - `docs/DECISIONS.md` D-66) - a thin
//! libsodium-ergonomics wrapper over [`crate::hazmat::kupyna_kmac::Kupyna256Kmac`].
//!
//! Two departures from the raw `hazmat` API, both following D-47's "delete the knob" criterion
//! (the same rule `crypto_secretbox` applied to Kalyna's five variants, D-51):
//! - **Only the 256-bit MAC size is exposed** - `hazmat::kupyna_kmac` also has `Kupyna384Kmac`/
//! `Kupyna512Kmac`, matching this crate's existing default-to-256-bit convention
//! (`crypto_secretbox`'s `Kalyna256_256Gcm`, `crypto_sign`'s internal `Kupyna256` message hash).
//! The other two sizes remain available at `hazmat::kupyna_kmac` for callers who need them.
//! - **The key is an opaque, `Zeroize`-on-drop [`Key`] type**, not a raw `&[u8]` - this also
//! forecloses `hazmat::kupyna_kmac::KmacError::WrongKeyLength` at this layer entirely: `Key` can
//! only ever be exactly 32 bytes (`from_bytes([u8; 32])` or [`Key::generate`]), so [`auth`] is
//! infallible and [`verify`]'s error type has only one variant. This is a type-signature
//! foreclosure, not an untested code path - see `docs/DECISIONS.md` D-66.
//!
//! Provenance is otherwise identical to the `hazmat` layer: dual-oracle-cited, not yet confirmed
//! against the primary DSTU 7564:2014 text (D-44).
//!
//! # Example
//!
//! A MAC lets two parties who share a secret key confirm a message hasn't been altered in transit.
//! Unlike a signature, either party can both create and check a tag (there's no "public" half), so
//! this only proves "someone who has the key", not "specifically you".
//!
//! ```rust
//! use dstu_core::crypto_auth::{auth, verify, Key};
//!
//! let key = Key::generate().expect("OS CSPRNG should not fail");
//! let message = b"a message both parties want to confirm is unmodified";
//!
//! let tag = auth(&key, message);
//! assert!(verify(&key, message, &tag).is_ok());
//!
//! // A tampered message, or the wrong key, is rejected.
//! assert!(verify(&key, b"a different message", &tag).is_err());
//! ```
use crate;
use fmt;
use Zeroize;
/// A `crypto_auth` key. Always exactly 32 bytes - [`Kupyna256Kmac`]'s fixed MAC/key length (see
/// the module doc).
;
/// `verify` can fail only one way: [`auth`] cannot fail at all (see the module doc's "delete the
/// knob" section - `Key`'s fixed length forecloses `hazmat`'s `WrongKeyLength` case here).
;
/// Computes the MAC of `message` under `key`.
/// Verifies `tag` against `message` under `key`, in constant time
/// ([`crate::hazmat::kupyna_kmac`]'s own `subtle::ConstantTimeEq` comparison).
///
/// # Errors
///
/// Returns [`TagMismatch`] if `tag` does not match.