Coverage Report

Created: 2026-06-30 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/jsonwebtoken-10.3.0/src/header.rs
Line
Count
Source
1
use std::collections::HashMap;
2
use std::result;
3
4
use base64::{Engine, engine::general_purpose::STANDARD};
5
use serde::{Deserialize, Deserializer, Serialize, Serializer};
6
7
use crate::algorithms::Algorithm;
8
use crate::errors::Result;
9
use crate::jwk::Jwk;
10
use crate::serialization::b64_decode;
11
12
const ZIP_SERIAL_DEFLATE: &str = "DEF";
13
const ENC_A128CBC_HS256: &str = "A128CBC-HS256";
14
const ENC_A192CBC_HS384: &str = "A192CBC-HS384";
15
const ENC_A256CBC_HS512: &str = "A256CBC-HS512";
16
const ENC_A128GCM: &str = "A128GCM";
17
const ENC_A192GCM: &str = "A192GCM";
18
const ENC_A256GCM: &str = "A256GCM";
19
20
/// Encryption algorithm for encrypted payloads.
21
///
22
/// Defined in [RFC7516#4.1.2](https://datatracker.ietf.org/doc/html/rfc7516#section-4.1.2).
23
///
24
/// Values defined in [RFC7518#5.1](https://datatracker.ietf.org/doc/html/rfc7518#section-5.1).
25
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
26
#[allow(clippy::upper_case_acronyms, non_camel_case_types)]
27
pub enum Enc {
28
    A128CBC_HS256,
29
    A192CBC_HS384,
30
    A256CBC_HS512,
31
    A128GCM,
32
    A192GCM,
33
    A256GCM,
34
    Other(String),
35
}
36
37
impl Serialize for Enc {
38
0
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
39
0
    where
40
0
        S: Serializer,
41
    {
42
0
        match self {
43
0
            Enc::A128CBC_HS256 => ENC_A128CBC_HS256,
44
0
            Enc::A192CBC_HS384 => ENC_A192CBC_HS384,
45
0
            Enc::A256CBC_HS512 => ENC_A256CBC_HS512,
46
0
            Enc::A128GCM => ENC_A128GCM,
47
0
            Enc::A192GCM => ENC_A192GCM,
48
0
            Enc::A256GCM => ENC_A256GCM,
49
0
            Enc::Other(v) => v,
50
        }
51
0
        .serialize(serializer)
52
0
    }
Unexecuted instantiation: <jsonwebtoken::header::Enc as serde_core::ser::Serialize>::serialize::<&mut serde_json::ser::Serializer<&mut alloc::vec::Vec<u8>>>
Unexecuted instantiation: <jsonwebtoken::header::Enc as serde_core::ser::Serialize>::serialize::<_>
53
}
54
55
impl<'de> Deserialize<'de> for Enc {
56
0
    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
57
0
    where
58
0
        D: Deserializer<'de>,
59
    {
60
0
        let s = String::deserialize(deserializer)?;
61
0
        match s.as_str() {
62
0
            ENC_A128CBC_HS256 => return Ok(Enc::A128CBC_HS256),
63
0
            ENC_A192CBC_HS384 => return Ok(Enc::A192CBC_HS384),
64
0
            ENC_A256CBC_HS512 => return Ok(Enc::A256CBC_HS512),
65
0
            ENC_A128GCM => return Ok(Enc::A128GCM),
66
0
            ENC_A192GCM => return Ok(Enc::A192GCM),
67
0
            ENC_A256GCM => return Ok(Enc::A256GCM),
68
0
            _ => (),
69
        }
70
0
        Ok(Enc::Other(s))
71
0
    }
72
}
73
74
/// Compression applied to plaintext.
75
///
76
/// Defined in [RFC7516#4.1.3](https://datatracker.ietf.org/doc/html/rfc7516#section-4.1.3).
77
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
78
pub enum Zip {
79
    Deflate,
80
    Other(String),
81
}
82
83
impl Serialize for Zip {
84
0
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
85
0
    where
86
0
        S: Serializer,
87
    {
88
0
        match self {
89
0
            Zip::Deflate => ZIP_SERIAL_DEFLATE,
90
0
            Zip::Other(v) => v,
91
        }
92
0
        .serialize(serializer)
93
0
    }
Unexecuted instantiation: <jsonwebtoken::header::Zip as serde_core::ser::Serialize>::serialize::<&mut serde_json::ser::Serializer<&mut alloc::vec::Vec<u8>>>
Unexecuted instantiation: <jsonwebtoken::header::Zip as serde_core::ser::Serialize>::serialize::<_>
94
}
95
96
impl<'de> Deserialize<'de> for Zip {
97
0
    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
98
0
    where
99
0
        D: Deserializer<'de>,
100
    {
101
0
        let s = String::deserialize(deserializer)?;
102
0
        match s.as_str() {
103
0
            ZIP_SERIAL_DEFLATE => Ok(Zip::Deflate),
104
0
            _ => Ok(Zip::Other(s)),
105
        }
106
0
    }
107
}
108
109
/// A basic JWT header, the alg defaults to HS256 and typ is automatically
110
/// set to `JWT`. All the other fields are optional.
111
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
112
pub struct Header {
113
    /// The type of JWS: it can only be "JWT" here
114
    ///
115
    /// Defined in [RFC7515#4.1.9](https://tools.ietf.org/html/rfc7515#section-4.1.9).
116
    #[serde(skip_serializing_if = "Option::is_none")]
117
    pub typ: Option<String>,
118
    /// The algorithm used
119
    ///
120
    /// Defined in [RFC7515#4.1.1](https://tools.ietf.org/html/rfc7515#section-4.1.1).
121
    pub alg: Algorithm,
122
    /// Content type
123
    ///
124
    /// Defined in [RFC7519#5.2](https://tools.ietf.org/html/rfc7519#section-5.2).
125
    #[serde(skip_serializing_if = "Option::is_none")]
126
    pub cty: Option<String>,
127
    /// JSON Key URL
128
    ///
129
    /// Defined in [RFC7515#4.1.2](https://tools.ietf.org/html/rfc7515#section-4.1.2).
130
    #[serde(skip_serializing_if = "Option::is_none")]
131
    pub jku: Option<String>,
132
    /// JSON Web Key
133
    ///
134
    /// Defined in [RFC7515#4.1.3](https://tools.ietf.org/html/rfc7515#section-4.1.3).
135
    #[serde(skip_serializing_if = "Option::is_none")]
136
    pub jwk: Option<Jwk>,
137
    /// Key ID
138
    ///
139
    /// Defined in [RFC7515#4.1.4](https://tools.ietf.org/html/rfc7515#section-4.1.4).
140
    #[serde(skip_serializing_if = "Option::is_none")]
141
    pub kid: Option<String>,
142
    /// X.509 URL
143
    ///
144
    /// Defined in [RFC7515#4.1.5](https://tools.ietf.org/html/rfc7515#section-4.1.5).
145
    #[serde(skip_serializing_if = "Option::is_none")]
146
    pub x5u: Option<String>,
147
    /// X.509 certificate chain. A Vec of base64 encoded ASN.1 DER certificates.
148
    ///
149
    /// Defined in [RFC7515#4.1.6](https://tools.ietf.org/html/rfc7515#section-4.1.6).
150
    #[serde(skip_serializing_if = "Option::is_none")]
151
    pub x5c: Option<Vec<String>>,
152
    /// X.509 SHA1 certificate thumbprint
153
    ///
154
    /// Defined in [RFC7515#4.1.7](https://tools.ietf.org/html/rfc7515#section-4.1.7).
155
    #[serde(skip_serializing_if = "Option::is_none")]
156
    pub x5t: Option<String>,
157
    /// X.509 SHA256 certificate thumbprint
158
    ///
159
    /// Defined in [RFC7515#4.1.8](https://tools.ietf.org/html/rfc7515#section-4.1.8).
160
    ///
161
    /// This will be serialized/deserialized as "x5t#S256", as defined by the RFC.
162
    #[serde(skip_serializing_if = "Option::is_none")]
163
    #[serde(rename = "x5t#S256")]
164
    pub x5t_s256: Option<String>,
165
    /// Critical - indicates header fields that must be understood by the receiver.
166
    ///
167
    /// Defined in [RFC7515#4.1.6](https://tools.ietf.org/html/rfc7515#section-4.1.6).
168
    #[serde(skip_serializing_if = "Option::is_none")]
169
    pub crit: Option<Vec<String>>,
170
    /// See `Enc` for description.
171
    #[serde(skip_serializing_if = "Option::is_none")]
172
    pub enc: Option<Enc>,
173
    /// See `Zip` for description.
174
    #[serde(skip_serializing_if = "Option::is_none")]
175
    pub zip: Option<Zip>,
176
    /// ACME: The URL to which this JWS object is directed
177
    ///
178
    /// Defined in [RFC8555#6.4](https://datatracker.ietf.org/doc/html/rfc8555#section-6.4).
179
    #[serde(skip_serializing_if = "Option::is_none")]
180
    pub url: Option<String>,
181
    /// ACME: Random data for preventing replay attacks.
182
    ///
183
    /// Defined in [RFC8555#6.5.2](https://datatracker.ietf.org/doc/html/rfc8555#section-6.5.2).
184
    #[serde(skip_serializing_if = "Option::is_none")]
185
    pub nonce: Option<String>,
186
    /// Any additional non-standard headers not defined in [RFC7515#4.1](https://datatracker.ietf.org/doc/html/rfc7515#section-4.1).
187
    /// Once serialized, all keys will be converted to fields at the root level of the header payload
188
    /// Ex: Dict("custom" -> "header") will be converted to "{"typ": "JWT", ..., "custom": "header"}"
189
    #[serde(flatten)]
190
    pub extras: HashMap<String, String>,
191
}
192
193
impl Header {
194
    /// Returns a JWT header with the algorithm given
195
0
    pub fn new(algorithm: Algorithm) -> Self {
196
0
        Header {
197
0
            typ: Some("JWT".to_string()),
198
0
            alg: algorithm,
199
0
            cty: None,
200
0
            jku: None,
201
0
            jwk: None,
202
0
            kid: None,
203
0
            x5u: None,
204
0
            x5c: None,
205
0
            x5t: None,
206
0
            x5t_s256: None,
207
0
            crit: None,
208
0
            enc: None,
209
0
            zip: None,
210
0
            url: None,
211
0
            nonce: None,
212
0
            extras: Default::default(),
213
0
        }
214
0
    }
215
216
    /// Converts an encoded part into the Header struct if possible
217
0
    pub(crate) fn from_encoded<T: AsRef<[u8]>>(encoded_part: T) -> Result<Self> {
218
0
        let decoded = b64_decode(encoded_part)?;
219
0
        Ok(serde_json::from_slice(&decoded)?)
220
0
    }
221
222
    /// Decodes the X.509 certificate chain into ASN.1 DER format.
223
0
    pub fn x5c_der(&self) -> Result<Option<Vec<Vec<u8>>>> {
224
0
        Ok(self
225
0
            .x5c
226
0
            .as_ref()
227
0
            .map(|b64_certs| {
228
0
                b64_certs.iter().map(|x| STANDARD.decode(x)).collect::<result::Result<_, _>>()
229
0
            })
230
0
            .transpose()?)
231
0
    }
232
}
233
234
impl Default for Header {
235
    /// Returns a JWT header using the default Algorithm, HS256
236
0
    fn default() -> Self {
237
0
        Header::new(Algorithm::default())
238
0
    }
239
}