Skip to main content

jwt_simple/algorithms/
eddsa.rs

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    /// Decode CWT token metadata that can be useful prior to signature/tag verification
224    #[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}