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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! [`Attestation`] — the parsed form of the `lys/attestation/v2` tagged
//! `COSE_Sign1` artifact.
//!
//! # Invariants
//!
//! - **The only durable form is the COSE bytes.** The struct deliberately
//! implements no `serde` traits: nothing can persist an attestation except
//! [`Attestation::to_cose_bytes`], so no second wire shape can ever exist
//! alongside the frozen COSE artifact.
//! - **Round-trip identity:** `from_cose_bytes(x.to_cose_bytes()) == x` for
//! every `Attestation` value, and `to_cose_bytes` of a parsed artifact
//! reproduces the input bytes exactly.
//! - **Canonical-encoding strictness:** [`Attestation::from_cose_bytes`]
//! rejects any input that is not byte-identical to the canonical
//! re-encoding of its parsed fields — including inputs whose signature is
//! cryptographically valid (unprotected-header smuggling, indefinite
//! lengths, oversized integer heads, reordered maps, tag stripping,
//! duplicate keys, trailing garbage). Vanilla COSE verifiers accept some
//! of those mutants; lys never does.
//! - Parsing performs no signature verification; pair `from_cose_bytes` with
//! [`super::sign::verify_attestation`] (or use
//! [`super::sign::verify_attestation_bytes`]) before trusting the fields.
//! - Every parse failure collapses to
//! [`TrustError::InvalidSignature`]
//! (non-oracle).
use crateencoding;
use crate;
/// Ed25519-signed attestation over a payload's SHA-256 hash, carried on the
/// wire as a tagged `COSE_Sign1` (RFC 9052) — the `lys/attestation/v2`
/// artifact.
///
/// Constructed by [`super::sign::sign_attestation`] or parsed from artifact
/// bytes by [`Self::from_cose_bytes`]; consumed by
/// [`super::sign::verify_attestation`]. The struct is intentionally a plain
/// record with public fields — the trust crate provides the primitive;
/// consumers wrap it with their domain meaning (execution receipt, audit
/// entry, etc.).
///
/// Every field is signature-covered: the signer key rides in the protected
/// `kid` header and the hash and timestamp are claims inside the payload,
/// all inside the Ed25519-signed `Sig_structure` (RFC 9052 §4.4). The
/// artifact never carries the attested payload bytes themselves.