Skip to main content

cratestack_cose/claims/
types.rs

1//! The values a claim object carries in and out.
2
3use std::fmt;
4
5use crate::alg::CoseAlg;
6use crate::thumbprint::KID_LEN;
7
8/// The longest `aud` (bytes of UTF-8) a claim object carries.
9pub const MAX_AUD_LEN: usize = 256;
10/// The longest `typ` (bytes of UTF-8) a claim object carries.
11pub const MAX_TYP_LEN: usize = 128;
12/// The longest `cti` (bytes) a claim object carries.
13pub const MAX_CTI_LEN: usize = 64;
14
15/// The CWT claims (RFC 8392 ยง3.1) a claim object may carry in protected
16/// label `15` (RFC 9597). Only the claims that are `Some` are written.
17///
18/// All four are optional and none is interpreted by this crate: neither
19/// [`sign_claims`](crate::sign_claims) nor [`open_claims`](crate::open_claims)
20/// compares `exp` or `iat` with a clock, or remembers a `cti`. `exp` and
21/// `iat` are whole seconds since the Unix epoch (`NumericDate`; fractional
22/// and negative dates are not written and are refused when read).
23///
24/// ```
25/// use cratestack_cose::CwtClaims;
26///
27/// let claims = CwtClaims { exp: Some(1_790_003_600), ..CwtClaims::default() };
28/// assert_eq!(claims.aud, None);
29/// ```
30#[derive(Debug, Clone, Default, PartialEq, Eq)]
31pub struct CwtClaims {
32    /// `aud` (3): who the object is for, a single non-empty string of at most
33    /// [`MAX_AUD_LEN`] bytes. The array form of RFC 8392 is not accepted.
34    pub aud: Option<String>,
35    /// `exp` (4): the last second the object is meant to be honoured. The
36    /// consumer enforces it.
37    pub exp: Option<u64>,
38    /// `iat` (6): when it was issued, by the issuer's clock.
39    pub iat: Option<u64>,
40    /// `cti` (7): a unique id of 1 to [`MAX_CTI_LEN`] bytes, for a consumer
41    /// that records ids it has accepted.
42    pub cti: Option<Vec<u8>>,
43}
44
45/// A claim object whose signature verified.
46///
47/// **Verified is not fresh.** Nothing here says the object is unexpired,
48/// issued for this audience or seen for the first time: that is the
49/// caller's to decide from [`claims`](Self::claims). `Debug` prints the
50/// payload's length, not its bytes.
51///
52/// `#[non_exhaustive]`: read it, never build it.
53#[derive(Clone, PartialEq, Eq)]
54#[non_exhaustive]
55pub struct OpenedClaims {
56    /// The `kid` from the protected header; the verifying key's own `kid`.
57    pub kid: [u8; KID_LEN],
58    /// The algorithm the object was verified with (a signature algorithm).
59    pub alg: CoseAlg,
60    /// The RFC 9679 thumbprint of the key that verified. Two keys can share
61    /// a `kid`, so this, not the `kid`, identifies the signer.
62    pub key_thumbprint: [u8; 32],
63    /// The claims from the protected header.
64    pub claims: CwtClaims,
65    /// The payload, exactly as signed.
66    pub payload: Vec<u8>,
67}
68
69impl fmt::Debug for OpenedClaims {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        f.debug_struct("OpenedClaims")
72            .field("kid", &self.kid)
73            .field("alg", &self.alg)
74            .field("key_thumbprint", &self.key_thumbprint)
75            .field("claims", &self.claims)
76            .field("payload_len", &self.payload.len())
77            .finish()
78    }
79}