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
//! Signature verification — M75 (RFC 7515 §5.2, RFC 8725 §3.1).
//!
//! Every other `check_*` module reads what the token *says*; this one
//! decides whether the issuer *said it*. It runs immediately after
//! `check_header` resolves the `kid` (M12) and before any claim is read,
//! so no claim — and no replay-cache, session-row or epoch lookup keyed on
//! one — is ever acted on for a token the issuer did not sign.
//!
//! The signing input is the first two segments **exactly as transmitted**
//! (RFC 7515 §5.2 step 8), never a re-encoding of the parsed JSON: a
//! re-encoding would verify a token other than the one presented.
//!
//! Until this module existed the pipeline resolved the `kid` and stopped
//! there, so any token naming a key in the set — with any payload and any
//! third segment — was admitted. The regression guards are
//! `test_reject_tampered_payload` and its siblings in
//! `tests/jwt_negative.rs`, with counterparts in `tests/id_token_negative.rs`
//! and `tests/id_token_logout_hint.rs`.
use DecodingKey;
use cratecheck_strict_base64url;
use crateSharedAuthError;
/// The algorithm the signature is verified under — pinned by the engine,
/// never read from the token header (M06). `Algorithm` is sealed to
/// `EdDSA` (M02), so this is the only value `check_algorithm` can have
/// admitted; a second algorithm would have to be threaded through here
/// deliberately, keyed to the resolved key, not to the header.
const PINNED_ALGORITHM: Algorithm = EdDSA;
pub