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