1use mas_iana::jose::{
8 JsonWebKeyEcEllipticCurve, JsonWebKeyOkpEllipticCurve, JsonWebKeyType, JsonWebSignatureAlg,
9};
10use schemars::JsonSchema;
11use serde::{Deserialize, Serialize};
12use thiserror::Error;
13
14use super::{ParametersInfo, public_parameters::JsonWebKeyPublicParameters};
15use crate::base64::Base64UrlNoPad;
16
17#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
18#[serde(tag = "kty")]
19pub enum JsonWebKeyPrivateParameters {
20 #[serde(rename = "oct")]
21 Oct(OctPrivateParameters),
22
23 #[serde(rename = "RSA")]
24 Rsa(RsaPrivateParameters),
25
26 #[serde(rename = "EC")]
27 Ec(EcPrivateParameters),
28
29 #[serde(rename = "OKP")]
30 Okp(OkpPrivateParameters),
31}
32
33impl JsonWebKeyPrivateParameters {
34 #[must_use]
35 pub const fn oct(&self) -> Option<&OctPrivateParameters> {
36 match self {
37 Self::Oct(params) => Some(params),
38 _ => None,
39 }
40 }
41
42 #[must_use]
43 pub const fn rsa(&self) -> Option<&RsaPrivateParameters> {
44 match self {
45 Self::Rsa(params) => Some(params),
46 _ => None,
47 }
48 }
49
50 #[must_use]
51 pub const fn ec(&self) -> Option<&EcPrivateParameters> {
52 match self {
53 Self::Ec(params) => Some(params),
54 _ => None,
55 }
56 }
57
58 #[must_use]
59 pub const fn okp(&self) -> Option<&OkpPrivateParameters> {
60 match self {
61 Self::Okp(params) => Some(params),
62 _ => None,
63 }
64 }
65}
66
67impl ParametersInfo for JsonWebKeyPrivateParameters {
68 fn kty(&self) -> JsonWebKeyType {
69 match self {
70 Self::Oct(_) => JsonWebKeyType::Oct,
71 Self::Rsa(_) => JsonWebKeyType::Rsa,
72 Self::Ec(_) => JsonWebKeyType::Ec,
73 Self::Okp(_) => JsonWebKeyType::Okp,
74 }
75 }
76
77 fn possible_algs(&self) -> &[JsonWebSignatureAlg] {
78 match self {
79 JsonWebKeyPrivateParameters::Oct(p) => p.possible_algs(),
80 JsonWebKeyPrivateParameters::Rsa(p) => p.possible_algs(),
81 JsonWebKeyPrivateParameters::Ec(p) => p.possible_algs(),
82 JsonWebKeyPrivateParameters::Okp(p) => p.possible_algs(),
83 }
84 }
85}
86
87#[derive(Debug, Error)]
88#[error("can't extract a public key out of a symetric key")]
89pub struct SymetricKeyError;
90
91impl TryFrom<JsonWebKeyPrivateParameters> for JsonWebKeyPublicParameters {
92 type Error = SymetricKeyError;
93
94 fn try_from(value: JsonWebKeyPrivateParameters) -> Result<Self, Self::Error> {
95 match value {
96 JsonWebKeyPrivateParameters::Oct(_) => Err(SymetricKeyError),
97 JsonWebKeyPrivateParameters::Rsa(p) => Ok(JsonWebKeyPublicParameters::Rsa(p.into())),
98 JsonWebKeyPrivateParameters::Ec(p) => Ok(JsonWebKeyPublicParameters::Ec(p.into())),
99 JsonWebKeyPrivateParameters::Okp(p) => Ok(JsonWebKeyPublicParameters::Okp(p.into())),
100 }
101 }
102}
103
104#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
105pub struct OctPrivateParameters {
106 #[schemars(with = "String")]
108 k: Base64UrlNoPad,
109}
110
111impl ParametersInfo for OctPrivateParameters {
112 fn kty(&self) -> JsonWebKeyType {
113 JsonWebKeyType::Oct
114 }
115
116 fn possible_algs(&self) -> &[JsonWebSignatureAlg] {
117 &[
118 JsonWebSignatureAlg::Hs256,
119 JsonWebSignatureAlg::Hs384,
120 JsonWebSignatureAlg::Hs512,
121 ]
122 }
123}
124
125#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
126pub struct RsaPrivateParameters {
127 #[schemars(with = "String")]
129 n: Base64UrlNoPad,
130
131 #[schemars(with = "String")]
133 e: Base64UrlNoPad,
134
135 #[schemars(with = "String")]
137 d: Base64UrlNoPad,
138
139 #[schemars(with = "String")]
141 p: Base64UrlNoPad,
142
143 #[schemars(with = "String")]
145 q: Base64UrlNoPad,
146
147 #[schemars(with = "String")]
149 dp: Base64UrlNoPad,
150
151 #[schemars(with = "String")]
153 dq: Base64UrlNoPad,
154
155 #[schemars(with = "String")]
157 qi: Base64UrlNoPad,
158
159 #[serde(skip_serializing_if = "Option::is_none")]
161 oth: Option<Vec<RsaOtherPrimeInfo>>,
162}
163
164impl ParametersInfo for RsaPrivateParameters {
165 fn kty(&self) -> JsonWebKeyType {
166 JsonWebKeyType::Rsa
167 }
168
169 fn possible_algs(&self) -> &[JsonWebSignatureAlg] {
170 &[
171 JsonWebSignatureAlg::Rs256,
172 JsonWebSignatureAlg::Rs384,
173 JsonWebSignatureAlg::Rs512,
174 JsonWebSignatureAlg::Ps256,
175 JsonWebSignatureAlg::Ps384,
176 JsonWebSignatureAlg::Ps512,
177 ]
178 }
179}
180
181impl From<RsaPrivateParameters> for super::public_parameters::RsaPublicParameters {
182 fn from(params: RsaPrivateParameters) -> Self {
183 Self::new(params.n, params.e)
184 }
185}
186
187#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
188struct RsaOtherPrimeInfo {
189 #[schemars(with = "String")]
191 r: Base64UrlNoPad,
192
193 #[schemars(with = "String")]
195 d: Base64UrlNoPad,
196
197 #[schemars(with = "String")]
199 t: Base64UrlNoPad,
200}
201
202mod rsa_impls {
203 use rsa::{BigUint, RsaPrivateKey};
204
205 use super::RsaPrivateParameters;
206
207 impl TryFrom<RsaPrivateParameters> for RsaPrivateKey {
208 type Error = rsa::errors::Error;
209 fn try_from(value: RsaPrivateParameters) -> Result<Self, Self::Error> {
210 Self::try_from(&value)
211 }
212 }
213
214 impl TryFrom<&RsaPrivateParameters> for RsaPrivateKey {
215 type Error = rsa::errors::Error;
216
217 #[allow(clippy::many_single_char_names)]
218 fn try_from(value: &RsaPrivateParameters) -> Result<Self, Self::Error> {
219 let n = BigUint::from_bytes_be(value.n.as_bytes());
220 let e = BigUint::from_bytes_be(value.e.as_bytes());
221 let d = BigUint::from_bytes_be(value.d.as_bytes());
222
223 let primes = [&value.p, &value.q]
224 .into_iter()
225 .chain(value.oth.iter().flatten().map(|o| &o.r))
226 .map(|i| BigUint::from_bytes_be(i.as_bytes()))
227 .collect();
228
229 let key = RsaPrivateKey::from_components(n, e, d, primes)?;
230
231 key.validate()?;
232
233 Ok(key)
234 }
235 }
236}
237
238#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
239pub struct EcPrivateParameters {
240 pub(crate) crv: JsonWebKeyEcEllipticCurve,
241
242 #[schemars(with = "String")]
243 x: Base64UrlNoPad,
244
245 #[schemars(with = "String")]
246 y: Base64UrlNoPad,
247
248 #[schemars(with = "String")]
249 d: Base64UrlNoPad,
250}
251
252impl ParametersInfo for EcPrivateParameters {
253 fn kty(&self) -> JsonWebKeyType {
254 JsonWebKeyType::Ec
255 }
256
257 fn possible_algs(&self) -> &[JsonWebSignatureAlg] {
258 match self.crv {
259 JsonWebKeyEcEllipticCurve::P256 => &[JsonWebSignatureAlg::Es256],
260 JsonWebKeyEcEllipticCurve::P384 => &[JsonWebSignatureAlg::Es384],
261 JsonWebKeyEcEllipticCurve::P521 => &[JsonWebSignatureAlg::Es512],
262 JsonWebKeyEcEllipticCurve::Secp256K1 => &[JsonWebSignatureAlg::Es256K],
263 _ => &[],
264 }
265 }
266}
267
268impl From<EcPrivateParameters> for super::public_parameters::EcPublicParameters {
269 fn from(params: EcPrivateParameters) -> Self {
270 Self::new(params.crv, params.x, params.y)
271 }
272}
273
274mod ec_impls {
275 use elliptic_curve::{
276 AffinePoint, Curve, SecretKey,
277 sec1::{Coordinates, FromEncodedPoint, ModulusSize, ToEncodedPoint},
278 };
279
280 use super::{super::JwkEcCurve, EcPrivateParameters};
281 use crate::base64::Base64UrlNoPad;
282
283 impl<C> TryFrom<EcPrivateParameters> for SecretKey<C>
284 where
285 C: Curve,
286 {
287 type Error = elliptic_curve::Error;
288 fn try_from(value: EcPrivateParameters) -> Result<Self, Self::Error> {
289 Self::try_from(&value)
290 }
291 }
292
293 impl<C> TryFrom<&EcPrivateParameters> for SecretKey<C>
294 where
295 C: Curve,
296 {
297 type Error = elliptic_curve::Error;
298
299 fn try_from(value: &EcPrivateParameters) -> Result<Self, Self::Error> {
300 SecretKey::from_slice(value.d.as_bytes())
301 }
302 }
303
304 impl<C> From<SecretKey<C>> for EcPrivateParameters
305 where
306 C: elliptic_curve::CurveArithmetic + JwkEcCurve,
307 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
308 C::FieldBytesSize: ModulusSize,
309 {
310 fn from(key: SecretKey<C>) -> Self {
311 (&key).into()
312 }
313 }
314
315 impl<C> From<&SecretKey<C>> for EcPrivateParameters
316 where
317 C: elliptic_curve::CurveArithmetic + JwkEcCurve,
318 AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
319 C::FieldBytesSize: ModulusSize,
320 {
321 fn from(key: &SecretKey<C>) -> Self {
322 let point = key.public_key().to_encoded_point(false);
323 let Coordinates::Uncompressed { x, y } = point.coordinates() else {
324 unreachable!()
325 };
326 let d = key.to_bytes();
327 EcPrivateParameters {
328 crv: C::CRV,
329 x: Base64UrlNoPad::new(x.to_vec()),
330 y: Base64UrlNoPad::new(y.to_vec()),
331 d: Base64UrlNoPad::new(d.to_vec()),
332 }
333 }
334 }
335}
336
337#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
338pub struct OkpPrivateParameters {
339 crv: JsonWebKeyOkpEllipticCurve,
340
341 #[schemars(with = "String")]
342 x: Base64UrlNoPad,
343}
344
345impl ParametersInfo for OkpPrivateParameters {
346 fn kty(&self) -> JsonWebKeyType {
347 JsonWebKeyType::Okp
348 }
349
350 fn possible_algs(&self) -> &[JsonWebSignatureAlg] {
351 &[JsonWebSignatureAlg::EdDsa]
352 }
353}
354
355impl From<OkpPrivateParameters> for super::public_parameters::OkpPublicParameters {
356 fn from(params: OkpPrivateParameters) -> Self {
357 Self::new(params.crv, params.x)
358 }
359}