1use mas_iana::jose::{
8 JsonWebKeyEcEllipticCurve, JsonWebKeyOkpEllipticCurve, JsonWebKeyType, JsonWebSignatureAlg,
9};
10use schemars::JsonSchema;
11use serde::{Deserialize, Serialize};
12
13use super::ParametersInfo;
14use crate::base64::Base64UrlNoPad;
15
16#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
17#[serde(tag = "kty")]
18pub enum JsonWebKeyPublicParameters {
19 #[serde(rename = "RSA")]
20 Rsa(RsaPublicParameters),
21
22 #[serde(rename = "EC")]
23 Ec(EcPublicParameters),
24
25 #[serde(rename = "OKP")]
26 Okp(OkpPublicParameters),
27}
28
29impl JsonWebKeyPublicParameters {
30 #[must_use]
31 pub const fn rsa(&self) -> Option<&RsaPublicParameters> {
32 match self {
33 Self::Rsa(params) => Some(params),
34 _ => None,
35 }
36 }
37
38 #[must_use]
39 pub const fn ec(&self) -> Option<&EcPublicParameters> {
40 match self {
41 Self::Ec(params) => Some(params),
42 _ => None,
43 }
44 }
45
46 #[must_use]
47 pub const fn okp(&self) -> Option<&OkpPublicParameters> {
48 match self {
49 Self::Okp(params) => Some(params),
50 _ => None,
51 }
52 }
53}
54
55impl ParametersInfo for JsonWebKeyPublicParameters {
56 fn kty(&self) -> JsonWebKeyType {
57 match self {
58 Self::Rsa(_) => JsonWebKeyType::Rsa,
59 Self::Ec(_) => JsonWebKeyType::Ec,
60 Self::Okp(_) => JsonWebKeyType::Okp,
61 }
62 }
63
64 fn possible_algs(&self) -> &[JsonWebSignatureAlg] {
65 match self {
66 JsonWebKeyPublicParameters::Rsa(p) => p.possible_algs(),
67 JsonWebKeyPublicParameters::Ec(p) => p.possible_algs(),
68 JsonWebKeyPublicParameters::Okp(p) => p.possible_algs(),
69 }
70 }
71}
72
73#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
74pub struct RsaPublicParameters {
75 #[schemars(with = "String")]
76 n: Base64UrlNoPad,
77
78 #[schemars(with = "String")]
79 e: Base64UrlNoPad,
80}
81
82impl ParametersInfo for RsaPublicParameters {
83 fn kty(&self) -> JsonWebKeyType {
84 JsonWebKeyType::Rsa
85 }
86
87 fn possible_algs(&self) -> &[JsonWebSignatureAlg] {
88 &[
89 JsonWebSignatureAlg::Rs256,
90 JsonWebSignatureAlg::Rs384,
91 JsonWebSignatureAlg::Rs512,
92 JsonWebSignatureAlg::Ps256,
93 JsonWebSignatureAlg::Ps384,
94 JsonWebSignatureAlg::Ps512,
95 ]
96 }
97}
98
99impl RsaPublicParameters {
100 pub const fn new(n: Base64UrlNoPad, e: Base64UrlNoPad) -> Self {
101 Self { n, e }
102 }
103}
104
105#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
106pub struct EcPublicParameters {
107 pub(crate) crv: JsonWebKeyEcEllipticCurve,
108
109 #[schemars(with = "String")]
110 x: Base64UrlNoPad,
111
112 #[schemars(with = "String")]
113 y: Base64UrlNoPad,
114}
115
116impl EcPublicParameters {
117 pub const fn new(crv: JsonWebKeyEcEllipticCurve, x: Base64UrlNoPad, y: Base64UrlNoPad) -> Self {
118 Self { crv, x, y }
119 }
120}
121
122impl ParametersInfo for EcPublicParameters {
123 fn kty(&self) -> JsonWebKeyType {
124 JsonWebKeyType::Ec
125 }
126
127 fn possible_algs(&self) -> &[JsonWebSignatureAlg] {
128 match &self.crv {
129 JsonWebKeyEcEllipticCurve::P256 => &[JsonWebSignatureAlg::Es256],
130 JsonWebKeyEcEllipticCurve::P384 => &[JsonWebSignatureAlg::Es384],
131 JsonWebKeyEcEllipticCurve::P521 => &[JsonWebSignatureAlg::Es512],
132 JsonWebKeyEcEllipticCurve::Secp256K1 => &[JsonWebSignatureAlg::Es256K],
133 _ => &[],
134 }
135 }
136}
137
138#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
139pub struct OkpPublicParameters {
140 crv: JsonWebKeyOkpEllipticCurve,
141
142 #[schemars(with = "String")]
143 x: Base64UrlNoPad,
144}
145
146impl ParametersInfo for OkpPublicParameters {
147 fn kty(&self) -> JsonWebKeyType {
148 JsonWebKeyType::Okp
149 }
150
151 fn possible_algs(&self) -> &[JsonWebSignatureAlg] {
152 &[JsonWebSignatureAlg::EdDsa]
153 }
154}
155
156impl OkpPublicParameters {
157 pub const fn new(crv: JsonWebKeyOkpEllipticCurve, x: Base64UrlNoPad) -> Self {
158 Self { crv, x }
159 }
160}
161
162mod rsa_impls {
163 use rsa::{BigUint, RsaPublicKey, traits::PublicKeyParts};
164
165 use super::{JsonWebKeyPublicParameters, RsaPublicParameters};
166 use crate::base64::Base64UrlNoPad;
167
168 impl From<RsaPublicKey> for JsonWebKeyPublicParameters {
169 fn from(key: RsaPublicKey) -> Self {
170 Self::from(&key)
171 }
172 }
173
174 impl From<&RsaPublicKey> for JsonWebKeyPublicParameters {
175 fn from(key: &RsaPublicKey) -> Self {
176 Self::Rsa(key.into())
177 }
178 }
179
180 impl From<RsaPublicKey> for RsaPublicParameters {
181 fn from(key: RsaPublicKey) -> Self {
182 Self::from(&key)
183 }
184 }
185
186 impl From<&RsaPublicKey> for RsaPublicParameters {
187 fn from(key: &RsaPublicKey) -> Self {
188 Self {
189 n: Base64UrlNoPad::new(key.n().to_bytes_be()),
190 e: Base64UrlNoPad::new(key.e().to_bytes_be()),
191 }
192 }
193 }
194
195 impl TryFrom<RsaPublicParameters> for RsaPublicKey {
196 type Error = rsa::errors::Error;
197 fn try_from(value: RsaPublicParameters) -> Result<Self, Self::Error> {
198 (&value).try_into()
199 }
200 }
201
202 impl TryFrom<&RsaPublicParameters> for RsaPublicKey {
203 type Error = rsa::errors::Error;
204 fn try_from(value: &RsaPublicParameters) -> Result<Self, Self::Error> {
205 let n = BigUint::from_bytes_be(value.n.as_bytes());
206 let e = BigUint::from_bytes_be(value.e.as_bytes());
207 let key = RsaPublicKey::new(n, e)?;
208 Ok(key)
209 }
210 }
211}
212
213mod ec_impls {
214 use digest::typenum::Unsigned;
215 use ecdsa::EncodedPoint;
216 use elliptic_curve::{
217 AffinePoint, FieldBytes, PublicKey,
218 sec1::{Coordinates, FromEncodedPoint, ModulusSize, ToEncodedPoint},
219 };
220
221 use super::{super::JwkEcCurve, EcPublicParameters, JsonWebKeyPublicParameters};
222 use crate::base64::Base64UrlNoPad;
223
224 impl<C> TryFrom<&EcPublicParameters> for PublicKey<C>
225 where
226 C: elliptic_curve::CurveArithmetic,
227 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
228 C::FieldBytesSize: ModulusSize + Unsigned,
229 {
230 type Error = elliptic_curve::Error;
231 fn try_from(value: &EcPublicParameters) -> Result<Self, Self::Error> {
232 let x = value
233 .x
234 .as_bytes()
235 .get(..C::FieldBytesSize::USIZE)
236 .ok_or(elliptic_curve::Error)?;
237 let y = value
238 .y
239 .as_bytes()
240 .get(..C::FieldBytesSize::USIZE)
241 .ok_or(elliptic_curve::Error)?;
242
243 let x = FieldBytes::<C>::from_slice(x);
244 let y = FieldBytes::<C>::from_slice(y);
245 let pubkey = EncodedPoint::<C>::from_affine_coordinates(x, y, false);
246 let pubkey: Option<_> = PublicKey::from_encoded_point(&pubkey).into();
247 pubkey.ok_or(elliptic_curve::Error)
248 }
249 }
250
251 impl<C> From<PublicKey<C>> for JsonWebKeyPublicParameters
252 where
253 C: elliptic_curve::CurveArithmetic + JwkEcCurve,
254 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
255 C::FieldBytesSize: ModulusSize,
256 {
257 fn from(key: PublicKey<C>) -> Self {
258 (&key).into()
259 }
260 }
261
262 impl<C> From<&PublicKey<C>> for JsonWebKeyPublicParameters
263 where
264 C: elliptic_curve::CurveArithmetic + JwkEcCurve,
265 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
266 C::FieldBytesSize: ModulusSize,
267 {
268 fn from(key: &PublicKey<C>) -> Self {
269 Self::Ec(key.into())
270 }
271 }
272
273 impl<C> From<PublicKey<C>> for EcPublicParameters
274 where
275 C: elliptic_curve::CurveArithmetic + JwkEcCurve,
276 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
277 C::FieldBytesSize: ModulusSize,
278 {
279 fn from(key: PublicKey<C>) -> Self {
280 (&key).into()
281 }
282 }
283
284 impl<C> From<&PublicKey<C>> for EcPublicParameters
285 where
286 C: elliptic_curve::CurveArithmetic + JwkEcCurve,
287 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
288 C::FieldBytesSize: ModulusSize,
289 {
290 fn from(key: &PublicKey<C>) -> Self {
291 let point = key.to_encoded_point(false);
292 let Coordinates::Uncompressed { x, y } = point.coordinates() else {
293 unreachable!()
294 };
295 EcPublicParameters {
296 crv: C::CRV,
297 x: Base64UrlNoPad::new(x.to_vec()),
298 y: Base64UrlNoPad::new(y.to_vec()),
299 }
300 }
301 }
302}