1use ct_codecs::{Base64UrlSafeNoPadding, Encoder};
2use hmac_sha1_compact::Hash as SHA1;
3use hmac_sha256::Hash as SHA256;
4use serde::{de::DeserializeOwned, Serialize};
5
6use crate::claims::*;
7use crate::common::*;
8#[cfg(feature = "cwt")]
9use crate::cwt_token::*;
10use crate::error::*;
11use crate::jwt_header::*;
12use crate::token::*;
13
14#[doc(hidden)]
15#[derive(Debug, Clone)]
16pub struct Edwards25519PublicKey(ed25519_compact::PublicKey);
17
18impl AsRef<ed25519_compact::PublicKey> for Edwards25519PublicKey {
19 fn as_ref(&self) -> &ed25519_compact::PublicKey {
20 &self.0
21 }
22}
23
24impl Edwards25519PublicKey {
25 pub fn from_bytes(raw: &[u8]) -> Result<Self, Error> {
26 let ed25519_pk = ed25519_compact::PublicKey::from_slice(raw);
27 Ok(Edwards25519PublicKey(
28 ed25519_pk.map_err(|_| JWTError::InvalidPublicKey)?,
29 ))
30 }
31
32 pub fn from_der(der: &[u8]) -> Result<Self, Error> {
33 let ed25519_pk = ed25519_compact::PublicKey::from_der(der);
34 Ok(Edwards25519PublicKey(
35 ed25519_pk.map_err(|_| JWTError::InvalidPublicKey)?,
36 ))
37 }
38
39 pub fn from_pem(pem: &str) -> Result<Self, Error> {
40 let ed25519_pk = ed25519_compact::PublicKey::from_pem(pem);
41 Ok(Edwards25519PublicKey(
42 ed25519_pk.map_err(|_| JWTError::InvalidPublicKey)?,
43 ))
44 }
45
46 pub fn to_bytes(&self) -> Vec<u8> {
47 self.0.as_ref().to_vec()
48 }
49
50 pub fn to_der(&self) -> Vec<u8> {
51 self.0.to_der()
52 }
53
54 pub fn to_pem(&self) -> String {
55 self.0.to_pem()
56 }
57
58 fn thumbprint(&self, hash: impl Fn(&[u8]) -> Vec<u8>) -> String {
59 Base64UrlSafeNoPadding::encode_to_string(hash(&self.to_der())).unwrap()
60 }
61}
62
63#[doc(hidden)]
64#[derive(Clone)]
65pub struct Edwards25519KeyPair {
66 ed25519_kp: ed25519_compact::KeyPair,
67 metadata: Option<KeyMetadata>,
68}
69
70impl std::fmt::Debug for Edwards25519KeyPair {
71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72 f.debug_struct("PKey").field("algorithm", &"Ed25519").finish()
73 }
74}
75
76impl AsRef<ed25519_compact::KeyPair> for Edwards25519KeyPair {
77 fn as_ref(&self) -> &ed25519_compact::KeyPair {
78 &self.ed25519_kp
79 }
80}
81
82impl Edwards25519KeyPair {
83 pub fn from_bytes(raw: &[u8]) -> Result<Self, Error> {
84 let ed25519_kp = ed25519_compact::KeyPair::from_slice(raw)?;
85 Ok(Edwards25519KeyPair {
86 ed25519_kp,
87 metadata: None,
88 })
89 }
90
91 pub fn from_der(der: &[u8]) -> Result<Self, Error> {
92 let ed25519_kp = match ed25519_compact::KeyPair::from_der(der) {
93 Ok(kp) => kp,
94 Err(_) => ed25519_compact::KeyPair::from_seed(
95 ed25519_compact::SecretKey::from_der(der)?.seed(),
96 ),
97 };
98 Ok(Edwards25519KeyPair {
99 ed25519_kp,
100 metadata: None,
101 })
102 }
103
104 pub fn from_pem(pem: &str) -> Result<Self, Error> {
105 let ed25519_kp = match ed25519_compact::KeyPair::from_pem(pem) {
106 Ok(kp) => kp,
107 Err(_) => ed25519_compact::KeyPair::from_seed(
108 ed25519_compact::SecretKey::from_pem(pem)?.seed(),
109 ),
110 };
111 Ok(Edwards25519KeyPair {
112 ed25519_kp,
113 metadata: None,
114 })
115 }
116
117 pub fn to_bytes(&self) -> Vec<u8> {
118 self.ed25519_kp.to_vec()
119 }
120
121 pub fn to_der(&self) -> Vec<u8> {
122 self.ed25519_kp.sk.to_der()
123 }
124
125 pub fn to_pem(&self) -> String {
126 self.ed25519_kp.to_pem()
127 }
128
129 pub fn public_key(&self) -> Edwards25519PublicKey {
130 let ed25519_pk = self.ed25519_kp.pk;
131 Edwards25519PublicKey(ed25519_pk)
132 }
133
134 pub fn generate() -> Self {
135 let ed25519_kp = ed25519_compact::KeyPair::from_seed(ed25519_compact::Seed::generate());
136 Edwards25519KeyPair {
137 ed25519_kp,
138 metadata: None,
139 }
140 }
141}
142
143pub trait EdDSAKeyPairLike {
144 fn jwt_alg_name() -> &'static str;
145 fn key_pair(&self) -> &Edwards25519KeyPair;
146 fn key_id(&self) -> &Option<String>;
147 fn metadata(&self) -> &Option<KeyMetadata>;
148 fn attach_metadata(&mut self, metadata: KeyMetadata) -> Result<(), Error>;
149
150 fn sign<CustomClaims: Serialize>(
151 &self,
152 claims: JWTClaims<CustomClaims>,
153 ) -> Result<String, Error> {
154 self.sign_with_options(claims, &Default::default())
155 }
156
157 fn sign_with_options<CustomClaims: Serialize>(
158 &self,
159 claims: JWTClaims<CustomClaims>,
160 opts: &HeaderOptions,
161 ) -> Result<String, Error> {
162 let jwt_header = JWTHeader::new(Self::jwt_alg_name().to_string(), self.key_id().clone())
163 .with_key_metadata(self.metadata())
164 .with_options(opts);
165 Token::build(&jwt_header, claims, |authenticated| {
166 let noise = ed25519_compact::Noise::generate();
167 let signature = self.key_pair().as_ref().sk.sign(authenticated, Some(noise));
168 Ok(signature.to_vec())
169 })
170 }
171}
172
173pub trait EdDSAPublicKeyLike {
174 fn jwt_alg_name() -> &'static str;
175 fn public_key(&self) -> &Edwards25519PublicKey;
176 fn key_id(&self) -> &Option<String>;
177 fn set_key_id(&mut self, key_id: String);
178
179 fn verify_token<CustomClaims: DeserializeOwned>(
180 &self,
181 token: &str,
182 options: Option<VerificationOptions>,
183 ) -> Result<JWTClaims<CustomClaims>, Error> {
184 Token::verify(
185 Self::jwt_alg_name(),
186 token,
187 options,
188 |authenticated, signature| {
189 let ed25519_signature = ed25519_compact::Signature::from_slice(signature)?;
190 self.public_key()
191 .as_ref()
192 .verify(authenticated, &ed25519_signature)
193 .map_err(|_| JWTError::InvalidSignature)?;
194 Ok(())
195 },
196 |_salt: Option<&[u8]>| Ok(()),
197 )
198 }
199
200 #[cfg(feature = "cwt")]
201 fn verify_cwt_token<CustomClaims: DeserializeOwned>(
202 &self,
203 token: &[u8],
204 options: Option<VerificationOptions>,
205 ) -> Result<JWTClaims<NoCustomClaims>, Error> {
206 CWTToken::verify(
207 Self::jwt_alg_name(),
208 token,
209 options,
210 |authenticated, signature| {
211 let ed25519_signature = ed25519_compact::Signature::from_slice(signature)?;
212 self.public_key()
213 .as_ref()
214 .verify(authenticated, &ed25519_signature)
215 .map_err(|_| JWTError::InvalidSignature)?;
216 Ok(())
217 },
218 )
219 }
220
221 #[cfg(feature = "cwt")]
223 fn decode_cwt_metadata(&self, token: impl AsRef<[u8]>) -> Result<TokenMetadata, Error> {
224 CWTToken::decode_metadata(token)
225 }
226
227 fn create_key_id(&mut self) -> &str {
228 self.set_key_id(
229 Base64UrlSafeNoPadding::encode_to_string(hmac_sha256::Hash::hash(
230 &self.public_key().to_bytes(),
231 ))
232 .unwrap(),
233 );
234 self.key_id().as_ref().map(|x| x.as_str()).unwrap()
235 }
236}
237
238#[derive(Clone)]
239pub struct Ed25519KeyPair {
240 key_pair: Edwards25519KeyPair,
241 key_id: Option<String>,
242}
243
244impl std::fmt::Debug for Ed25519KeyPair {
245 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
246 f.debug_struct("PKey").field("algorithm", &"Ed25519").finish()
247 }
248}
249
250#[derive(Debug, Clone)]
251pub struct Ed25519PublicKey {
252 pk: Edwards25519PublicKey,
253 key_id: Option<String>,
254}
255
256impl EdDSAKeyPairLike for Ed25519KeyPair {
257 fn jwt_alg_name() -> &'static str {
258 "EdDSA"
259 }
260
261 fn key_pair(&self) -> &Edwards25519KeyPair {
262 &self.key_pair
263 }
264
265 fn key_id(&self) -> &Option<String> {
266 &self.key_id
267 }
268
269 fn metadata(&self) -> &Option<KeyMetadata> {
270 &self.key_pair.metadata
271 }
272
273 fn attach_metadata(&mut self, metadata: KeyMetadata) -> Result<(), Error> {
274 self.key_pair.metadata = Some(metadata);
275 Ok(())
276 }
277}
278
279impl Ed25519KeyPair {
280 pub fn from_bytes(raw: &[u8]) -> Result<Self, Error> {
281 Ok(Ed25519KeyPair {
282 key_pair: Edwards25519KeyPair::from_bytes(raw)?,
283 key_id: None,
284 })
285 }
286
287 pub fn from_der(der: &[u8]) -> Result<Self, Error> {
288 Ok(Ed25519KeyPair {
289 key_pair: Edwards25519KeyPair::from_der(der)?,
290 key_id: None,
291 })
292 }
293
294 pub fn from_pem(pem: &str) -> Result<Self, Error> {
295 Ok(Ed25519KeyPair {
296 key_pair: Edwards25519KeyPair::from_pem(pem)?,
297 key_id: None,
298 })
299 }
300
301 pub fn to_bytes(&self) -> Vec<u8> {
302 self.key_pair.to_bytes()
303 }
304
305 pub fn to_der(&self) -> Vec<u8> {
306 self.key_pair.to_der()
307 }
308
309 pub fn to_pem(&self) -> String {
310 self.key_pair.to_pem()
311 }
312
313 pub fn public_key(&self) -> Ed25519PublicKey {
314 Ed25519PublicKey {
315 pk: self.key_pair.public_key(),
316 key_id: self.key_id.clone(),
317 }
318 }
319
320 pub fn generate() -> Self {
321 Ed25519KeyPair {
322 key_pair: Edwards25519KeyPair::generate(),
323 key_id: None,
324 }
325 }
326
327 pub fn with_key_id(mut self, key_id: &str) -> Self {
328 self.key_id = Some(key_id.to_string());
329 self
330 }
331}
332
333impl EdDSAPublicKeyLike for Ed25519PublicKey {
334 fn jwt_alg_name() -> &'static str {
335 "EdDSA"
336 }
337
338 fn public_key(&self) -> &Edwards25519PublicKey {
339 &self.pk
340 }
341
342 fn key_id(&self) -> &Option<String> {
343 &self.key_id
344 }
345
346 fn set_key_id(&mut self, key_id: String) {
347 self.key_id = Some(key_id);
348 }
349}
350
351impl Ed25519PublicKey {
352 pub fn from_bytes(raw: &[u8]) -> Result<Self, Error> {
353 Ok(Ed25519PublicKey {
354 pk: Edwards25519PublicKey::from_bytes(raw)?,
355 key_id: None,
356 })
357 }
358
359 pub fn from_der(der: &[u8]) -> Result<Self, Error> {
360 Ok(Ed25519PublicKey {
361 pk: Edwards25519PublicKey::from_der(der)?,
362 key_id: None,
363 })
364 }
365
366 pub fn from_pem(pem: &str) -> Result<Self, Error> {
367 Ok(Ed25519PublicKey {
368 pk: Edwards25519PublicKey::from_pem(pem)?,
369 key_id: None,
370 })
371 }
372
373 pub fn to_bytes(&self) -> Vec<u8> {
374 self.pk.to_bytes()
375 }
376
377 pub fn to_der(&self) -> Vec<u8> {
378 self.pk.to_der()
379 }
380
381 pub fn to_pem(&self) -> String {
382 self.pk.to_pem()
383 }
384
385 pub fn with_key_id(mut self, key_id: &str) -> Self {
386 self.key_id = Some(key_id.to_string());
387 self
388 }
389
390 pub fn sha1_thumbprint(&self) -> String {
391 self.pk.thumbprint(|data| SHA1::hash(data).to_vec())
392 }
393
394 pub fn sha256_thumbprint(&self) -> String {
395 self.pk.thumbprint(|data| SHA256::hash(data).to_vec())
396 }
397}