1use std::collections::HashSet;
2
3use coarsetime::{Duration, UnixTimeStamp};
4use ct_codecs::{Base64UrlSafeNoPadding, Decoder, Encoder, Hex};
5use rand::RngCore;
6
7use crate::{claims::DEFAULT_TIME_TOLERANCE_SECS, error::*};
8
9pub const DEFAULT_MAX_TOKEN_LENGTH: usize = 1_000_000;
10
11#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct VerificationOptions {
15 pub reject_before: Option<UnixTimeStamp>,
26
27 pub accept_future: bool,
29
30 pub required_subject: Option<String>,
32
33 pub required_key_id: Option<String>,
35
36 pub required_signature_type: Option<String>,
38
39 pub required_content_type: Option<String>,
41
42 pub required_nonce: Option<String>,
44
45 pub allowed_issuers: Option<HashSet<String>>,
47
48 pub allowed_audiences: Option<HashSet<String>>,
50
51 pub time_tolerance: Option<Duration>,
54
55 pub max_validity: Option<Duration>,
57
58 pub max_token_length: Option<usize>,
60
61 pub max_header_length: Option<usize>,
63
64 pub artificial_time: Option<UnixTimeStamp>,
66}
67
68impl Default for VerificationOptions {
69 fn default() -> Self {
70 Self {
71 reject_before: None,
72 accept_future: false,
73 required_subject: None,
74 required_key_id: None,
75 required_signature_type: None,
76 required_content_type: None,
77 required_nonce: None,
78 allowed_issuers: None,
79 allowed_audiences: None,
80 time_tolerance: Some(Duration::from_secs(DEFAULT_TIME_TOLERANCE_SECS)),
81 max_validity: None,
82 max_token_length: Some(DEFAULT_MAX_TOKEN_LENGTH),
83 max_header_length: None,
84 artificial_time: None,
85 }
86 }
87}
88
89#[derive(Debug, Clone, Default)]
91pub struct HeaderOptions {
92 pub content_type: Option<String>,
95 pub signature_type: Option<String>,
99}
100
101#[derive(Debug, Clone, Default)]
102pub enum Salt {
103 #[default]
105 None,
106 Signer(Vec<u8>),
108 Verifier(Vec<u8>),
110}
111
112impl Salt {
113 pub fn len(&self) -> usize {
115 match self {
116 Salt::None => 0,
117 Salt::Signer(s) => s.len(),
118 Salt::Verifier(s) => s.len(),
119 }
120 }
121
122 pub fn is_empty(&self) -> bool {
124 self.len() == 0
125 }
126
127 pub fn generate() -> Self {
129 let mut salt = vec![0u8; 32];
130 rand::thread_rng().fill_bytes(&mut salt);
131 Salt::Signer(salt)
132 }
133}
134
135impl AsRef<[u8]> for Salt {
136 fn as_ref(&self) -> &[u8] {
138 match self {
139 Salt::None => &[],
140 Salt::Signer(s) => s,
141 Salt::Verifier(s) => s,
142 }
143 }
144}
145
146#[derive(Debug, Clone, Default)]
150pub struct KeyMetadata {
151 pub(crate) key_set_url: Option<String>,
152 pub(crate) public_key: Option<String>,
153 pub(crate) certificate_url: Option<String>,
154 pub(crate) certificate_sha1_thumbprint: Option<String>,
155 pub(crate) certificate_sha256_thumbprint: Option<String>,
156 pub(crate) salt: Salt,
157}
158
159impl KeyMetadata {
160 pub fn with_salt(mut self, salt: Salt) -> Self {
162 self.salt = salt;
163 self
164 }
165
166 pub fn with_key_set_url(mut self, key_set_url: impl ToString) -> Self {
168 self.key_set_url = Some(key_set_url.to_string());
169 self
170 }
171
172 pub fn with_public_key(mut self, public_key: impl ToString) -> Self {
174 self.public_key = Some(public_key.to_string());
175 self
176 }
177
178 pub fn with_certificate_url(mut self, certificate_url: impl ToString) -> Self {
180 self.certificate_url = Some(certificate_url.to_string());
181 self
182 }
183
184 pub fn with_certificate_sha1_thumbprint(
186 mut self,
187 certificate_sha1_thumbprint: impl ToString,
188 ) -> Result<Self, Error> {
189 let thumbprint = certificate_sha1_thumbprint.to_string();
190 let mut bin = [0u8; 20];
191 if thumbprint.len() == 40 {
192 ensure!(
193 Hex::decode(&mut bin, &thumbprint, None)?.len() == bin.len(),
194 JWTError::InvalidCertThumprint
195 );
196 let thumbprint = Base64UrlSafeNoPadding::encode_to_string(bin)?;
197 self.certificate_sha1_thumbprint = Some(thumbprint);
198 return Ok(self);
199 }
200 ensure!(
201 Base64UrlSafeNoPadding::decode(&mut bin, &thumbprint, None)?.len() == bin.len(),
202 JWTError::InvalidCertThumprint
203 );
204 self.certificate_sha1_thumbprint = Some(thumbprint);
205 Ok(self)
206 }
207
208 pub fn with_certificate_sha256_thumbprint(
210 mut self,
211 certificate_sha256_thumbprint: impl ToString,
212 ) -> Result<Self, Error> {
213 let thumbprint = certificate_sha256_thumbprint.to_string();
214 let mut bin = [0u8; 32];
215 if thumbprint.len() == 64 {
216 ensure!(
217 Hex::decode(&mut bin, &thumbprint, None)?.len() == bin.len(),
218 JWTError::InvalidCertThumprint
219 );
220 let thumbprint = Base64UrlSafeNoPadding::encode_to_string(bin)?;
221 self.certificate_sha256_thumbprint = Some(thumbprint);
222 return Ok(self);
223 }
224 ensure!(
225 Base64UrlSafeNoPadding::decode(&mut bin, &thumbprint, None)?.len() == bin.len(),
226 JWTError::InvalidCertThumprint
227 );
228 self.certificate_sha256_thumbprint = Some(thumbprint);
229 Ok(self)
230 }
231}