jwt_next/algorithm/rust_crypto/
asymmetric.rs1use crate::algorithm::{AlgorithmType, SigningAlgorithm, VerifyingAlgorithm};
2use crate::error::Error;
3use crate::SEPARATOR;
4
5use base64::Engine;
6use digest::Digest;
7use p256::pkcs8::{DecodePrivateKey, DecodePublicKey};
8use rsa::pkcs1::DecodeRsaPrivateKey;
9use rsa::{RsaPrivateKey, RsaPublicKey};
10use signature::{DigestSigner, DigestVerifier, SignatureEncoding};
11
12#[derive(Clone, Debug)]
13pub enum VerifyingKey {
14 RS256(Box<rsa::pkcs1v15::VerifyingKey<sha2::Sha256>>),
15 RS384(Box<rsa::pkcs1v15::VerifyingKey<sha2::Sha384>>),
16 RS512(Box<rsa::pkcs1v15::VerifyingKey<sha2::Sha512>>),
17 EC256(Box<p256::ecdsa::VerifyingKey>),
18 EC384(Box<p384::ecdsa::VerifyingKey>),
19}
20
21impl VerifyingKey {
22 pub fn from_ec256(key: p256::PublicKey) -> Self {
23 Self::EC256(p256::ecdsa::VerifyingKey::from(key).into())
24 }
25
26 pub fn from_ec384(key: p384::PublicKey) -> Self {
27 Self::EC384(p384::ecdsa::VerifyingKey::from(key).into())
28 }
29
30 pub fn from_rsa256(key: RsaPublicKey) -> Self {
31 Self::RS256(rsa::pkcs1v15::VerifyingKey::new(key).into())
32 }
33
34 pub fn from_rsa384(key: RsaPublicKey) -> Self {
35 Self::RS384(rsa::pkcs1v15::VerifyingKey::new(key).into())
36 }
37
38 pub fn from_rsa512(key: RsaPublicKey) -> Self {
39 Self::RS512(rsa::pkcs1v15::VerifyingKey::new(key).into())
40 }
41}
42
43#[derive(Clone, Debug)]
44pub enum SigningKey {
45 RS256(Box<rsa::pkcs1v15::SigningKey<sha2::Sha256>>),
46 RS384(Box<rsa::pkcs1v15::SigningKey<sha2::Sha384>>),
47 RS512(Box<rsa::pkcs1v15::SigningKey<sha2::Sha512>>),
48 EC256(Box<p256::ecdsa::SigningKey>),
49 EC384(Box<p384::ecdsa::SigningKey>),
50}
51
52impl SigningKey {
53 pub fn from_ec256(key: p256::SecretKey) -> Self {
54 Self::EC256(p256::ecdsa::SigningKey::from(key).into())
55 }
56
57 pub fn from_ec384(key: p384::SecretKey) -> Self {
58 Self::EC384(p384::ecdsa::SigningKey::from(key).into())
59 }
60
61 pub fn from_rsa256(key: RsaPrivateKey) -> Self {
62 Self::RS256(rsa::pkcs1v15::SigningKey::new(key).into())
63 }
64
65 pub fn from_rsa384(key: RsaPrivateKey) -> Self {
66 Self::RS384(rsa::pkcs1v15::SigningKey::new(key).into())
67 }
68
69 pub fn from_rsa512(key: RsaPrivateKey) -> Self {
70 Self::RS512(rsa::pkcs1v15::SigningKey::new(key).into())
71 }
72}
73
74pub use ::{digest, ecdsa, p256, rsa, signature};
75
76#[derive(Clone, Debug)]
77pub enum PublicKey {
78 RSA(Box<RsaPublicKey>),
79 EC256(Box<p256::PublicKey>),
80 EC384(Box<p384::PublicKey>),
81}
82
83impl PublicKey {
84 pub fn from_pem_bytes(encoded: &[u8]) -> Result<Self, Error> {
85 Self::from_pem(std::str::from_utf8(encoded).map_err(|_| Error::InvalidKey)?)
86 }
87
88 pub fn from_pem(encoded: &str) -> Result<Self, Error> {
89 if let Ok(ec) = encoded.parse::<p384::PublicKey>() {
90 Ok(PublicKey::EC384(ec.into()))
91 } else if let Ok(ec) = encoded.parse::<p256::PublicKey>() {
92 Ok(PublicKey::EC256(ec.into()))
93 } else if let Ok(rsa) = rsa::RsaPublicKey::from_public_key_pem(encoded) {
94 Ok(PublicKey::RSA(rsa.into()))
95 } else {
96 Err(Error::InvalidKey)
97 }
98 }
99
100 pub fn into_rsa(self) -> Result<RsaPublicKey, Self> {
101 match self {
102 PublicKey::RSA(rsa) => Ok(*rsa),
103 _ => Err(self),
104 }
105 }
106
107 pub fn into_ec256(self) -> Result<p256::PublicKey, Self> {
108 match self {
109 PublicKey::EC256(ec) => Ok(*ec),
110 _ => Err(self),
111 }
112 }
113
114 pub fn into_ec384(self) -> Result<p384::PublicKey, Self> {
115 match self {
116 PublicKey::EC384(ec) => Ok(*ec),
117 _ => Err(self),
118 }
119 }
120}
121
122#[derive(Clone, Debug)]
123pub enum PrivateKey {
124 RSA(Box<RsaPrivateKey>),
125 EC256(Box<p256::SecretKey>),
126 EC384(Box<p384::SecretKey>),
127}
128
129impl PrivateKey {
130 pub fn from_pem_bytes(encoded: &[u8]) -> Result<Self, Error> {
131 Self::from_pem(std::str::from_utf8(encoded).map_err(|_| Error::InvalidKey)?)
132 }
133
134 pub fn from_pem(pem: &str) -> Result<Self, Error> {
135 if let Ok(ec) = pem.parse::<p384::SecretKey>() {
136 Ok(PrivateKey::EC384(ec.into()))
137 } else if let Ok(ec) = pem.parse::<p256::SecretKey>() {
138 Ok(PrivateKey::EC256(ec.into()))
139 } else if let Ok(rsa) = rsa::RsaPrivateKey::from_pkcs8_pem(pem) {
140 Ok(PrivateKey::RSA(rsa.into()))
141 } else if let Ok(rsa) = rsa::RsaPrivateKey::from_pkcs1_pem(pem) {
142 Ok(PrivateKey::RSA(rsa.into()))
143 } else {
144 Err(Error::InvalidKey)
145 }
146 }
147
148 pub fn into_rsa(self) -> Result<RsaPrivateKey, Self> {
149 match self {
150 PrivateKey::RSA(rsa) => Ok(*rsa),
151 _ => Err(self),
152 }
153 }
154
155 pub fn into_ec256(self) -> Result<p256::SecretKey, Self> {
156 match self {
157 PrivateKey::EC256(ec) => Ok(*ec),
158 _ => Err(self),
159 }
160 }
161
162 pub fn into_ec384(self) -> Result<p384::SecretKey, Self> {
163 match self {
164 PrivateKey::EC384(ec) => Ok(*ec),
165 _ => Err(self),
166 }
167 }
168}
169
170pub struct AsymmetricKeyWithDigest<K> {
171 key: K,
172}
173
174impl<K> AsymmetricKeyWithDigest<K> {
175 pub fn new(key: K) -> Self {
176 Self { key }
177 }
178}
179
180impl SigningAlgorithm for AsymmetricKeyWithDigest<SigningKey> {
181 fn algorithm_type(&self) -> AlgorithmType {
182 match self.key {
183 SigningKey::RS256(_) => AlgorithmType::Rs256,
184 SigningKey::RS384(_) => AlgorithmType::Rs384,
185 SigningKey::RS512(_) => AlgorithmType::Rs512,
186 SigningKey::EC256(_) => AlgorithmType::Es256,
187 SigningKey::EC384(_) => AlgorithmType::Es384,
188 }
189 }
190
191 fn sign(&self, header: &str, claims: &str) -> Result<String, Error> {
192 macro_rules! short_hand {
193 ($key:ident, $hash:ty, $sig:ty) => {
194 let mut digest = <$hash>::new();
195
196 digest.update(header.as_bytes());
197 digest.update(SEPARATOR.as_bytes());
198 digest.update(claims.as_bytes());
199
200 let signed: $sig = $key.try_sign_digest(digest)?;
201
202 return Ok(
203 base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(signed.to_bytes())
204 );
205 };
206 }
207
208 match &self.key {
209 SigningKey::RS256(key) => {
210 short_hand!(key, sha2::Sha256, rsa::pkcs1v15::Signature);
211 }
212 SigningKey::RS384(key) => {
213 short_hand!(key, sha2::Sha384, rsa::pkcs1v15::Signature);
214 }
215 SigningKey::RS512(key) => {
216 short_hand!(key, sha2::Sha512, rsa::pkcs1v15::Signature);
217 }
218 SigningKey::EC256(key) => {
219 short_hand!(key, sha2::Sha256, p256::ecdsa::Signature);
220 }
221 SigningKey::EC384(key) => {
222 short_hand!(key, sha2::Sha384, p384::ecdsa::Signature);
223 }
224 }
225 }
226}
227
228impl VerifyingAlgorithm for AsymmetricKeyWithDigest<VerifyingKey> {
229 fn algorithm_type(&self) -> AlgorithmType {
230 match self.key {
231 VerifyingKey::RS256(_) => AlgorithmType::Rs256,
232 VerifyingKey::RS384(_) => AlgorithmType::Rs384,
233 VerifyingKey::RS512(_) => AlgorithmType::Rs512,
234 VerifyingKey::EC256(_) => AlgorithmType::Es256,
235 VerifyingKey::EC384(_) => AlgorithmType::Es384,
236 }
237 }
238
239 fn verify_bytes(&self, header: &str, claims: &str, signature: &[u8]) -> Result<bool, Error> {
240 macro_rules! short_hand {
241 ($key:ident, $hash:ty, $sig:ty) => {
242 let mut digest = <$hash>::new();
243
244 digest.update(header.as_bytes());
245 digest.update(SEPARATOR.as_bytes());
246 digest.update(claims.as_bytes());
247
248 let signature = <$sig>::try_from(signature).map_err(|_| Error::InvalidSignature)?;
249
250 return Ok($key.verify_digest(digest, &signature).is_ok());
251 };
252 }
253
254 match &self.key {
255 VerifyingKey::RS256(key) => {
256 short_hand!(key, sha2::Sha256, rsa::pkcs1v15::Signature);
257 }
258 VerifyingKey::RS384(key) => {
259 short_hand!(key, sha2::Sha384, rsa::pkcs1v15::Signature);
260 }
261 VerifyingKey::RS512(key) => {
262 short_hand!(key, sha2::Sha512, rsa::pkcs1v15::Signature);
263 }
264 VerifyingKey::EC256(key) => {
265 short_hand!(key, sha2::Sha256, p256::ecdsa::Signature);
266 }
267 VerifyingKey::EC384(key) => {
268 short_hand!(key, sha2::Sha384, p384::ecdsa::Signature);
269 }
270 }
271 }
272}
273
274#[cfg(test)]
275mod tests {
276 use super::*;
277
278 use crate::algorithm::AlgorithmType::*;
279 use crate::algorithm::{SigningAlgorithm, VerifyingAlgorithm};
280 use crate::error::Error;
281 use crate::header::PrecomputedAlgorithmOnlyHeader as AlgOnly;
282 use crate::ToBase64;
283
284 const CLAIMS: &str = "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9";
286
287 const RS256_SIGNATURE: &str =
288 "cQsAHF2jHvPGFP5zTD8BgoJrnzEx6JNQCpupebWLFnOc2r_punDDTylI6Ia4JZNkvy2dQP-7W-DEbFQ3oaarHsDndqUgwf9iYlDQxz4Rr2nEZX1FX0-FMEgFPeQpdwveCgjtTYUbVy37ijUySN_rW-xZTrsh_Ug-ica8t-zHRIw";
289
290 const PREGENERATED_ES256_SIGNATURE: &str =
291 "6SgeIURSNz_qFcxsKQOWZmi_ALiBctj_ZINvce4AOa-OQn9QI6lh8P78FTZx5LQtOleF3XeBlGIAdYms_VPecA";
292
293 #[test]
294 fn rs256_sign() -> Result<(), Error> {
295 let key = PrivateKey::from_pem_bytes(include_bytes!("../../../test/rs256-private.pem"))?;
296 let signer = AsymmetricKeyWithDigest::new(SigningKey::from_rsa256(key.into_rsa().unwrap()));
297 let result = signer.sign(&AlgOnly(Rs256).to_base64()?, CLAIMS)?;
298 assert_eq!(result, RS256_SIGNATURE);
299 Ok(())
300 }
301
302 #[test]
303 fn rs256_verify() -> Result<(), Error> {
304 let key = PublicKey::from_pem_bytes(include_bytes!("../../../test/rs256-public.pem"))?;
305 let verifier =
306 AsymmetricKeyWithDigest::new(VerifyingKey::from_rsa256(key.into_rsa().unwrap()));
307 assert!(
308 verifier.verify(&AlgOnly(Rs256).to_base64()?, CLAIMS, RS256_SIGNATURE)?,
309 "signature should be valid"
310 );
311 Ok(())
312 }
313
314 #[test]
315 fn es256_sign() -> Result<(), Error> {
316 let key = PrivateKey::from_pem_bytes(include_bytes!("../../../test/es256-private.pem"))?;
317 let signer =
318 AsymmetricKeyWithDigest::new(SigningKey::from_ec256(key.into_ec256().unwrap()));
319 let signature = signer.sign(&AlgOnly(Es256).to_base64()?, CLAIMS)?;
320
321 let key = PublicKey::from_pem_bytes(include_bytes!("../../../test/es256-public.pem"))?;
322 let verifier =
323 AsymmetricKeyWithDigest::new(VerifyingKey::from_ec256(key.into_ec256().unwrap()));
324 assert!(
325 verifier.verify(&AlgOnly(Es256).to_base64()?, CLAIMS, &signature)?,
326 "signature should be valid"
327 );
328 Ok(())
329 }
330
331 #[test]
332 fn es256_verify() -> Result<(), Error> {
333 let key = PublicKey::from_pem_bytes(include_bytes!("../../../test/es256-public.pem"))?;
334 let verifier =
335 AsymmetricKeyWithDigest::new(VerifyingKey::from_ec256(key.into_ec256().unwrap()));
336 assert!(
337 verifier.verify(
338 &AlgOnly(Es256).to_base64()?,
339 CLAIMS,
340 PREGENERATED_ES256_SIGNATURE
341 )?,
342 "signature should be valid"
343 );
344
345 Ok(())
346 }
347
348 #[test]
349 fn genric_public_key_parse() -> Result<(), Error> {
350 match PublicKey::from_pem_bytes(include_bytes!("../../../test/rs256-public.pem")) {
351 Ok(PublicKey::RSA(_)) => {}
352 _ => panic!("invalid rsa key"),
353 }
354
355 match PublicKey::from_pem_bytes(include_bytes!("../../../test/es256-public.pem")) {
356 Ok(PublicKey::EC256(_)) => {}
357 _ => panic!("invalid ec key"),
358 }
359
360 Ok(())
361 }
362
363 #[test]
364 fn genric_private_key_parse() -> Result<(), Error> {
365 match PrivateKey::from_pem_bytes(include_bytes!("../../../test/rs256-private.pem")) {
366 Ok(PrivateKey::RSA(_)) => {}
367 _ => panic!("invalid rsa key"),
368 }
369
370 match PrivateKey::from_pem_bytes(include_bytes!("../../../test/es256-private.pem")) {
371 Ok(PrivateKey::EC256(_)) => {}
372 _ => panic!("invalid ec key"),
373 }
374
375 Ok(())
376 }
377}