1#![allow(clippy::needless_range_loop)]
10
11use super::bigint::BigInt;
44use super::rsa::{RsaPublicKey, RsaSecretKey, representative_in_range, rsa_decrypt_raw, rsa_encrypt_raw};
45use crate::Hasher;
46use crate::hash::ripemd160::Ripemd160;
47use crate::hash::sha1::Sha1;
48use crate::hash::sha3::{Sha3_256, Sha3_384, Sha3_512};
49use crate::hash::sha224::Sha224;
50use crate::hash::sha256::Sha256;
51use crate::hash::sha384::Sha384;
52use crate::hash::sha512::Sha512;
53
54#[derive(Clone, Copy, Debug, PartialEq)]
76pub enum HashAlg {
77 Sha1,
80 Sha224,
82 Sha256,
84 Sha384,
86 Sha512,
88 Sha3_256,
90 Sha3_384,
92 Sha3_512,
94 Ripemd160,
97}
98
99impl HashAlg {
100 fn digest_info_prefix(&self) -> &'static [u8] {
105 match self {
106 HashAlg::Sha1 => &[
109 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14,
110 ],
111 HashAlg::Sha224 => &[
115 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00,
116 0x04, 0x1c,
117 ],
118 HashAlg::Sha256 => &[
120 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
121 0x04, 0x20,
122 ],
123 HashAlg::Sha384 => &[
125 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00,
126 0x04, 0x30,
127 ],
128 HashAlg::Sha512 => &[
130 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00,
131 0x04, 0x40,
132 ],
133 HashAlg::Sha3_256 => &[
135 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08, 0x05, 0x00,
136 0x04, 0x20,
137 ],
138 HashAlg::Sha3_384 => &[
140 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09, 0x05, 0x00,
141 0x04, 0x30,
142 ],
143 HashAlg::Sha3_512 => &[
145 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0a, 0x05, 0x00,
146 0x04, 0x40,
147 ],
148 HashAlg::Ripemd160 => &[
151 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14,
152 ],
153 }
154 }
155
156 fn hash_len(&self) -> usize {
158 match self {
159 HashAlg::Sha1 | HashAlg::Ripemd160 => 20,
160 HashAlg::Sha224 => 28,
161 HashAlg::Sha256 | HashAlg::Sha3_256 => 32,
162 HashAlg::Sha384 | HashAlg::Sha3_384 => 48,
163 HashAlg::Sha512 | HashAlg::Sha3_512 => 64,
164 }
165 }
166}
167
168pub fn pkcs1v15_encrypt(pk: &RsaPublicKey, msg: &[u8], rng: &mut dyn FnMut(&mut [u8])) -> Vec<u8> {
173 let k = pk.modulus_byte_len();
174 assert!(
175 msg.len() <= k - 11,
176 "PKCS1v15 encrypt: message too long (max {} bytes, got {})",
177 k - 11,
178 msg.len()
179 );
180
181 let ps_len = k - msg.len() - 3;
183 let mut em = vec![0u8; k];
184 em[0] = 0x00;
185 em[1] = 0x02;
186
187 rng(&mut em[2..2 + ps_len]);
189 for b in em[2..2 + ps_len].iter_mut() {
190 while *b == 0 {
191 let mut tmp = [0u8; 1];
192 rng(&mut tmp);
193 *b = tmp[0];
194 }
195 }
196
197 em[2 + ps_len] = 0x00;
198 em[3 + ps_len..].copy_from_slice(msg);
199
200 let m = BigInt::from_be_bytes(&em);
201 let c = rsa_encrypt_raw(pk, &m);
202 c.to_be_bytes(k)
203}
204
205pub fn pkcs1v15_decrypt(sk: &RsaSecretKey, ct: &[u8]) -> Option<Vec<u8>> {
210 let k = sk.modulus_byte_len();
211 if ct.len() != k || k < 11 {
212 return None;
213 }
214
215 let c = BigInt::from_be_bytes(ct);
216 if !representative_in_range(&c, &sk.n) {
223 return None;
224 }
225 let m = rsa_decrypt_raw(sk, &c);
226 let em = m.to_be_bytes(k);
227
228 if em[0] != 0x00 || em[1] != 0x02 {
230 return None;
231 }
232
233 let mut sep = None;
235 for i in 2..em.len() {
236 if em[i] == 0x00 {
237 if i < 10 {
238 return None;
240 }
241 sep = Some(i);
242 break;
243 }
244 }
245
246 let sep = sep?;
247 Some(em[sep + 1..].to_vec())
248}
249
250pub fn pkcs1v15_sign(sk: &RsaSecretKey, hash: &[u8], hash_alg: HashAlg) -> Vec<u8> {
254 let k = sk.modulus_byte_len();
255 let prefix = hash_alg.digest_info_prefix();
256 let t_len = prefix.len() + hash_alg.hash_len();
257
258 assert!(hash.len() == hash_alg.hash_len(), "Hash length mismatch");
259 assert!(k >= t_len + 11, "Modulus too short for PKCS1v15 signature");
260
261 let ps_len = k - t_len - 3;
263 let mut em = vec![0u8; k];
264 em[0] = 0x00;
265 em[1] = 0x01;
266 for i in 0..ps_len {
267 em[2 + i] = 0xFF;
268 }
269 em[2 + ps_len] = 0x00;
270 em[3 + ps_len..3 + ps_len + prefix.len()].copy_from_slice(prefix);
271 em[3 + ps_len + prefix.len()..].copy_from_slice(hash);
272
273 let m = BigInt::from_be_bytes(&em);
274 let s = rsa_decrypt_raw(sk, &m); s.to_be_bytes(k)
276}
277
278pub fn pkcs1v15_verify(pk: &RsaPublicKey, hash: &[u8], hash_alg: HashAlg, sig: &[u8]) -> bool {
282 let k = pk.modulus_byte_len();
283 if sig.len() != k {
284 return false;
285 }
286 if hash.len() != hash_alg.hash_len() {
287 return false;
288 }
289
290 let s = BigInt::from_be_bytes(sig);
291 if !representative_in_range(&s, &pk.n) {
295 return false;
296 }
297 let m = rsa_encrypt_raw(pk, &s); let em = m.to_be_bytes(k);
299
300 let prefix = hash_alg.digest_info_prefix();
302 let t_len = prefix.len() + hash_alg.hash_len();
303 if k < t_len + 11 {
304 return false;
305 }
306
307 let ps_len = k - t_len - 3;
308 let mut expected = vec![0u8; k];
309 expected[0] = 0x00;
310 expected[1] = 0x01;
311 for i in 0..ps_len {
312 expected[2 + i] = 0xFF;
313 }
314 expected[2 + ps_len] = 0x00;
315 expected[3 + ps_len..3 + ps_len + prefix.len()].copy_from_slice(prefix);
316 expected[3 + ps_len + prefix.len()..].copy_from_slice(hash);
317
318 let mut diff = 0u8;
320 for (a, b) in em.iter().zip(expected.iter()) {
321 diff |= a ^ b;
322 }
323 diff == 0 && em.len() == expected.len()
324}
325
326pub fn pkcs1v15_sign_sha256(sk: &RsaSecretKey, message: &[u8]) -> Vec<u8> {
339 let hash = Sha256::hash(message);
340 pkcs1v15_sign(sk, &hash, HashAlg::Sha256)
341}
342
343pub fn pkcs1v15_verify_sha256(pk: &RsaPublicKey, message: &[u8], sig: &[u8]) -> bool {
345 let hash = Sha256::hash(message);
346 pkcs1v15_verify(pk, &hash, HashAlg::Sha256, sig)
347}
348
349macro_rules! convenience_pair {
350 ($sign_fn:ident, $verify_fn:ident, $hasher:ty, $alg:expr, $doc:literal) => {
351 #[doc = $doc]
352 pub fn $sign_fn(sk: &RsaSecretKey, message: &[u8]) -> Vec<u8> {
353 let hash = <$hasher as Hasher>::hash(message);
354 pkcs1v15_sign(sk, &hash, $alg)
355 }
356
357 #[doc = $doc]
358 pub fn $verify_fn(pk: &RsaPublicKey, message: &[u8], sig: &[u8]) -> bool {
359 let hash = <$hasher as Hasher>::hash(message);
360 pkcs1v15_verify(pk, &hash, $alg, sig)
361 }
362 };
363}
364
365convenience_pair!(
366 pkcs1v15_sign_sha1,
367 pkcs1v15_verify_sha1,
368 Sha1,
369 HashAlg::Sha1,
370 "Convenience: hash a message with SHA-1, then sign / verify. \
371 **Legacy**: do not use for new designs; SHA-1 is collision-broken."
372);
373
374convenience_pair!(
375 pkcs1v15_sign_sha224,
376 pkcs1v15_verify_sha224,
377 Sha224,
378 HashAlg::Sha224,
379 "Convenience: hash a message with SHA-224, then sign / verify."
380);
381
382convenience_pair!(
383 pkcs1v15_sign_sha384,
384 pkcs1v15_verify_sha384,
385 Sha384,
386 HashAlg::Sha384,
387 "Convenience: hash a message with SHA-384, then sign / verify."
388);
389
390convenience_pair!(
391 pkcs1v15_sign_sha512,
392 pkcs1v15_verify_sha512,
393 Sha512,
394 HashAlg::Sha512,
395 "Convenience: hash a message with SHA-512, then sign / verify."
396);
397
398convenience_pair!(
399 pkcs1v15_sign_sha3_256,
400 pkcs1v15_verify_sha3_256,
401 Sha3_256,
402 HashAlg::Sha3_256,
403 "Convenience: hash a message with SHA3-256, then sign / verify."
404);
405
406convenience_pair!(
407 pkcs1v15_sign_sha3_384,
408 pkcs1v15_verify_sha3_384,
409 Sha3_384,
410 HashAlg::Sha3_384,
411 "Convenience: hash a message with SHA3-384, then sign / verify."
412);
413
414convenience_pair!(
415 pkcs1v15_sign_sha3_512,
416 pkcs1v15_verify_sha3_512,
417 Sha3_512,
418 HashAlg::Sha3_512,
419 "Convenience: hash a message with SHA3-512, then sign / verify."
420);
421
422convenience_pair!(
423 pkcs1v15_sign_ripemd160,
424 pkcs1v15_verify_ripemd160,
425 Ripemd160,
426 HashAlg::Ripemd160,
427 "Convenience: hash a message with RIPEMD-160, then sign / verify. \
428 **Legacy**: included for compatibility with older systems \
429 (Bitcoin, some 2000s X.509 CAs); not recommended for new designs."
430);
431
432#[cfg(test)]
433mod tests {
434 use super::*;
435
436 fn test_rng() -> impl FnMut(&mut [u8]) {
437 let mut state: u64 = 0xdeadbeefcafebabe;
438 move |buf: &mut [u8]| {
439 for b in buf.iter_mut() {
440 state = state
441 .wrapping_mul(6364136223846793005)
442 .wrapping_add(1442695040888963407);
443 *b = (state >> 33) as u8;
444 }
445 }
446 }
447
448 #[test]
449 fn test_pkcs1v15_encrypt_decrypt_roundtrip() {
450 let mut rng = test_rng();
451 let (pk, sk) = super::super::rsa::rsa_keygen(512, &mut rng);
452 let msg = b"Hello, RSA!";
453 let ct = pkcs1v15_encrypt(&pk, msg, &mut rng);
454 let pt = pkcs1v15_decrypt(&sk, &ct).expect("decryption failed");
455 assert_eq!(&pt, msg);
456 }
457
458 #[test]
459 fn test_pkcs1v15_sign_verify_roundtrip() {
460 let mut rng = test_rng();
461 let (pk, sk) = super::super::rsa::rsa_keygen(512, &mut rng);
462 let message = b"Sign me!";
463 let sig = pkcs1v15_sign_sha256(&sk, message);
464 assert!(pkcs1v15_verify_sha256(&pk, message, &sig));
465 let mut bad_sig = sig.clone();
467 bad_sig[0] ^= 0xFF;
468 assert!(!pkcs1v15_verify_sha256(&pk, message, &bad_sig));
469 }
470
471 #[test]
481 fn pkcs1v15_all_supported_hashes_roundtrip() {
482 let mut rng = test_rng();
483 let (pk, sk) = super::super::rsa::rsa_keygen(1024, &mut rng);
484 let msg = b"hash flexibility test";
485
486 let sig = pkcs1v15_sign_sha1(&sk, msg);
488 assert!(pkcs1v15_verify_sha1(&pk, msg, &sig));
489 let sig = pkcs1v15_sign_sha224(&sk, msg);
491 assert!(pkcs1v15_verify_sha224(&pk, msg, &sig));
492 let sig = pkcs1v15_sign_sha256(&sk, msg);
494 assert!(pkcs1v15_verify_sha256(&pk, msg, &sig));
495 let sig = pkcs1v15_sign_sha384(&sk, msg);
497 assert!(pkcs1v15_verify_sha384(&pk, msg, &sig));
498 let sig = pkcs1v15_sign_sha512(&sk, msg);
500 assert!(pkcs1v15_verify_sha512(&pk, msg, &sig));
501 let sig = pkcs1v15_sign_sha3_256(&sk, msg);
503 assert!(pkcs1v15_verify_sha3_256(&pk, msg, &sig));
504 let sig = pkcs1v15_sign_sha3_384(&sk, msg);
506 assert!(pkcs1v15_verify_sha3_384(&pk, msg, &sig));
507 let sig = pkcs1v15_sign_sha3_512(&sk, msg);
509 assert!(pkcs1v15_verify_sha3_512(&pk, msg, &sig));
510 let sig = pkcs1v15_sign_ripemd160(&sk, msg);
512 assert!(pkcs1v15_verify_ripemd160(&pk, msg, &sig));
513 }
514
515 #[test]
525 fn pkcs1v15_hash_mismatch_rejected() {
526 let mut rng = test_rng();
527 let (pk, sk) = super::super::rsa::rsa_keygen(1024, &mut rng);
528 let msg = b"hash mismatch test";
529
530 let sig256 = pkcs1v15_sign_sha256(&sk, msg);
532 assert!(pkcs1v15_verify_sha256(&pk, msg, &sig256));
533
534 assert!(!pkcs1v15_verify_sha512(&pk, msg, &sig256));
538
539 assert!(!pkcs1v15_verify_sha3_256(&pk, msg, &sig256));
544
545 let sig512 = pkcs1v15_sign_sha512(&sk, msg);
547 assert!(pkcs1v15_verify_sha512(&pk, msg, &sig512));
548 assert!(!pkcs1v15_verify_sha256(&pk, msg, &sig512));
549
550 let sig3_256 = pkcs1v15_sign_sha3_256(&sk, msg);
553 assert!(pkcs1v15_verify_sha3_256(&pk, msg, &sig3_256));
554 assert!(!pkcs1v15_verify_sha256(&pk, msg, &sig3_256));
555 }
556
557 #[test]
563 fn hashalg_lengths_agree_with_hasher_output_len() {
564 assert_eq!(HashAlg::Sha1.hash_len(), <Sha1 as Hasher>::OUTPUT_LEN);
565 assert_eq!(HashAlg::Sha224.hash_len(), <Sha224 as Hasher>::OUTPUT_LEN);
566 assert_eq!(HashAlg::Sha256.hash_len(), <Sha256 as Hasher>::OUTPUT_LEN);
567 assert_eq!(HashAlg::Sha384.hash_len(), <Sha384 as Hasher>::OUTPUT_LEN);
568 assert_eq!(HashAlg::Sha512.hash_len(), <Sha512 as Hasher>::OUTPUT_LEN);
569 assert_eq!(HashAlg::Sha3_256.hash_len(), <Sha3_256 as Hasher>::OUTPUT_LEN);
570 assert_eq!(HashAlg::Sha3_384.hash_len(), <Sha3_384 as Hasher>::OUTPUT_LEN);
571 assert_eq!(HashAlg::Sha3_512.hash_len(), <Sha3_512 as Hasher>::OUTPUT_LEN);
572 assert_eq!(HashAlg::Ripemd160.hash_len(), <Ripemd160 as Hasher>::OUTPUT_LEN);
573 }
574}