1mod blinded_signing_key;
13mod signature;
14mod signing_key;
15mod verifying_key;
16
17pub use self::{
18 blinded_signing_key::BlindedSigningKey, signature::Signature, signing_key::SigningKey,
19 verifying_key::VerifyingKey,
20};
21
22use alloc::vec::Vec;
23use core::fmt::{self, Debug};
24use crypto_bigint::BoxedUint;
25
26use digest::{Digest, FixedOutputReset};
27use rand_core::TryCryptoRng;
28
29use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad};
30use crate::algorithms::pss::*;
31use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt};
32use crate::errors::{Error, Result};
33use crate::traits::PublicKeyParts;
34use crate::traits::SignatureScheme;
35use crate::{RsaPrivateKey, RsaPublicKey};
36
37#[cfg(feature = "encoding")]
38use {
39 crate::encoding::ID_RSASSA_PSS,
40 const_oid::AssociatedOid,
41 pkcs1::RsaPssParams,
42 spki::{der::Any, AlgorithmIdentifierOwned},
43};
44
45pub struct Pss<D> {
47 pub blinded: bool,
49
50 pub digest: D,
52
53 pub salt_len: Option<usize>,
56}
57
58impl<D> Default for Pss<D>
59where
60 D: Digest,
61{
62 fn default() -> Self {
63 Self::new()
64 }
65}
66
67impl<D> Pss<D>
68where
69 D: Digest,
70{
71 pub fn new() -> Self {
74 Self::new_with_salt(<D as Digest>::output_size())
75 }
76
77 pub fn new_with_salt(len: usize) -> Self {
79 Self {
80 blinded: false,
81 digest: D::new(),
82 salt_len: Some(len),
83 }
84 }
85
86 pub fn new_blinded() -> Self {
89 Self::new_blinded_with_salt(<D as Digest>::output_size())
90 }
91
92 pub fn new_blinded_with_salt(len: usize) -> Self {
95 Self {
96 blinded: true,
97 digest: D::new(),
98 salt_len: Some(len),
99 }
100 }
101}
102
103impl<D> SignatureScheme for Pss<D>
104where
105 D: Digest + FixedOutputReset,
106{
107 fn sign<Rng: TryCryptoRng + ?Sized>(
108 mut self,
109 rng: Option<&mut Rng>,
110 priv_key: &RsaPrivateKey,
111 hashed: &[u8],
112 ) -> Result<Vec<u8>> {
113 sign(
114 rng.ok_or(Error::InvalidPaddingScheme)?,
115 self.blinded,
116 priv_key,
117 hashed,
118 self.salt_len.expect("salt_len to be Some"),
119 &mut self.digest,
120 )
121 }
122
123 fn verify(mut self, pub_key: &RsaPublicKey, hashed: &[u8], sig: &[u8]) -> Result<()> {
124 verify(
125 pub_key,
126 hashed,
127 &BoxedUint::from_be_slice_vartime(sig),
128 sig.len(),
129 &mut self.digest,
130 self.salt_len,
131 )
132 }
133}
134
135impl<D> Debug for Pss<D> {
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 f.debug_struct("PSS")
138 .field("blinded", &self.blinded)
139 .field("digest", &"...")
140 .field("salt_len", &self.salt_len)
141 .finish()
142 }
143}
144
145pub(crate) fn verify<D>(
146 pub_key: &RsaPublicKey,
147 hashed: &[u8],
148 sig: &BoxedUint,
149 sig_len: usize,
150 digest: &mut D,
151 salt_len: Option<usize>,
152) -> Result<()>
153where
154 D: Digest + FixedOutputReset,
155{
156 if sig_len != pub_key.size() {
157 return Err(Error::Verification);
158 }
159 let raw = rsa_encrypt(pub_key, sig)?;
160 let mut em = uint_to_be_pad(raw, pub_key.size())?;
161
162 emsa_pss_verify(hashed, &mut em, salt_len, digest, pub_key.n().bits() as _)
163}
164
165pub(crate) fn verify_digest<D>(
166 pub_key: &RsaPublicKey,
167 hashed: &[u8],
168 sig: &BoxedUint,
169 salt_len: Option<usize>,
170) -> Result<()>
171where
172 D: Digest + FixedOutputReset,
173{
174 let n = pub_key.n();
175 if sig >= n.as_ref() || sig.bits_precision() != pub_key.n_bits_precision() {
176 return Err(Error::Verification);
177 }
178
179 let mut em = uint_to_be_pad(rsa_encrypt(pub_key, sig)?, pub_key.size())?;
180
181 emsa_pss_verify_digest::<D>(hashed, &mut em, salt_len, pub_key.n().bits() as _)
182}
183
184pub(crate) fn sign<T, D>(
190 rng: &mut T,
191 blind: bool,
192 priv_key: &RsaPrivateKey,
193 hashed: &[u8],
194 salt_len: usize,
195 digest: &mut D,
196) -> Result<Vec<u8>>
197where
198 T: TryCryptoRng + ?Sized,
199 D: Digest + FixedOutputReset,
200{
201 let mut salt = vec![0; salt_len];
202 rng.try_fill_bytes(&mut salt[..]).map_err(|_| Error::Rng)?;
203
204 sign_pss_with_salt(blind.then_some(rng), priv_key, hashed, &salt, digest)
205}
206
207pub(crate) fn sign_digest<T, D>(
208 rng: &mut T,
209 blind: bool,
210 priv_key: &RsaPrivateKey,
211 hashed: &[u8],
212 salt_len: usize,
213) -> Result<Vec<u8>>
214where
215 T: TryCryptoRng + ?Sized,
216 D: Digest + FixedOutputReset,
217{
218 let mut salt = vec![0; salt_len];
219 rng.try_fill_bytes(&mut salt[..]).map_err(|_| Error::Rng)?;
220
221 sign_pss_with_salt_digest::<_, D>(blind.then_some(rng), priv_key, hashed, &salt)
222}
223
224fn sign_pss_with_salt<T, D>(
230 blind_rng: Option<&mut T>,
231 priv_key: &RsaPrivateKey,
232 hashed: &[u8],
233 salt: &[u8],
234 digest: &mut D,
235) -> Result<Vec<u8>>
236where
237 T: TryCryptoRng + ?Sized,
238 D: Digest + FixedOutputReset,
239{
240 let em_bits = priv_key.n().bits() - 1;
241
242 let em = emsa_pss_encode(hashed, em_bits as _, salt, digest)?;
243
244 let em = BoxedUint::from_be_slice(&em, priv_key.n_bits_precision())?;
245 let raw = rsa_decrypt_and_check(priv_key, blind_rng, &em)?;
246 uint_to_zeroizing_be_pad(raw, priv_key.size())
247}
248
249fn sign_pss_with_salt_digest<T, D>(
250 blind_rng: Option<&mut T>,
251 priv_key: &RsaPrivateKey,
252 hashed: &[u8],
253 salt: &[u8],
254) -> Result<Vec<u8>>
255where
256 T: TryCryptoRng + ?Sized,
257 D: Digest + FixedOutputReset,
258{
259 let em_bits = priv_key.n().bits() - 1;
260 let em = emsa_pss_encode_digest::<D>(hashed, em_bits as _, salt)?;
261
262 let em = BoxedUint::from_be_slice(&em, priv_key.n_bits_precision())?;
263 uint_to_zeroizing_be_pad(
264 rsa_decrypt_and_check(priv_key, blind_rng, &em)?,
265 priv_key.size(),
266 )
267}
268
269#[cfg(feature = "encoding")]
271pub fn get_default_pss_signature_algo_id<D>() -> spki::Result<AlgorithmIdentifierOwned>
272where
273 D: Digest + AssociatedOid,
274{
275 let salt_len: u8 = <D as Digest>::output_size() as u8;
276 get_pss_signature_algo_id::<D>(salt_len)
277}
278
279#[cfg(feature = "encoding")]
280fn get_pss_signature_algo_id<D>(salt_len: u8) -> spki::Result<AlgorithmIdentifierOwned>
281where
282 D: Digest + AssociatedOid,
283{
284 let pss_params = RsaPssParams::new::<D>(salt_len);
285
286 Ok(AlgorithmIdentifierOwned {
287 oid: ID_RSASSA_PSS,
288 parameters: Some(Any::encode_from(&pss_params)?),
289 })
290}
291
292#[cfg(all(test, feature = "encoding"))]
293mod test {
294 use crate::pss::{BlindedSigningKey, Pss, Signature, SigningKey, VerifyingKey};
295 use crate::{RsaPrivateKey, RsaPublicKey};
296
297 use crate::traits::PublicKeyParts;
298 use hex_literal::hex;
299 use pkcs1::DecodeRsaPrivateKey;
300 use rand::rngs::ChaCha8Rng;
301 use rand_core::SeedableRng;
302 use rstest::rstest;
303 use sha1::{Digest, Sha1};
304 use signature::hazmat::{PrehashVerifier, RandomizedPrehashSigner};
305 use signature::{DigestVerifier, Keypair, RandomizedDigestSigner, RandomizedSigner, Verifier};
306
307 fn get_private_key() -> RsaPrivateKey {
308 let pem = r#"
320-----BEGIN RSA PRIVATE KEY-----
321MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
322fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
323/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu
324RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/
325EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A
326IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS
327tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
328-----END RSA PRIVATE KEY-----"#;
329
330 RsaPrivateKey::from_pkcs1_pem(pem).unwrap()
331 }
332
333 #[rstest]
334 #[case(
335 "test\n",
336 hex!(
337 "6f86f26b14372b2279f79fb6807c49889835c204f71e38249b4c5601462da8ae"
338 "30f26ffdd9c13f1c75eee172bebe7b7c89f2f1526c722833b9737d6c172a962f"
339 ),
340 true,
341 )]
342 #[case(
343 "test\n",
344 hex!(
345 "6f86f26b14372b2279f79fb6807c49889835c204f71e38249b4c5601462da8ae"
346 "30f26ffdd9c13f1c75eee172bebe7b7c89f2f1526c722833b9737d6c172a962e"
347 ),
348 false,
349 )]
350 fn test_verify_pss(#[case] text: &str, #[case] sig: [u8; 64], #[case] expected: bool) {
351 let priv_key = get_private_key();
352 let pub_key: RsaPublicKey = priv_key.into();
353
354 let digest = Sha1::digest(text.as_bytes()).to_vec();
355 let result = pub_key.verify(Pss::<Sha1>::new(), &digest, &sig);
356
357 match expected {
358 true => result.expect("failed to verify"),
359 false => {
360 result.expect_err("expected verifying error");
361 }
362 }
363 }
364
365 #[rstest]
366 #[case(
367 "test\n",
368 hex!(
369 "6f86f26b14372b2279f79fb6807c49889835c204f71e38249b4c5601462da8ae"
370 "30f26ffdd9c13f1c75eee172bebe7b7c89f2f1526c722833b9737d6c172a962f"
371 ),
372 true,
373 )]
374 #[case(
375 "test\n",
376 hex!(
377 "6f86f26b14372b2279f79fb6807c49889835c204f71e38249b4c5601462da8ae"
378 "30f26ffdd9c13f1c75eee172bebe7b7c89f2f1526c722833b9737d6c172a962e"
379 ),
380 false,
381 )]
382 fn test_verify_pss_signer(#[case] text: &str, #[case] sig: [u8; 64], #[case] expected: bool) {
383 let priv_key = get_private_key();
384 let pub_key: RsaPublicKey = priv_key.into();
385 let verifying_key: VerifyingKey<Sha1> = VerifyingKey::new(pub_key);
386
387 let result = verifying_key.verify(
388 text.as_bytes(),
389 &Signature::try_from(sig.as_slice()).unwrap(),
390 );
391 match expected {
392 true => result.expect("failed to verify"),
393 false => {
394 result.expect_err("expected verifying error");
395 }
396 }
397 }
398
399 #[rstest]
400 #[case(
401 "test\n",
402 hex!(
403 "6f86f26b14372b2279f79fb6807c49889835c204f71e38249b4c5601462da8ae"
404 "30f26ffdd9c13f1c75eee172bebe7b7c89f2f1526c722833b9737d6c172a962f"
405 ),
406 true,
407 )]
408 #[case(
409 "test\n",
410 hex!(
411 "6f86f26b14372b2279f79fb6807c49889835c204f71e38249b4c5601462da8ae"
412 "30f26ffdd9c13f1c75eee172bebe7b7c89f2f1526c722833b9737d6c172a962e"
413 ),
414 false,
415 )]
416 fn test_verify_pss_digest_signer(
417 #[case] text: &str,
418 #[case] sig: [u8; 64],
419 #[case] expected: bool,
420 ) {
421 let priv_key = get_private_key();
422 let pub_key: RsaPublicKey = priv_key.into();
423 let verifying_key = VerifyingKey::new(pub_key);
424
425 let result = verifying_key.verify_digest(
426 |digest: &mut Sha1| {
427 digest.update(text.as_bytes());
428 Ok(())
429 },
430 &Signature::try_from(sig.as_slice()).unwrap(),
431 );
432 match expected {
433 true => result.expect("failed to verify"),
434 false => {
435 result.expect_err("expected verifying error");
436 }
437 }
438 }
439
440 #[rstest]
441 #[case("test\n")]
442 fn test_sign_and_verify_roundtrip(#[case] test: &str) {
443 let priv_key = get_private_key();
444
445 let mut rng = ChaCha8Rng::from_seed([42; 32]);
446
447 let digest = Sha1::digest(test.as_bytes()).to_vec();
448 let sig = priv_key
449 .sign_with_rng(&mut rng, Pss::<Sha1>::new(), &digest)
450 .expect("failed to sign");
451
452 priv_key
453 .to_public_key()
454 .verify(Pss::<Sha1>::new(), &digest, &sig)
455 .expect("failed to verify");
456 }
457
458 #[rstest]
459 #[case("test\n")]
460 fn test_sign_blinded_and_verify_roundtrip(#[case] test: &str) {
461 let priv_key = get_private_key();
462
463 let mut rng = ChaCha8Rng::from_seed([42; 32]);
464
465 let digest = Sha1::digest(test.as_bytes()).to_vec();
466 let sig = priv_key
467 .sign_with_rng(&mut rng, Pss::<Sha1>::new_blinded(), &digest)
468 .expect("failed to sign");
469
470 priv_key
471 .to_public_key()
472 .verify(Pss::<Sha1>::new(), &digest, &sig)
473 .expect("failed to verify");
474 }
475
476 #[rstest]
477 #[case("test\n")]
478 fn test_sign_and_verify_roundtrip_signer(#[case] test: &str) {
479 let priv_key = get_private_key();
480
481 let mut rng = ChaCha8Rng::from_seed([42; 32]);
482 let signing_key = SigningKey::<Sha1>::new(priv_key);
483 let verifying_key = signing_key.verifying_key();
484
485 let sig = signing_key.sign_with_rng(&mut rng, test.as_bytes());
486 verifying_key
487 .verify(test.as_bytes(), &sig)
488 .expect("failed to verify");
489 }
490
491 #[rstest]
492 #[case("test\n")]
493 fn test_sign_and_verify_roundtrip_blinded_signer(#[case] test: &str) {
494 let priv_key = get_private_key();
495
496 let mut rng = ChaCha8Rng::from_seed([42; 32]);
497 let signing_key = BlindedSigningKey::<Sha1>::new(priv_key);
498 let verifying_key = signing_key.verifying_key();
499
500 let sig = signing_key.sign_with_rng(&mut rng, test.as_bytes());
501 verifying_key
502 .verify(test.as_bytes(), &sig)
503 .expect("failed to verify");
504 }
505
506 #[rstest]
507 #[case("test\n")]
508 fn test_sign_and_verify_roundtrip_digest_signer(#[case] test: &str) {
509 let priv_key = get_private_key();
510
511 let mut rng = ChaCha8Rng::from_seed([42; 32]);
512 let signing_key = SigningKey::new(priv_key);
513 let verifying_key = signing_key.verifying_key();
514
515 let sig = signing_key
516 .sign_digest_with_rng(&mut rng, |digest: &mut Sha1| digest.update(test.as_bytes()));
517
518 verifying_key
519 .verify_digest(
520 |digest: &mut Sha1| {
521 digest.update(test.as_bytes());
522 Ok(())
523 },
524 &sig,
525 )
526 .expect("failed to verify");
527 }
528
529 #[rstest]
530 #[case("test\n")]
531 fn test_sign_and_verify_roundtrip_blinded_digest_signer(#[case] test: &str) {
532 let priv_key = get_private_key();
533
534 let mut rng = ChaCha8Rng::from_seed([42; 32]);
535 let signing_key = BlindedSigningKey::<Sha1>::new(priv_key);
536 let verifying_key = signing_key.verifying_key();
537
538 let sig = signing_key
539 .sign_digest_with_rng(&mut rng, |digest: &mut Sha1| digest.update(test.as_bytes()));
540
541 verifying_key
542 .verify_digest(
543 |digest: &mut Sha1| {
544 digest.update(test.as_bytes());
545 Ok(())
546 },
547 &sig,
548 )
549 .expect("failed to verify");
550 }
551
552 #[rstest]
553 #[case(
554 "test\n",
555 hex!(
556 "6f86f26b14372b2279f79fb6807c49889835c204f71e38249b4c5601462da8ae"
557 "30f26ffdd9c13f1c75eee172bebe7b7c89f2f1526c722833b9737d6c172a962f"
558 ),
559 true
560 )]
561 #[case(
562 "test\n",
563 hex!(
564 "6f86f26b14372b2279f79fb6807c49889835c204f71e38249b4c5601462da8ae"
565 "30f26ffdd9c13f1c75eee172bebe7b7c89f2f1526c722833b9737d6c172a962e"
566 ),
567 false
568 )]
569 fn test_verify_pss_hazmat(#[case] text: &str, #[case] sig: [u8; 64], #[case] expected: bool) {
570 let text = Sha1::digest(text);
571 let priv_key = get_private_key();
572
573 let pub_key: RsaPublicKey = priv_key.into();
574 let verifying_key = VerifyingKey::<Sha1>::new(pub_key);
575
576 let result = verifying_key
577 .verify_prehash(text.as_ref(), &Signature::try_from(sig.as_slice()).unwrap());
578 match expected {
579 true => result.expect("failed to verify"),
580 false => {
581 result.expect_err("expected verifying error");
582 }
583 }
584 }
585
586 #[rstest]
587 #[case("test\n")]
588 fn test_sign_and_verify_pss_hazmat(#[case] test: &str) {
589 let test = &Sha1::digest(test);
590 let priv_key = get_private_key();
591
592 let mut rng = ChaCha8Rng::from_seed([42; 32]);
593 let signing_key = SigningKey::<Sha1>::new(priv_key);
594 let verifying_key = signing_key.verifying_key();
595
596 let sig = signing_key
597 .sign_prehash_with_rng(&mut rng, test)
598 .expect("failed to sign");
599 verifying_key
600 .verify_prehash(test, &sig)
601 .expect("failed to verify");
602 }
603
604 #[rstest]
605 #[case("test\n")]
606 fn test_sign_and_verify_pss_blinded_hazmat(#[case] test: &str) {
607 let priv_key = get_private_key();
608
609 let test = &Sha1::digest(test);
610 let mut rng = ChaCha8Rng::from_seed([42; 32]);
611 let signing_key = BlindedSigningKey::<Sha1>::new(priv_key);
612 let verifying_key = signing_key.verifying_key();
613
614 let sig = signing_key
615 .sign_prehash_with_rng(&mut rng, test)
616 .expect("failed to sign");
617 verifying_key
618 .verify_prehash(test, &sig)
619 .expect("failed to verify");
620 }
621
622 #[test]
623 fn test_sign_and_verify_2049bit_key() {
625 let plaintext = "Hello\n";
626 let mut rng = ChaCha8Rng::from_seed([42; 32]);
627 for i in 0..10 {
628 println!("round {i}");
629 let priv_key = RsaPrivateKey::new(&mut rng, 2049).unwrap();
630
631 let digest = Sha1::digest(plaintext.as_bytes()).to_vec();
632 let sig = priv_key
633 .sign_with_rng(&mut rng, Pss::<Sha1>::new(), &digest)
634 .expect("failed to sign");
635
636 priv_key
637 .to_public_key()
638 .verify(Pss::<Sha1>::new(), &digest, &sig)
639 .expect("failed to verify");
640 }
641 }
642
643 #[rstest]
646 #[case("test\n")]
647 fn test_sign_and_verify_pss_differing_salt_len(#[case] test: &str) {
648 let priv_key = get_private_key();
649
650 let mut rng = ChaCha8Rng::from_seed([42; 32]);
651
652 let signing_keys = [
654 SigningKey::<Sha1>::new(priv_key.clone()),
656 SigningKey::<Sha1>::new_with_salt_len(
658 priv_key.clone(),
659 priv_key.size() - Sha1::output_size() - 2,
660 ),
661 SigningKey::<Sha1>::new_with_salt_len(priv_key.clone(), 0),
663 ];
664
665 let verifying_key = VerifyingKey::<Sha1>::new_with_auto_salt_len(priv_key.to_public_key());
667
668 for signing_key in &signing_keys {
669 let sig = signing_key.sign_with_rng(&mut rng, test.as_bytes());
670 verifying_key
671 .verify(test.as_bytes(), &sig)
672 .expect("verification to succeed");
673 }
674 }
675}