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