keygate_jwt/algorithms/
eddsa.rs1use 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}