1use serde::{Deserialize, Serialize};
2use small_collections::SmallString;
3use smallvec::SmallVec;
4
5use crate::{
6 Algorithm, Blake3Key, Ed25519PublicKey, Ed25519SecretKey, Error, HmacSha256Key, HmacSha512Key, P256PublicKey,
7 P256SecretKey, RsaPublicKey, Signature, Signer, Verifier,
8};
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct Jwks {
12 pub keys: SmallVec<Jwk, 5>,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct Jwk {
21 pub kid: SmallString<36>, pub r#use: KeyUse,
23 #[serde(rename = "alg")]
24 pub algorithm: Algorithm,
25
26 #[serde(flatten)]
27 pub crypto: JwkCrypto,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
31#[serde(rename_all = "UPPERCASE", tag = "kty")]
32pub enum JwkCrypto {
33 Okp {
35 #[serde(rename = "crv")]
36 curve: OkpCurve,
37 #[serde(with = "base64_url_no_padding")]
38 x: SmallVec<u8, 32>,
39 #[serde(with = "base64_url_no_padding::option", skip_serializing_if = "Option::is_none")]
40 d: Option<SmallVec<u8, 32>>,
41 },
42 Ec {
44 #[serde(rename = "crv")]
45 curve: EcCurve,
46 #[serde(with = "base64_url_no_padding")]
47 x: SmallVec<u8, 32>,
48 #[serde(with = "base64_url_no_padding")]
49 y: SmallVec<u8, 32>,
50 #[serde(with = "base64_url_no_padding::option", skip_serializing_if = "Option::is_none")]
51 d: Option<SmallVec<u8, 32>>,
52 },
53 #[serde(rename = "oct")]
55 Oct {
56 #[serde(with = "base64_url_no_padding")]
57 key: SmallVec<u8, 32>,
58 },
59 #[serde(rename = "RSA")]
61 Rsa {
62 #[serde(with = "base64_url_no_padding")]
65 n: SmallVec<u8, 0>,
66 #[serde(with = "base64_url_no_padding")]
67 e: SmallVec<u8, 4>,
68 },
69}
70
71#[derive(Copy, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
72pub enum KeyUse {
73 #[serde(rename = "sig")]
74 Sign,
75 #[serde(rename = "enc")]
76 Encrypt,
77}
78
79#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
83pub enum OkpCurve {
84 Ed25519,
85}
86
87impl core::str::FromStr for OkpCurve {
88 type Err = Error;
89
90 fn from_str(s: &str) -> Result<Self, Self::Err> {
91 match s {
92 "Ed25519" => Ok(OkpCurve::Ed25519),
93 _ => Err(Error::InvalidCurve),
94 }
95 }
96}
97
98impl core::fmt::Display for OkpCurve {
99 fn fmt(&self, f: &mut alloc::fmt::Formatter<'_>) -> alloc::fmt::Result {
100 write!(f, "{self:?}")
101 }
102}
103
104#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
105pub enum EcCurve {
106 P256,
108
109 P384,
111
112 P521,
114}
115
116impl From<&Blake3Key> for Jwk {
117 #[inline]
118 fn from(key: &Blake3Key) -> Self {
119 return Jwk {
120 kid: SmallString::new(),
121 r#use: KeyUse::Sign,
122 algorithm: Algorithm::BLAKE3,
123 crypto: JwkCrypto::Oct {
124 key: key.as_bytes().into(),
125 },
126 };
127 }
128}
129
130impl From<&HmacSha256Key> for Jwk {
131 #[inline]
132 fn from(key: &HmacSha256Key) -> Self {
133 return Jwk {
134 kid: SmallString::new(),
135 r#use: KeyUse::Sign,
136 algorithm: Algorithm::HS256,
137 crypto: JwkCrypto::Oct {
138 key: key.as_bytes().into(),
139 },
140 };
141 }
142}
143
144impl From<&HmacSha512Key> for Jwk {
145 #[inline]
146 fn from(key: &HmacSha512Key) -> Self {
147 return Jwk {
148 kid: SmallString::new(),
149 r#use: KeyUse::Sign,
150 algorithm: Algorithm::HS512,
151 crypto: JwkCrypto::Oct {
152 key: key.as_bytes().into(),
153 },
154 };
155 }
156}
157
158impl From<&Ed25519SecretKey> for Jwk {
159 #[inline]
160 fn from(key: &Ed25519SecretKey) -> Self {
161 return Jwk {
162 kid: SmallString::new(),
163 r#use: KeyUse::Sign,
164 algorithm: Algorithm::EdDSA,
165 crypto: JwkCrypto::Okp {
166 curve: OkpCurve::Ed25519,
167 x: key.public_key().to_bytes().into(),
168 d: Some(key.to_bytes().into()),
169 },
170 };
171 }
172}
173
174impl From<&Ed25519PublicKey> for Jwk {
175 #[inline]
176 fn from(key: &Ed25519PublicKey) -> Self {
177 return Jwk {
178 kid: SmallString::new(),
179 r#use: KeyUse::Sign,
180 algorithm: Algorithm::EdDSA,
181 crypto: JwkCrypto::Okp {
182 curve: OkpCurve::Ed25519,
183 x: key.to_bytes().into(),
184 d: None,
185 },
186 };
187 }
188}
189
190impl From<&P256SecretKey> for Jwk {
191 #[inline]
192 fn from(key: &P256SecretKey) -> Self {
193 let public_key = key.public_key();
194 let (x, y) = public_key.key.x_y();
195 return Jwk {
196 kid: SmallString::new(),
197 r#use: KeyUse::Sign,
198 algorithm: Algorithm::ES256,
199 crypto: JwkCrypto::Ec {
200 curve: EcCurve::P256,
201 x: x.into(),
202 y: y.into(),
203 d: Some(key.to_bytes().into()),
204 },
205 };
206 }
207}
208
209impl From<&P256PublicKey> for Jwk {
210 #[inline]
211 fn from(key: &P256PublicKey) -> Self {
212 let (x, y) = key.key.x_y();
213 return Jwk {
214 kid: SmallString::new(),
215 r#use: KeyUse::Sign,
216 algorithm: Algorithm::ES256,
217 crypto: JwkCrypto::Ec {
218 curve: EcCurve::P256,
219 x: x.into(),
220 y: y.into(),
221 d: None,
222 },
223 };
224 }
225}
226
227impl From<&RsaPublicKey> for Jwk {
228 fn from(key: &RsaPublicKey) -> Self {
229 Jwk {
230 kid: SmallString::new(),
231 r#use: KeyUse::Sign,
232 algorithm: key.algorithm(),
233 crypto: JwkCrypto::Rsa {
234 n: key.key.n_bytes().into(),
235 e: key.key.e_bytes().into(),
236 },
237 }
238 }
239}
240
241impl From<&Key> for Jwk {
242 fn from(key: &Key) -> Self {
243 match key {
244 Key::Blake3(k) => Jwk::from(k),
245 Key::HmacSha256(k) => Jwk::from(k),
246 Key::HmacSha512(k) => Jwk::from(k),
247 Key::Ed25519Secret(k) => Jwk::from(k),
248 Key::Ed25519Public(k) => Jwk::from(k),
249 Key::P256Secret(k) => Jwk::from(k),
250 Key::P256Public(k) => Jwk::from(k),
251 Key::RsaPublic(k) => Jwk::from(k.as_ref()),
252 }
253 }
254}
255
256pub enum Key {
270 Blake3(Blake3Key),
271 HmacSha256(HmacSha256Key),
272 HmacSha512(HmacSha512Key),
273 Ed25519Secret(Ed25519SecretKey),
274 Ed25519Public(Ed25519PublicKey),
275 P256Secret(P256SecretKey),
276 P256Public(P256PublicKey),
277 RsaPublic(alloc::boxed::Box<RsaPublicKey>),
278}
279
280impl TryFrom<&Jwk> for Key {
281 type Error = Error;
282
283 fn try_from(jwk: &Jwk) -> Result<Self, Error> {
284 match &jwk.crypto {
285 JwkCrypto::Okp {
286 curve,
287 x,
288 d,
289 } => match curve {
290 OkpCurve::Ed25519 => match d {
291 Some(d_bytes) => {
292 let seed: [u8; 32] = d_bytes.as_slice().try_into().map_err(|_| Error::InvalidKey)?;
293 Ok(Key::Ed25519Secret(Ed25519SecretKey::from_bytes(&seed)?))
294 }
295 None => {
296 let pk: [u8; 32] = x.as_slice().try_into().map_err(|_| Error::InvalidKey)?;
297 Ok(Key::Ed25519Public(Ed25519PublicKey::from_bytes(&pk)?))
298 }
299 },
300 },
301 JwkCrypto::Ec {
302 curve,
303 x,
304 y,
305 d,
306 } => match curve {
307 EcCurve::P256 => {
308 let x_arr: [u8; 32] = x.as_slice().try_into().map_err(|_| Error::InvalidKey)?;
309 let y_arr: [u8; 32] = y.as_slice().try_into().map_err(|_| Error::InvalidKey)?;
310 match d {
311 Some(d_bytes) => {
312 let key: [u8; 32] = d_bytes.as_slice().try_into().map_err(|_| Error::InvalidKey)?;
313 Ok(Key::P256Secret(P256SecretKey::from_bytes(&key)?))
314 }
315 None => Ok(Key::P256Public(P256PublicKey::from_x_y(&x_arr, &y_arr)?)),
316 }
317 }
318 EcCurve::P384 | EcCurve::P521 => Err(Error::InvalidEllipticCurve(alloc::format!("{curve:?}"))),
319 },
320 JwkCrypto::Oct {
321 key,
322 } => match jwk.algorithm {
323 Algorithm::BLAKE3 => {
324 let arr: [u8; 32] = key.as_slice().try_into().map_err(|_| Error::InvalidKey)?;
325 Ok(Key::Blake3(Blake3Key::from_bytes(&arr)))
326 }
327 Algorithm::HS256 => Ok(Key::HmacSha256(HmacSha256Key::from_bytes(key)?)),
328 Algorithm::HS512 => Ok(Key::HmacSha512(HmacSha512Key::from_bytes(key)?)),
329 _ => Err(Error::InvalidJwk {
330 kid: alloc::format!("{}", jwk.kid),
331 err: alloc::format!("unsupported algorithm for oct key: {:?}", jwk.algorithm),
332 }),
333 },
334 JwkCrypto::Rsa {
335 n,
336 e,
337 } => {
338 let key = RsaPublicKey::from_n_e(jwk.algorithm, n, e)?;
339 Ok(Key::RsaPublic(alloc::boxed::Box::new(key)))
340 }
341 }
342 }
343}
344
345impl Signer for Key {
346 fn sign(&self, message: &[u8]) -> Result<Signature, Error> {
347 match self {
348 Key::Blake3(k) => k.sign(message),
349 Key::HmacSha256(k) => k.sign(message),
350 Key::HmacSha512(k) => k.sign(message),
351 Key::Ed25519Secret(k) => k.sign(message),
352 Key::P256Secret(k) => k.sign(message),
353 Key::Ed25519Public(_) | Key::P256Public(_) | Key::RsaPublic(_) => Err(Error::InvalidKey),
354 }
355 }
356
357 fn algorithm(&self) -> Algorithm {
358 match self {
359 Key::Blake3(k) => Signer::algorithm(k),
360 Key::HmacSha256(k) => Signer::algorithm(k),
361 Key::HmacSha512(k) => Signer::algorithm(k),
362 Key::Ed25519Secret(k) => k.algorithm(),
363 Key::P256Secret(k) => k.algorithm(),
364 Key::Ed25519Public(k) => k.algorithm(),
365 Key::P256Public(k) => k.algorithm(),
366 Key::RsaPublic(k) => k.algorithm(),
367 }
368 }
369}
370
371impl Verifier for Key {
372 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), Error> {
373 match self {
374 Key::Blake3(k) => k.verify(message, signature),
375 Key::HmacSha256(k) => k.verify(message, signature),
376 Key::HmacSha512(k) => k.verify(message, signature),
377 Key::Ed25519Secret(k) => k.public_key().verify(message, signature),
378 Key::Ed25519Public(k) => k.verify(message, signature),
379 Key::P256Secret(k) => k.public_key().verify(message, signature),
380 Key::P256Public(k) => k.verify(message, signature),
381 Key::RsaPublic(k) => k.verify(message, signature),
382 }
383 }
384
385 fn algorithm(&self) -> Algorithm {
386 match self {
387 Key::Blake3(k) => Verifier::algorithm(k),
388 Key::HmacSha256(k) => Verifier::algorithm(k),
389 Key::HmacSha512(k) => Verifier::algorithm(k),
390 Key::Ed25519Secret(k) => k.algorithm(),
391 Key::P256Secret(k) => k.algorithm(),
392 Key::Ed25519Public(k) => k.algorithm(),
393 Key::P256Public(k) => k.algorithm(),
394 Key::RsaPublic(k) => k.algorithm(),
395 }
396 }
397}
398
399mod base64_url_no_padding {
400 use base64::{Alphabet, decode, encode};
401 use serde::{Deserializer, Serializer};
402
403 use super::*;
404
405 pub fn serialize<S: Serializer, const N: usize>(data: &SmallVec<u8, N>, serializer: S) -> Result<S::Ok, S::Error> {
406 serializer.serialize_str(&encode(data, Alphabet::UrlNoPadding))
407 }
408
409 pub fn deserialize<'de, D: Deserializer<'de>, const N: usize>(
410 deserializer: D,
411 ) -> Result<SmallVec<u8, N>, D::Error> {
412 let s = <&str>::deserialize(deserializer)?;
413 let bytes = decode(s.as_bytes(), Alphabet::UrlNoPadding).map_err(serde::de::Error::custom)?;
414 Ok(SmallVec::from(bytes))
415 }
416
417 pub(crate) mod option {
418 use alloc::string::String;
419
420 use super::*;
421
422 pub fn serialize<S: Serializer, const N: usize>(
423 data: &Option<SmallVec<u8, N>>,
424 serializer: S,
425 ) -> Result<S::Ok, S::Error> {
426 match data {
427 Some(val) => serializer.serialize_str(&encode(val, Alphabet::UrlNoPadding)),
428 None => serializer.serialize_none(),
429 }
430 }
431
432 pub fn deserialize<'de, D: Deserializer<'de>, const N: usize>(
433 deserializer: D,
434 ) -> Result<Option<SmallVec<u8, N>>, D::Error> {
435 let opt: Option<String> = Option::deserialize(deserializer)?;
436 match opt {
437 Some(s) => {
438 let bytes = decode(s.as_bytes(), Alphabet::UrlNoPadding).map_err(serde::de::Error::custom)?;
439 Ok(Some(SmallVec::from(bytes)))
440 }
441 None => Ok(None),
442 }
443 }
444 }
445}