1#[cfg(feature = "random")]
2use alloc::boxed::Box;
3
4use constant_time_eq::constant_time_eq;
5#[cfg(feature = "random")]
6use crypto::mldsa::{MlDsa44SecretKey, MlDsa65SecretKey, MlDsa87SecretKey};
7use crypto::{
8 Hash, Hasher,
9 blake3::Blake3,
10 curve25519::ed25519,
11 hmac::Hmac,
12 mldsa::{
13 ML_DSA_44_SIGNATURE_SIZE, ML_DSA_65_SIGNATURE_SIZE, ML_DSA_87_SIGNATURE_SIZE, MlDsa44PublicKey,
14 MlDsa65PublicKey, MlDsa87PublicKey,
15 },
16 p256, p384, p521, rsa,
17 sha2::{Sha256, Sha384, Sha512},
18};
19
20use crate::{Algorithm, EcCurve, Error, Jwk, JwkCrypto, OkpCurve};
21
22pub(crate) const SIGNATURE_MAX_SIZE: usize = 4627; pub trait Signer {
25 fn sign(&self, message: &[u8]) -> Result<Signature, Error>;
26 fn algorithm(&self) -> Algorithm;
27}
28
29pub trait Verifier {
30 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), Error>;
31 fn algorithm(&self) -> Algorithm;
32}
33
34#[derive(Clone, Copy)]
39pub struct Signature {
40 value: [u8; SIGNATURE_MAX_SIZE],
41 length: usize,
42}
43
44impl core::ops::Deref for Signature {
45 type Target = [u8];
46
47 #[inline]
48 fn deref(&self) -> &[u8] {
49 &self.value[..self.length as usize]
50 }
51}
52
53impl AsRef<[u8]> for Signature {
54 #[inline]
55 fn as_ref(&self) -> &[u8] {
56 &self.value[..self.length]
57 }
58}
59
60impl TryFrom<&[u8]> for Signature {
61 type Error = Error;
62
63 #[inline]
64 fn try_from(signature: &[u8]) -> Result<Self, Self::Error> {
65 let length = signature.len();
66 if length > SIGNATURE_MAX_SIZE {
67 return Err(Error::InvalidSignature);
68 }
69
70 let mut value = [0u8; SIGNATURE_MAX_SIZE];
71 value[..length].copy_from_slice(signature);
72
73 return Ok(Signature {
74 value,
75 length,
76 });
77 }
78}
79
80impl<const N: usize> TryFrom<[u8; N]> for Signature {
81 type Error = Error;
82
83 #[inline]
84 fn try_from(signature: [u8; N]) -> Result<Self, Self::Error> {
85 signature.as_slice().try_into()
86 }
87}
88
89impl<const N: usize> TryFrom<&[u8; N]> for Signature {
90 type Error = Error;
91
92 #[inline]
93 fn try_from(signature: &[u8; N]) -> Result<Self, Self::Error> {
94 signature.as_slice().try_into()
95 }
96}
97
98#[allow(clippy::large_enum_variant)] pub enum Key<'a> {
124 Secret(SecretKey<'a>),
126
127 Ed25519Public(ed25519::PublicKey),
129
130 Ed25519Secret(ed25519::SecretKey),
132
133 P256Public(p256::PublicKey),
135
136 P256Secret(p256::SecretKey),
138
139 P384Public(p384::PublicKey),
141
142 P521Public(p521::PublicKey),
144
145 P521Secret(p521::SecretKey),
147
148 Rsa(RsaPublicKey),
150
151 MlDsa44Public(MlDsa44PublicKey),
153
154 #[cfg(feature = "random")]
158 MlDsa44Secret(MlDsa44SecretKey),
159
160 MlDsa65Public(MlDsa65PublicKey),
162
163 #[cfg(feature = "random")]
170 MlDsa65Secret(Box<MlDsa65SecretKey>),
171
172 MlDsa87Public(MlDsa87PublicKey),
174
175 #[cfg(feature = "random")]
182 MlDsa87Secret(Box<MlDsa87SecretKey>),
183}
184
185impl<'a> TryFrom<&'a Jwk> for Key<'a> {
186 type Error = Error;
187
188 fn try_from(jwk: &'a Jwk) -> Result<Self, Self::Error> {
189 match &jwk.crypto {
190 JwkCrypto::Oct {
191 ..
192 } => Ok(Key::Secret(SecretKey::try_from(jwk)?)),
193 JwkCrypto::Okp {
194 curve: OkpCurve::Ed25519,
195 d: Some(_),
196 ..
197 } => Ok(Key::Ed25519Secret(ed25519::SecretKey::try_from(jwk)?)),
198 JwkCrypto::Okp {
199 curve: OkpCurve::Ed25519,
200 ..
201 } => Ok(Key::Ed25519Public(ed25519::PublicKey::try_from(jwk)?)),
202 JwkCrypto::Ec {
203 curve: EcCurve::P256,
204 d: Some(_),
205 ..
206 } => Ok(Key::P256Secret(p256::SecretKey::try_from(jwk)?)),
207 JwkCrypto::Ec {
208 curve: EcCurve::P256, ..
209 } => Ok(Key::P256Public(p256::PublicKey::try_from(jwk)?)),
210 JwkCrypto::Ec {
211 curve: EcCurve::P384, ..
212 } => Ok(Key::P384Public(p384::PublicKey::try_from(jwk)?)),
213 JwkCrypto::Ec {
214 curve: EcCurve::P521,
215 d: Some(_),
216 ..
217 } => Ok(Key::P521Secret(p521::SecretKey::try_from(jwk)?)),
218 JwkCrypto::Ec {
219 curve: EcCurve::P521, ..
220 } => Ok(Key::P521Public(p521::PublicKey::try_from(jwk)?)),
221 JwkCrypto::Rsa {
222 ..
223 } => Ok(Key::Rsa(RsaPublicKey::try_from(jwk)?)),
224 JwkCrypto::Akp {
225 private_key: Some(_), ..
226 } => match jwk.algorithm {
227 #[cfg(feature = "random")]
228 Algorithm::MlDsa44 => Ok(Key::MlDsa44Secret(MlDsa44SecretKey::try_from(jwk)?)),
229 #[cfg(feature = "random")]
230 Algorithm::MlDsa65 => Ok(Key::MlDsa65Secret(alloc::boxed::Box::new(MlDsa65SecretKey::try_from(jwk)?))),
231 #[cfg(feature = "random")]
232 Algorithm::MlDsa87 => Ok(Key::MlDsa87Secret(alloc::boxed::Box::new(MlDsa87SecretKey::try_from(jwk)?))),
233 _ => Err(Error::InvalidKey),
234 },
235 JwkCrypto::Akp {
236 private_key: None, ..
237 } => match jwk.algorithm {
238 Algorithm::MlDsa44 => Ok(Key::MlDsa44Public(MlDsa44PublicKey::try_from(jwk)?)),
239 Algorithm::MlDsa65 => Ok(Key::MlDsa65Public(MlDsa65PublicKey::try_from(jwk)?)),
240 Algorithm::MlDsa87 => Ok(Key::MlDsa87Public(MlDsa87PublicKey::try_from(jwk)?)),
241 _ => Err(Error::InvalidKey),
242 },
243 }
244 }
245}
246
247impl Key<'_> {
248 fn jose_algorithm(&self) -> Algorithm {
250 match self {
251 Key::Secret(key) => Signer::algorithm(key),
252 Key::Ed25519Public(_) | Key::Ed25519Secret(_) => Algorithm::EdDSA,
253 Key::P256Public(_) | Key::P256Secret(_) => Algorithm::ES256,
254 Key::P384Public(_) => Algorithm::ES384,
255 Key::P521Public(_) | Key::P521Secret(_) => Algorithm::ES512,
256 Key::Rsa(key) => Verifier::algorithm(key),
257 Key::MlDsa44Public(_) => Algorithm::MlDsa44,
258 #[cfg(feature = "random")]
259 Key::MlDsa44Secret(_) => Algorithm::MlDsa44,
260 Key::MlDsa65Public(_) => Algorithm::MlDsa65,
261 #[cfg(feature = "random")]
262 Key::MlDsa65Secret(_) => Algorithm::MlDsa65,
263 Key::MlDsa87Public(_) => Algorithm::MlDsa87,
264 #[cfg(feature = "random")]
265 Key::MlDsa87Secret(_) => Algorithm::MlDsa87,
266 }
267 }
268
269 pub fn is_secret_key(&self) -> bool {
271 match self {
272 Key::Secret(_) | Key::Ed25519Secret(_) | Key::P256Secret(_) | Key::P521Secret(_) => true,
273 #[cfg(feature = "random")]
274 Key::MlDsa44Secret(_) | Key::MlDsa65Secret(_) | Key::MlDsa87Secret(_) => true,
275 _ => false,
276 }
277 }
278}
279
280impl Signer for Key<'_> {
281 fn sign(&self, message: &[u8]) -> Result<Signature, Error> {
282 match self {
283 Key::Secret(key) => Signer::sign(key, message),
284 Key::Ed25519Secret(key) => Signer::sign(key, message),
285 Key::P256Secret(key) => Signer::sign(key, message),
286 Key::P521Secret(key) => Signer::sign(key, message),
287 #[cfg(feature = "random")]
288 Key::MlDsa44Secret(key) => Signer::sign(key, message),
289 #[cfg(feature = "random")]
290 Key::MlDsa65Secret(key) => Signer::sign(key.as_ref(), message),
291 #[cfg(feature = "random")]
292 Key::MlDsa87Secret(key) => Signer::sign(key.as_ref(), message),
293 _ => Err(Error::InvalidKey),
294 }
295 }
296
297 #[inline(always)]
298 fn algorithm(&self) -> Algorithm {
299 self.jose_algorithm()
300 }
301}
302
303impl Verifier for Key<'_> {
304 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), Error> {
305 match self {
306 Key::Secret(key) => Verifier::verify(key, message, signature),
307 Key::Ed25519Public(key) => Verifier::verify(key, message, signature),
308 Key::Ed25519Secret(key) => Verifier::verify(&key.public_key(), message, signature),
309 Key::P256Public(key) => Verifier::verify(key, message, signature),
310 Key::P256Secret(key) => Verifier::verify(&key.public_key(), message, signature),
311 Key::P384Public(key) => Verifier::verify(key, message, signature),
312 Key::P521Public(key) => Verifier::verify(key, message, signature),
313 Key::P521Secret(key) => Verifier::verify(&key.public_key(), message, signature),
314 Key::Rsa(key) => Verifier::verify(key, message, signature),
315 Key::MlDsa44Public(key) => Verifier::verify(key, message, signature),
316 #[cfg(feature = "random")]
317 Key::MlDsa44Secret(key) => Verifier::verify(&key.public_key(), message, signature),
318 Key::MlDsa65Public(key) => Verifier::verify(key, message, signature),
319 #[cfg(feature = "random")]
320 Key::MlDsa65Secret(key) => Verifier::verify(&key.public_key(), message, signature),
321 Key::MlDsa87Public(key) => Verifier::verify(key, message, signature),
322 #[cfg(feature = "random")]
323 Key::MlDsa87Secret(key) => Verifier::verify(&key.public_key(), message, signature),
324 }
325 }
326
327 #[inline(always)]
328 fn algorithm(&self) -> Algorithm {
329 self.jose_algorithm()
330 }
331}
332
333impl core::fmt::Debug for Key<'_> {
334 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
335 f.write_str(match self {
336 Key::Secret(_) => "Key::Secret",
337 Key::Ed25519Public(_) => "Key::Ed25519Public",
338 Key::Ed25519Secret(_) => "Key::Ed25519Secret",
339 Key::P256Public(_) => "Key::P256Public",
340 Key::P256Secret(_) => "Key::P256Secret",
341 Key::P384Public(_) => "Key::P384Public",
342 Key::P521Public(_) => "Key::P521Public",
343 Key::P521Secret(_) => "Key::P521Secret",
344 Key::Rsa(_) => "Key::Rsa",
345 Key::MlDsa44Public(_) => "Key::MlDsa44Public",
346 #[cfg(feature = "random")]
347 Key::MlDsa44Secret(_) => "Key::MlDsa44Secret",
348 Key::MlDsa65Public(_) => "Key::MlDsa65Public",
349 #[cfg(feature = "random")]
350 Key::MlDsa65Secret(_) => "Key::MlDsa65Secret",
351 Key::MlDsa87Public(_) => "Key::MlDsa87Public",
352 #[cfg(feature = "random")]
353 Key::MlDsa87Secret(_) => "Key::MlDsa87Secret",
354 })
355 }
356}
357
358pub struct SecretKey<'a> {
370 pub(crate) key: &'a [u8],
371 pub(crate) algorithm: Algorithm,
372}
373
374impl<'a> SecretKey<'a> {
375 #[inline(always)]
377 pub fn new(algorithm: Algorithm, key: &'a [u8]) -> Self {
378 Self {
379 key,
380 algorithm,
381 }
382 }
383
384 fn mac(&self, message: &[u8]) -> Result<Hash, Error> {
386 match self.algorithm {
387 Algorithm::BLAKE3 => {
388 let key: &[u8; 32] = self.key.try_into().map_err(|_| Error::InvalidKey)?;
389 Ok(Blake3::keyed_hash(key, message))
390 }
391 Algorithm::HS256 => self.hmac::<Sha256>(message),
392 Algorithm::HS384 => self.hmac::<Sha384>(message),
393 Algorithm::HS512 => self.hmac::<Sha512>(message),
394 _ => Err(Error::InvalidKey),
395 }
396 }
397
398 fn hmac<H: Hasher>(&self, message: &[u8]) -> Result<Hash, Error> {
400 if self.key.len() < 16 {
401 return Err(Error::InvalidKey);
402 }
403
404 Ok(Hmac::<H>::mac(self.key, message))
405 }
406}
407
408impl Signer for SecretKey<'_> {
409 fn sign(&self, message: &[u8]) -> Result<Signature, Error> {
410 return self.mac(message)?.as_ref().try_into();
411 }
412
413 #[inline(always)]
414 fn algorithm(&self) -> Algorithm {
415 self.algorithm
416 }
417}
418
419impl Verifier for SecretKey<'_> {
420 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), Error> {
421 let mac = self.mac(message)?;
422 return match constant_time_eq(mac.as_ref(), signature) {
423 true => Ok(()),
424 false => Err(Error::InvalidSignature),
425 };
426 }
427
428 #[inline(always)]
429 fn algorithm(&self) -> Algorithm {
430 self.algorithm
431 }
432}
433
434impl Signer for ed25519::SecretKey {
439 fn sign(&self, message: &[u8]) -> Result<Signature, Error> {
440 return ed25519::SecretKey::sign(self, message).as_ref().try_into();
441 }
442
443 #[inline(always)]
444 fn algorithm(&self) -> Algorithm {
445 Algorithm::EdDSA
446 }
447}
448
449impl Verifier for ed25519::PublicKey {
450 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), Error> {
451 let signature = signature.try_into().map_err(|_| Error::InvalidSignature)?;
452 return ed25519::PublicKey::verify(self, message, &signature).map_err(|_| Error::InvalidSignature);
453 }
454
455 #[inline(always)]
456 fn algorithm(&self) -> Algorithm {
457 Algorithm::EdDSA
458 }
459}
460
461impl Signer for p256::SecretKey {
466 fn sign(&self, message: &[u8]) -> Result<Signature, Error> {
467 return p256::SecretKey::sign(self, message)
468 .map_err(|err| Error::Unspecified(alloc::format!("error signing message: {err:?}")))?
469 .as_ref()
470 .try_into();
471 }
472
473 #[inline(always)]
474 fn algorithm(&self) -> Algorithm {
475 Algorithm::ES256
476 }
477}
478
479impl Verifier for p256::PublicKey {
480 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), Error> {
481 let signature = signature.try_into().map_err(|_| Error::InvalidSignature)?;
482 return p256::PublicKey::verify(self, message, &signature).map_err(|_| Error::InvalidSignature);
483 }
484
485 #[inline(always)]
486 fn algorithm(&self) -> Algorithm {
487 Algorithm::ES256
488 }
489}
490
491impl Verifier for p384::PublicKey {
496 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), Error> {
497 let signature = signature.try_into().map_err(|_| Error::InvalidSignature)?;
498 return p384::PublicKey::verify(self, message, &signature).map_err(|_| Error::InvalidSignature);
499 }
500
501 #[inline(always)]
502 fn algorithm(&self) -> Algorithm {
503 Algorithm::ES384
504 }
505}
506
507impl Signer for p521::SecretKey {
512 fn sign(&self, message: &[u8]) -> Result<Signature, Error> {
513 return p521::SecretKey::sign(self, message)
514 .map_err(|err| Error::Unspecified(alloc::format!("error signing message: {err:?}")))?
515 .as_ref()
516 .try_into();
517 }
518
519 #[inline(always)]
520 fn algorithm(&self) -> Algorithm {
521 Algorithm::ES512
522 }
523}
524
525impl Verifier for p521::PublicKey {
526 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), Error> {
527 let signature = signature.try_into().map_err(|_| Error::InvalidSignature)?;
528 return p521::PublicKey::verify(self, message, &signature).map_err(|_| Error::InvalidSignature);
529 }
530
531 #[inline(always)]
532 fn algorithm(&self) -> Algorithm {
533 Algorithm::ES512
534 }
535}
536
537#[cfg(feature = "random")]
542impl Signer for MlDsa44SecretKey {
543 fn sign(&self, message: &[u8]) -> Result<Signature, Error> {
544 return MlDsa44SecretKey::sign(self, message, b"")
545 .map_err(|_| Error::InvalidSignature)?
546 .as_ref()
547 .try_into();
548 }
549
550 #[inline(always)]
551 fn algorithm(&self) -> Algorithm {
552 Algorithm::MlDsa44
553 }
554}
555
556impl Verifier for MlDsa44PublicKey {
557 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), Error> {
558 let signature: &[u8; ML_DSA_44_SIGNATURE_SIZE] = signature.try_into().map_err(|_| Error::InvalidSignature)?;
559 return MlDsa44PublicKey::verify(self, message, signature, b"").map_err(|_| Error::InvalidSignature);
560 }
561
562 #[inline(always)]
563 fn algorithm(&self) -> Algorithm {
564 Algorithm::MlDsa44
565 }
566}
567
568#[cfg(feature = "random")]
573impl Signer for MlDsa65SecretKey {
574 fn sign(&self, message: &[u8]) -> Result<Signature, Error> {
575 return MlDsa65SecretKey::sign(self, message, b"")
576 .map_err(|_| Error::InvalidSignature)?
577 .as_ref()
578 .try_into();
579 }
580
581 #[inline(always)]
582 fn algorithm(&self) -> Algorithm {
583 Algorithm::MlDsa65
584 }
585}
586
587impl Verifier for MlDsa65PublicKey {
588 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), Error> {
589 let signature: &[u8; ML_DSA_65_SIGNATURE_SIZE] = signature.try_into().map_err(|_| Error::InvalidSignature)?;
590 return MlDsa65PublicKey::verify(self, message, signature, b"").map_err(|_| Error::InvalidSignature);
591 }
592
593 #[inline(always)]
594 fn algorithm(&self) -> Algorithm {
595 Algorithm::MlDsa65
596 }
597}
598
599#[cfg(feature = "random")]
604impl Signer for MlDsa87SecretKey {
605 fn sign(&self, message: &[u8]) -> Result<Signature, Error> {
606 return MlDsa87SecretKey::sign(self, message, b"")
607 .map_err(|_| Error::InvalidSignature)?
608 .as_ref()
609 .try_into();
610 }
611
612 #[inline(always)]
613 fn algorithm(&self) -> Algorithm {
614 Algorithm::MlDsa87
615 }
616}
617
618impl Verifier for MlDsa87PublicKey {
619 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), Error> {
620 let signature: &[u8; ML_DSA_87_SIGNATURE_SIZE] = signature.try_into().map_err(|_| Error::InvalidSignature)?;
621 return MlDsa87PublicKey::verify(self, message, signature, b"").map_err(|_| Error::InvalidSignature);
622 }
623
624 #[inline(always)]
625 fn algorithm(&self) -> Algorithm {
626 Algorithm::MlDsa87
627 }
628}
629
630pub struct RsaPublicKey {
663 pub(crate) key: rsa::PublicKey,
664 pub(crate) alg: Algorithm,
665}
666
667impl RsaPublicKey {
668 pub(crate) fn from_n_e(alg: Algorithm, n: &[u8], e: &[u8]) -> Result<Self, Error> {
679 if !matches!(
680 alg,
681 Algorithm::RS256
682 | Algorithm::RS384
683 | Algorithm::RS512
684 | Algorithm::PS256
685 | Algorithm::PS384
686 | Algorithm::PS512
687 ) {
688 return Err(Error::InvalidKey);
689 }
690 let key = rsa::PublicKey::from_n_e(n, e).map_err(|_| Error::InvalidKey)?;
691 Ok(RsaPublicKey {
692 key,
693 alg,
694 })
695 }
696
697 pub fn from_pkcs1_der(pkcs1_der: &[u8], alg: Algorithm) -> Result<Self, Error> {
707 if !matches!(
708 alg,
709 Algorithm::RS256
710 | Algorithm::RS384
711 | Algorithm::RS512
712 | Algorithm::PS256
713 | Algorithm::PS384
714 | Algorithm::PS512
715 ) {
716 return Err(Error::InvalidKey);
717 }
718 let key = rsa::PublicKey::from_pkcs1_der(pkcs1_der).map_err(|_| Error::InvalidKey)?;
719 Ok(RsaPublicKey {
720 key,
721 alg,
722 })
723 }
724}
725
726impl Verifier for RsaPublicKey {
727 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), Error> {
728 match self.alg {
729 Algorithm::RS256 => {
730 let digest = Sha256::hash(message);
731 self.key
732 .verify_pkcs1_v1_5(signature, digest.as_ref(), rsa::DIGEST_INFO_SHA256_PREFIX)
733 }
734 Algorithm::RS384 => {
735 let digest = Sha384::hash(message);
736 self.key
737 .verify_pkcs1_v1_5(signature, digest.as_ref(), rsa::DIGEST_INFO_SHA384_PREFIX)
738 }
739 Algorithm::RS512 => {
740 let digest = Sha512::hash(message);
741 self.key
742 .verify_pkcs1_v1_5(signature, digest.as_ref(), rsa::DIGEST_INFO_SHA512_PREFIX)
743 }
744 Algorithm::PS256 => self.key.verify_pss::<Sha256>(signature, message, Sha256::OUTPUT_SIZE),
745 Algorithm::PS384 => self.key.verify_pss::<Sha384>(signature, message, Sha384::OUTPUT_SIZE),
746 Algorithm::PS512 => self.key.verify_pss::<Sha512>(signature, message, Sha512::OUTPUT_SIZE),
747 _ => return Err(Error::InvalidKey),
748 }
749 .map_err(|_| Error::InvalidSignature)
750 }
751
752 #[inline(always)]
753 fn algorithm(&self) -> Algorithm {
754 self.alg
755 }
756}