keygate_jwt/algorithms/
eddsa.rs

1use base64ct::Base64UrlUnpadded;
2use base64ct::Encoding;
3use serde::{de::DeserializeOwned, Serialize};
4use sha2::Digest;
5
6use crate::claims::*;
7use crate::common::*;
8use crate::error::*;
9use crate::jwt_header::*;
10use crate::token::*;
11
12#[doc(hidden)]
13#[derive(Debug, Clone)]
14pub struct Edwards25519PublicKey(ed25519_compact::PublicKey);
15
16impl AsRef<ed25519_compact::PublicKey> for Edwards25519PublicKey {
17    fn as_ref(&self) -> &ed25519_compact::PublicKey {
18        &self.0
19    }
20}
21
22impl Edwards25519PublicKey {
23    pub fn from_bytes(raw: &[u8]) -> Result<Self, JWTError> {
24        let ed25519_pk = ed25519_compact::PublicKey::from_slice(raw);
25        Ok(Edwards25519PublicKey(
26            ed25519_pk.map_err(|_| JWTError::InvalidPublicKey)?,
27        ))
28    }
29
30    pub fn from_der(der: &[u8]) -> Result<Self, JWTError> {
31        let ed25519_pk = ed25519_compact::PublicKey::from_der(der);
32        Ok(Edwards25519PublicKey(
33            ed25519_pk.map_err(|_| JWTError::InvalidPublicKey)?,
34        ))
35    }
36
37    pub fn from_pem(pem: &str) -> Result<Self, JWTError> {
38        let ed25519_pk = ed25519_compact::PublicKey::from_pem(pem);
39        Ok(Edwards25519PublicKey(
40            ed25519_pk.map_err(|_| JWTError::InvalidPublicKey)?,
41        ))
42    }
43
44    pub fn to_bytes(&self) -> Vec<u8> {
45        self.0.as_ref().to_vec()
46    }
47
48    pub fn to_der(&self) -> Vec<u8> {
49        self.0.to_der()
50    }
51
52    pub fn to_pem(&self) -> String {
53        self.0.to_pem()
54    }
55}
56
57#[doc(hidden)]
58#[derive(Clone)]
59pub struct Edwards25519KeyPair {
60    ed25519_kp: ed25519_compact::KeyPair,
61    metadata: Option<KeyMetadata>,
62}
63
64impl AsRef<ed25519_compact::KeyPair> for Edwards25519KeyPair {
65    fn as_ref(&self) -> &ed25519_compact::KeyPair {
66        &self.ed25519_kp
67    }
68}
69
70impl Edwards25519KeyPair {
71    pub fn from_bytes(raw: &[u8]) -> Result<Self, JWTError> {
72        let ed25519_kp = ed25519_compact::KeyPair::from_slice(raw)?;
73        Ok(Edwards25519KeyPair {
74            ed25519_kp,
75            metadata: None,
76        })
77    }
78
79    pub fn from_der(der: &[u8]) -> Result<Self, JWTError> {
80        let ed25519_kp = match ed25519_compact::KeyPair::from_der(der) {
81            Ok(kp) => kp,
82            Err(_) => ed25519_compact::KeyPair::from_seed(
83                ed25519_compact::SecretKey::from_der(der)?.seed(),
84            ),
85        };
86        Ok(Edwards25519KeyPair {
87            ed25519_kp,
88            metadata: None,
89        })
90    }
91
92    pub fn from_pem(pem: &str) -> Result<Self, JWTError> {
93        let ed25519_kp = match ed25519_compact::KeyPair::from_pem(pem) {
94            Ok(kp) => kp,
95            Err(_) => ed25519_compact::KeyPair::from_seed(
96                ed25519_compact::SecretKey::from_pem(pem)?.seed(),
97            ),
98        };
99        Ok(Edwards25519KeyPair {
100            ed25519_kp,
101            metadata: None,
102        })
103    }
104
105    pub fn to_bytes(&self) -> Vec<u8> {
106        self.ed25519_kp.to_vec()
107    }
108
109    pub fn to_der(&self) -> Vec<u8> {
110        self.ed25519_kp.sk.to_der()
111    }
112
113    pub fn to_pem(&self) -> String {
114        self.ed25519_kp.to_pem()
115    }
116
117    pub fn public_key(&self) -> Edwards25519PublicKey {
118        let ed25519_pk = self.ed25519_kp.pk;
119        Edwards25519PublicKey(ed25519_pk)
120    }
121
122    pub fn generate() -> Self {
123        let ed25519_kp = ed25519_compact::KeyPair::from_seed(ed25519_compact::Seed::generate());
124        Edwards25519KeyPair {
125            ed25519_kp,
126            metadata: None,
127        }
128    }
129}
130
131pub trait EdDSAKeyPairLike {
132    fn jwt_alg_name() -> &'static str;
133    fn key_pair(&self) -> &Edwards25519KeyPair;
134    fn key_id(&self) -> &Option<String>;
135    fn metadata(&self) -> &Option<KeyMetadata>;
136    fn attach_metadata(&mut self, metadata: KeyMetadata) -> Result<(), JWTError>;
137
138    fn sign<CustomClaims: Serialize + DeserializeOwned>(
139        &self,
140        claims: JWTClaims<CustomClaims>,
141    ) -> Result<String, JWTError> {
142        let jwt_header = JWTHeader::new(Self::jwt_alg_name().to_string(), self.key_id().clone())
143            .with_metadata(self.metadata());
144        Token::build(&jwt_header, claims, |authenticated| {
145            let noise = ed25519_compact::Noise::generate();
146            let signature = self.key_pair().as_ref().sk.sign(authenticated, Some(noise));
147            Ok(signature.to_vec())
148        })
149    }
150}
151
152pub trait EdDSAPublicKeyLike {
153    fn jwt_alg_name() -> &'static str;
154    fn public_key(&self) -> &Edwards25519PublicKey;
155    fn key_id(&self) -> &Option<String>;
156    fn set_key_id(&mut self, key_id: String);
157
158    fn verify_token<CustomClaims: Serialize + DeserializeOwned>(
159        &self,
160        token: &str,
161        options: Option<VerificationOptions>,
162    ) -> Result<JWTClaims<CustomClaims>, JWTError> {
163        Token::verify(
164            Self::jwt_alg_name(),
165            token,
166            options,
167            |authenticated, signature| {
168                let ed25519_signature = ed25519_compact::Signature::from_slice(signature)?;
169                self.public_key()
170                    .as_ref()
171                    .verify(authenticated, &ed25519_signature)
172                    .map_err(|_| JWTError::InvalidSignature)?;
173                Ok(())
174            },
175        )
176    }
177
178    fn create_key_id(&mut self) -> Result<String, JWTError> {
179        let mut hasher = sha2::Sha256::new();
180        hasher.update(self.public_key().to_bytes());
181        let key_id = Base64UrlUnpadded::encode_string(&hasher.finalize());
182        self.set_key_id(key_id.clone());
183        Ok(key_id)
184    }
185}
186
187#[derive(Clone)]
188pub struct Ed25519KeyPair {
189    key_pair: Edwards25519KeyPair,
190    key_id: Option<String>,
191}
192
193#[derive(Debug, Clone)]
194pub struct Ed25519PublicKey {
195    pk: Edwards25519PublicKey,
196    key_id: Option<String>,
197}
198
199impl EdDSAKeyPairLike for Ed25519KeyPair {
200    fn jwt_alg_name() -> &'static str {
201        "EdDSA"
202    }
203
204    fn key_pair(&self) -> &Edwards25519KeyPair {
205        &self.key_pair
206    }
207
208    fn key_id(&self) -> &Option<String> {
209        &self.key_id
210    }
211
212    fn metadata(&self) -> &Option<KeyMetadata> {
213        &self.key_pair.metadata
214    }
215
216    fn attach_metadata(&mut self, metadata: KeyMetadata) -> Result<(), JWTError> {
217        self.key_pair.metadata = Some(metadata);
218        Ok(())
219    }
220}
221
222impl Ed25519KeyPair {
223    pub fn from_bytes(raw: &[u8]) -> Result<Self, JWTError> {
224        Ok(Ed25519KeyPair {
225            key_pair: Edwards25519KeyPair::from_bytes(raw)?,
226            key_id: None,
227        })
228    }
229
230    pub fn from_der(der: &[u8]) -> Result<Self, JWTError> {
231        Ok(Ed25519KeyPair {
232            key_pair: Edwards25519KeyPair::from_der(der)?,
233            key_id: None,
234        })
235    }
236
237    pub fn from_pem(pem: &str) -> Result<Self, JWTError> {
238        Ok(Ed25519KeyPair {
239            key_pair: Edwards25519KeyPair::from_pem(pem)?,
240            key_id: None,
241        })
242    }
243
244    pub fn to_bytes(&self) -> Vec<u8> {
245        self.key_pair.to_bytes()
246    }
247
248    pub fn to_der(&self) -> Vec<u8> {
249        self.key_pair.to_der()
250    }
251
252    pub fn to_pem(&self) -> String {
253        self.key_pair.to_pem()
254    }
255
256    pub fn public_key(&self) -> Ed25519PublicKey {
257        Ed25519PublicKey {
258            pk: self.key_pair.public_key(),
259            key_id: self.key_id.clone(),
260        }
261    }
262
263    pub fn generate() -> Self {
264        Ed25519KeyPair {
265            key_pair: Edwards25519KeyPair::generate(),
266            key_id: None,
267        }
268    }
269
270    pub fn with_key_id(mut self, key_id: &str) -> Self {
271        self.key_id = Some(key_id.to_string());
272        self
273    }
274}
275
276impl EdDSAPublicKeyLike for Ed25519PublicKey {
277    fn jwt_alg_name() -> &'static str {
278        "EdDSA"
279    }
280
281    fn public_key(&self) -> &Edwards25519PublicKey {
282        &self.pk
283    }
284
285    fn key_id(&self) -> &Option<String> {
286        &self.key_id
287    }
288
289    fn set_key_id(&mut self, key_id: String) {
290        self.key_id = Some(key_id);
291    }
292}
293
294impl Ed25519PublicKey {
295    pub fn from_bytes(raw: &[u8]) -> Result<Self, JWTError> {
296        Ok(Ed25519PublicKey {
297            pk: Edwards25519PublicKey::from_bytes(raw)?,
298            key_id: None,
299        })
300    }
301
302    pub fn from_der(der: &[u8]) -> Result<Self, JWTError> {
303        Ok(Ed25519PublicKey {
304            pk: Edwards25519PublicKey::from_der(der)?,
305            key_id: None,
306        })
307    }
308
309    pub fn from_pem(pem: &str) -> Result<Self, JWTError> {
310        Ok(Ed25519PublicKey {
311            pk: Edwards25519PublicKey::from_pem(pem)?,
312            key_id: None,
313        })
314    }
315
316    pub fn to_bytes(&self) -> Vec<u8> {
317        self.pk.to_bytes()
318    }
319
320    pub fn to_der(&self) -> Vec<u8> {
321        self.pk.to_der()
322    }
323
324    pub fn to_pem(&self) -> String {
325        self.pk.to_pem()
326    }
327
328    pub fn with_key_id(mut self, key_id: &str) -> Self {
329        self.key_id = Some(key_id.to_string());
330        self
331    }
332
333    pub fn sha256_thumbprint(&self) -> Result<String, JWTError> {
334        let mut hasher = sha2::Sha256::new();
335        hasher.update(self.to_der());
336
337        Ok(Base64UrlUnpadded::encode_string(&hasher.finalize()))
338    }
339}