1use alloc::string::String;
4
5use base64ct::{Base64UrlUnpadded, Encoding};
6use serde::{Deserialize, Serialize};
7use sha2::{Digest, Sha256};
8use ts_crypto::{
9 any,
10 ecdsa::{
11 P256VerifyingKey, P384VerifyingKey, P521VerifyingKey, SECP_256_R_1, SECP_384_R_1,
12 SECP_521_R_1, VerifyingKey as _,
13 },
14 eddsa::{Ed448VerifyingKey, Ed25519VerifyingKey, ID_ED_448, ID_ED_25519, VerifyingKey as _},
15 rsa::{RsaVerifyingKey, VerifyingKey as _},
16};
17use ts_io::Base64Url;
18
19use crate::{Algorithm, Curve, JsonWebToken};
20
21#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
25#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
26pub struct JsonWebKey {
27 pub kid: String,
29
30 #[serde(rename = "use")]
33 pub usage: String,
34
35 pub alg: Algorithm,
37
38 #[serde(skip_serializing_if = "Option::is_none")]
40 pub crv: Option<Curve>,
41
42 #[serde(flatten)]
44 pub kty: KeyType,
45}
46
47#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
49#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
50#[serde(tag = "kty")]
51#[non_exhaustive]
52pub enum KeyType {
53 #[serde(rename = "EC")]
55 #[allow(missing_docs)]
56 Ec { x: Base64Url, y: Base64Url },
57
58 #[serde(rename = "RSA")]
60 #[allow(missing_docs)]
61 Rsa { n: Base64Url, e: Base64Url },
62 #[serde(rename = "OKP")]
64 #[allow(missing_docs)]
65 Okp { x: Base64Url },
66}
67
68impl KeyType {
69 pub fn kid(&self) -> String {
71 let mut digest = Sha256::default();
72 match &self {
73 Self::Ec { x, y } => {
74 digest.update(x);
75 digest.update(y);
76 }
77 Self::Rsa { n, e } => {
78 digest.update(n);
79 digest.update(e);
80 }
81 Self::Okp { x } => {
82 digest.update(x);
83 }
84 };
85 let hash = digest.finalize();
86 Base64UrlUnpadded::encode_string(&hash)
87 }
88}
89
90impl JsonWebKey {
91 pub fn verifies_signature(&self, jwt: &JsonWebToken) -> bool {
93 match &self.kty {
94 KeyType::Ec { x, y } => {
95 let key: Box<dyn ts_crypto::ecdsa::VerifyingKey> = match self.crv {
96 Some(Curve::P256) => {
97 let Some(key) = P256VerifyingKey::from_coordinates(x, y) else {
98 return false;
99 };
100 Box::new(key)
101 }
102 Some(Curve::P384) => {
103 let Some(key) = P384VerifyingKey::from_coordinates(x, y) else {
104 return false;
105 };
106 Box::new(key)
107 }
108 Some(Curve::P521) => {
109 let Some(key) = P521VerifyingKey::from_coordinates(x, y) else {
110 return false;
111 };
112 Box::new(key)
113 }
114 _ => return false,
115 };
116 match self.alg {
117 Algorithm::ES256 => key.verifies_sha256(&jwt.signature, &jwt.message()),
118 Algorithm::ES384 => key.verifies_sha384(&jwt.signature, &jwt.message()),
119 Algorithm::ES512 => key.verifies_sha512(&jwt.signature, &jwt.message()),
120 _ => false,
121 }
122 }
123 KeyType::Rsa { n, e } => {
124 let Some(key) = RsaVerifyingKey::from_parameters(n, e) else {
125 return false;
126 };
127
128 match self.alg {
129 Algorithm::RS256 => key.verifies_rs256(&jwt.signature, &jwt.message()),
130 Algorithm::RS384 => key.verifies_rs384(&jwt.signature, &jwt.message()),
131 Algorithm::RS512 => key.verifies_rs512(&jwt.signature, &jwt.message()),
132 Algorithm::PS256 => key.verifies_ps256(&jwt.signature, &jwt.message()),
133 Algorithm::PS384 => key.verifies_ps384(&jwt.signature, &jwt.message()),
134 Algorithm::PS512 => key.verifies_ps512(&jwt.signature, &jwt.message()),
135 _ => false,
136 }
137 }
138 KeyType::Okp { x } => match (self.alg, self.crv) {
139 (Algorithm::Ed25519, _) | (Algorithm::EdDSA, Some(Curve::Ed25519)) => {
140 let Some(key) = Ed25519VerifyingKey::from_raw_public_key(x) else {
141 return false;
142 };
143 key.verifies(&jwt.signature, &jwt.message())
144 }
145 (Algorithm::Ed448, _) | (Algorithm::EdDSA, Some(Curve::Ed448)) => {
146 let Some(key) = Ed448VerifyingKey::from_raw_public_key(x) else {
147 return false;
148 };
149 key.verifies(&jwt.signature, &jwt.message())
150 }
151 _ => false,
152 },
153 }
154 }
155
156 pub fn from_key(key: &any::VerifyingKey) -> Option<Self> {
158 let (kty, alg, crv) = match &key {
159 any::VerifyingKey::Ecdsa(key) => {
160 let (alg, crv) = match key.curve_oid() {
161 SECP_256_R_1 => (Algorithm::ES256, Curve::P256),
162 SECP_384_R_1 => (Algorithm::ES384, Curve::P384),
163 SECP_521_R_1 => (Algorithm::ES512, Curve::P521),
164 _ => return None,
165 };
166
167 let kty = KeyType::Ec {
168 x: Base64Url(key.x()),
169 y: Base64Url(key.y()),
170 };
171 (kty, alg, Some(crv))
172 }
173 any::VerifyingKey::EdDsa(key) => {
174 let crv = match key.curve_oid() {
175 ID_ED_25519 => Curve::Ed25519,
176 ID_ED_448 => Curve::Ed448,
177 _ => return None,
178 };
179
180 let kty = KeyType::Okp {
181 x: Base64Url(key.raw_public_key()),
182 };
183 (kty, Algorithm::EdDSA, Some(crv))
184 }
185 any::VerifyingKey::Rsa(key) => {
186 let alg = Algorithm::PS256;
187 let kty = KeyType::Rsa {
188 n: Base64Url(key.modulus()),
189 e: Base64Url(key.exponent()),
190 };
191 (kty, alg, None)
192 }
193 };
194
195 Some(Self {
196 kid: kty.kid(),
197 usage: "sig".to_string(),
198 alg,
199 crv,
200 kty,
201 })
202 }
203}