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