1use super::bigint::BigInt;
34use super::rsa::{RsaPublicKey, RsaSecretKey, rsa_decrypt_raw, rsa_encrypt_raw};
35use crate::Hasher;
36use crate::hash::ripemd160::Ripemd160;
37use crate::hash::sha1::Sha1;
38use crate::hash::sha3::{Sha3_256, Sha3_384, Sha3_512};
39use crate::hash::sha256::Sha256;
40use crate::hash::sha384::Sha384;
41use crate::hash::sha512::Sha512;
42
43#[derive(Clone, Copy, Debug, PartialEq)]
65pub enum HashAlg {
66 Sha1,
69 Sha256,
71 Sha384,
73 Sha512,
75 Sha3_256,
77 Sha3_384,
79 Sha3_512,
81 Ripemd160,
84}
85
86impl HashAlg {
87 fn digest_info_prefix(&self) -> &'static [u8] {
92 match self {
93 HashAlg::Sha1 => &[
96 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14,
97 ],
98 HashAlg::Sha256 => &[
100 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
101 0x04, 0x20,
102 ],
103 HashAlg::Sha384 => &[
105 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00,
106 0x04, 0x30,
107 ],
108 HashAlg::Sha512 => &[
110 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00,
111 0x04, 0x40,
112 ],
113 HashAlg::Sha3_256 => &[
115 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08, 0x05, 0x00,
116 0x04, 0x20,
117 ],
118 HashAlg::Sha3_384 => &[
120 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09, 0x05, 0x00,
121 0x04, 0x30,
122 ],
123 HashAlg::Sha3_512 => &[
125 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0a, 0x05, 0x00,
126 0x04, 0x40,
127 ],
128 HashAlg::Ripemd160 => &[
131 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14,
132 ],
133 }
134 }
135
136 fn hash_len(&self) -> usize {
138 match self {
139 HashAlg::Sha1 | HashAlg::Ripemd160 => 20,
140 HashAlg::Sha256 | HashAlg::Sha3_256 => 32,
141 HashAlg::Sha384 | HashAlg::Sha3_384 => 48,
142 HashAlg::Sha512 | HashAlg::Sha3_512 => 64,
143 }
144 }
145}
146
147pub fn pkcs1v15_encrypt(pk: &RsaPublicKey, msg: &[u8], rng: &mut dyn FnMut(&mut [u8])) -> Vec<u8> {
152 let k = pk.modulus_byte_len();
153 assert!(
154 msg.len() <= k - 11,
155 "PKCS1v15 encrypt: message too long (max {} bytes, got {})",
156 k - 11,
157 msg.len()
158 );
159
160 let ps_len = k - msg.len() - 3;
162 let mut em = vec![0u8; k];
163 em[0] = 0x00;
164 em[1] = 0x02;
165
166 rng(&mut em[2..2 + ps_len]);
168 for b in em[2..2 + ps_len].iter_mut() {
169 while *b == 0 {
170 let mut tmp = [0u8; 1];
171 rng(&mut tmp);
172 *b = tmp[0];
173 }
174 }
175
176 em[2 + ps_len] = 0x00;
177 em[3 + ps_len..].copy_from_slice(msg);
178
179 let m = BigInt::from_be_bytes(&em);
180 let c = rsa_encrypt_raw(pk, &m);
181 c.to_be_bytes(k)
182}
183
184pub fn pkcs1v15_decrypt(sk: &RsaSecretKey, ct: &[u8]) -> Option<Vec<u8>> {
189 let k = sk.modulus_byte_len();
190 if ct.len() != k || k < 11 {
191 return None;
192 }
193
194 let c = BigInt::from_be_bytes(ct);
195 let m = rsa_decrypt_raw(sk, &c);
196 let em = m.to_be_bytes(k);
197
198 if em[0] != 0x00 || em[1] != 0x02 {
200 return None;
201 }
202
203 let mut sep = None;
205 for i in 2..em.len() {
206 if em[i] == 0x00 {
207 if i < 10 {
208 return None;
210 }
211 sep = Some(i);
212 break;
213 }
214 }
215
216 let sep = sep?;
217 Some(em[sep + 1..].to_vec())
218}
219
220pub fn pkcs1v15_sign(sk: &RsaSecretKey, hash: &[u8], hash_alg: HashAlg) -> Vec<u8> {
224 let k = sk.modulus_byte_len();
225 let prefix = hash_alg.digest_info_prefix();
226 let t_len = prefix.len() + hash_alg.hash_len();
227
228 assert!(hash.len() == hash_alg.hash_len(), "Hash length mismatch");
229 assert!(k >= t_len + 11, "Modulus too short for PKCS1v15 signature");
230
231 let ps_len = k - t_len - 3;
233 let mut em = vec![0u8; k];
234 em[0] = 0x00;
235 em[1] = 0x01;
236 for i in 0..ps_len {
237 em[2 + i] = 0xFF;
238 }
239 em[2 + ps_len] = 0x00;
240 em[3 + ps_len..3 + ps_len + prefix.len()].copy_from_slice(prefix);
241 em[3 + ps_len + prefix.len()..].copy_from_slice(hash);
242
243 let m = BigInt::from_be_bytes(&em);
244 let s = rsa_decrypt_raw(sk, &m); s.to_be_bytes(k)
246}
247
248pub fn pkcs1v15_verify(pk: &RsaPublicKey, hash: &[u8], hash_alg: HashAlg, sig: &[u8]) -> bool {
252 let k = pk.modulus_byte_len();
253 if sig.len() != k {
254 return false;
255 }
256 if hash.len() != hash_alg.hash_len() {
257 return false;
258 }
259
260 let s = BigInt::from_be_bytes(sig);
261 let m = rsa_encrypt_raw(pk, &s); let em = m.to_be_bytes(k);
263
264 let prefix = hash_alg.digest_info_prefix();
266 let t_len = prefix.len() + hash_alg.hash_len();
267 if k < t_len + 11 {
268 return false;
269 }
270
271 let ps_len = k - t_len - 3;
272 let mut expected = vec![0u8; k];
273 expected[0] = 0x00;
274 expected[1] = 0x01;
275 for i in 0..ps_len {
276 expected[2 + i] = 0xFF;
277 }
278 expected[2 + ps_len] = 0x00;
279 expected[3 + ps_len..3 + ps_len + prefix.len()].copy_from_slice(prefix);
280 expected[3 + ps_len + prefix.len()..].copy_from_slice(hash);
281
282 let mut diff = 0u8;
284 for (a, b) in em.iter().zip(expected.iter()) {
285 diff |= a ^ b;
286 }
287 diff == 0 && em.len() == expected.len()
288}
289
290pub fn pkcs1v15_sign_sha256(sk: &RsaSecretKey, message: &[u8]) -> Vec<u8> {
303 let hash = Sha256::hash(message);
304 pkcs1v15_sign(sk, &hash, HashAlg::Sha256)
305}
306
307pub fn pkcs1v15_verify_sha256(pk: &RsaPublicKey, message: &[u8], sig: &[u8]) -> bool {
309 let hash = Sha256::hash(message);
310 pkcs1v15_verify(pk, &hash, HashAlg::Sha256, sig)
311}
312
313macro_rules! convenience_pair {
314 ($sign_fn:ident, $verify_fn:ident, $hasher:ty, $alg:expr, $doc:literal) => {
315 #[doc = $doc]
316 pub fn $sign_fn(sk: &RsaSecretKey, message: &[u8]) -> Vec<u8> {
317 let hash = <$hasher as Hasher>::hash(message);
318 pkcs1v15_sign(sk, &hash, $alg)
319 }
320
321 #[doc = $doc]
322 pub fn $verify_fn(pk: &RsaPublicKey, message: &[u8], sig: &[u8]) -> bool {
323 let hash = <$hasher as Hasher>::hash(message);
324 pkcs1v15_verify(pk, &hash, $alg, sig)
325 }
326 };
327}
328
329convenience_pair!(
330 pkcs1v15_sign_sha1,
331 pkcs1v15_verify_sha1,
332 Sha1,
333 HashAlg::Sha1,
334 "Convenience: hash a message with SHA-1, then sign / verify. \
335 **Legacy**: do not use for new designs; SHA-1 is collision-broken."
336);
337
338convenience_pair!(
339 pkcs1v15_sign_sha384,
340 pkcs1v15_verify_sha384,
341 Sha384,
342 HashAlg::Sha384,
343 "Convenience: hash a message with SHA-384, then sign / verify."
344);
345
346convenience_pair!(
347 pkcs1v15_sign_sha512,
348 pkcs1v15_verify_sha512,
349 Sha512,
350 HashAlg::Sha512,
351 "Convenience: hash a message with SHA-512, then sign / verify."
352);
353
354convenience_pair!(
355 pkcs1v15_sign_sha3_256,
356 pkcs1v15_verify_sha3_256,
357 Sha3_256,
358 HashAlg::Sha3_256,
359 "Convenience: hash a message with SHA3-256, then sign / verify."
360);
361
362convenience_pair!(
363 pkcs1v15_sign_sha3_384,
364 pkcs1v15_verify_sha3_384,
365 Sha3_384,
366 HashAlg::Sha3_384,
367 "Convenience: hash a message with SHA3-384, then sign / verify."
368);
369
370convenience_pair!(
371 pkcs1v15_sign_sha3_512,
372 pkcs1v15_verify_sha3_512,
373 Sha3_512,
374 HashAlg::Sha3_512,
375 "Convenience: hash a message with SHA3-512, then sign / verify."
376);
377
378convenience_pair!(
379 pkcs1v15_sign_ripemd160,
380 pkcs1v15_verify_ripemd160,
381 Ripemd160,
382 HashAlg::Ripemd160,
383 "Convenience: hash a message with RIPEMD-160, then sign / verify. \
384 **Legacy**: included for compatibility with older systems \
385 (Bitcoin, some 2000s X.509 CAs); not recommended for new designs."
386);
387
388#[cfg(test)]
389mod tests {
390 use super::*;
391
392 fn test_rng() -> impl FnMut(&mut [u8]) {
393 let mut state: u64 = 0xdeadbeefcafebabe;
394 move |buf: &mut [u8]| {
395 for b in buf.iter_mut() {
396 state = state
397 .wrapping_mul(6364136223846793005)
398 .wrapping_add(1442695040888963407);
399 *b = (state >> 33) as u8;
400 }
401 }
402 }
403
404 #[test]
405 fn test_pkcs1v15_encrypt_decrypt_roundtrip() {
406 let mut rng = test_rng();
407 let (pk, sk) = super::super::rsa::rsa_keygen(512, &mut rng);
408 let msg = b"Hello, RSA!";
409 let ct = pkcs1v15_encrypt(&pk, msg, &mut rng);
410 let pt = pkcs1v15_decrypt(&sk, &ct).expect("decryption failed");
411 assert_eq!(&pt, msg);
412 }
413
414 #[test]
415 fn test_pkcs1v15_sign_verify_roundtrip() {
416 let mut rng = test_rng();
417 let (pk, sk) = super::super::rsa::rsa_keygen(512, &mut rng);
418 let message = b"Sign me!";
419 let sig = pkcs1v15_sign_sha256(&sk, message);
420 assert!(pkcs1v15_verify_sha256(&pk, message, &sig));
421 let mut bad_sig = sig.clone();
423 bad_sig[0] ^= 0xFF;
424 assert!(!pkcs1v15_verify_sha256(&pk, message, &bad_sig));
425 }
426
427 #[test]
437 fn pkcs1v15_all_supported_hashes_roundtrip() {
438 let mut rng = test_rng();
439 let (pk, sk) = super::super::rsa::rsa_keygen(1024, &mut rng);
440 let msg = b"hash flexibility test";
441
442 let sig = pkcs1v15_sign_sha1(&sk, msg);
444 assert!(pkcs1v15_verify_sha1(&pk, msg, &sig));
445 let sig = pkcs1v15_sign_sha256(&sk, msg);
447 assert!(pkcs1v15_verify_sha256(&pk, msg, &sig));
448 let sig = pkcs1v15_sign_sha384(&sk, msg);
450 assert!(pkcs1v15_verify_sha384(&pk, msg, &sig));
451 let sig = pkcs1v15_sign_sha512(&sk, msg);
453 assert!(pkcs1v15_verify_sha512(&pk, msg, &sig));
454 let sig = pkcs1v15_sign_sha3_256(&sk, msg);
456 assert!(pkcs1v15_verify_sha3_256(&pk, msg, &sig));
457 let sig = pkcs1v15_sign_sha3_384(&sk, msg);
459 assert!(pkcs1v15_verify_sha3_384(&pk, msg, &sig));
460 let sig = pkcs1v15_sign_sha3_512(&sk, msg);
462 assert!(pkcs1v15_verify_sha3_512(&pk, msg, &sig));
463 let sig = pkcs1v15_sign_ripemd160(&sk, msg);
465 assert!(pkcs1v15_verify_ripemd160(&pk, msg, &sig));
466 }
467
468 #[test]
478 fn pkcs1v15_hash_mismatch_rejected() {
479 let mut rng = test_rng();
480 let (pk, sk) = super::super::rsa::rsa_keygen(1024, &mut rng);
481 let msg = b"hash mismatch test";
482
483 let sig256 = pkcs1v15_sign_sha256(&sk, msg);
485 assert!(pkcs1v15_verify_sha256(&pk, msg, &sig256));
486
487 assert!(!pkcs1v15_verify_sha512(&pk, msg, &sig256));
491
492 assert!(!pkcs1v15_verify_sha3_256(&pk, msg, &sig256));
497
498 let sig512 = pkcs1v15_sign_sha512(&sk, msg);
500 assert!(pkcs1v15_verify_sha512(&pk, msg, &sig512));
501 assert!(!pkcs1v15_verify_sha256(&pk, msg, &sig512));
502
503 let sig3_256 = pkcs1v15_sign_sha3_256(&sk, msg);
506 assert!(pkcs1v15_verify_sha3_256(&pk, msg, &sig3_256));
507 assert!(!pkcs1v15_verify_sha256(&pk, msg, &sig3_256));
508 }
509
510 #[test]
516 fn hashalg_lengths_agree_with_hasher_output_len() {
517 assert_eq!(HashAlg::Sha1.hash_len(), <Sha1 as Hasher>::OUTPUT_LEN);
518 assert_eq!(HashAlg::Sha256.hash_len(), <Sha256 as Hasher>::OUTPUT_LEN);
519 assert_eq!(HashAlg::Sha384.hash_len(), <Sha384 as Hasher>::OUTPUT_LEN);
520 assert_eq!(HashAlg::Sha512.hash_len(), <Sha512 as Hasher>::OUTPUT_LEN);
521 assert_eq!(HashAlg::Sha3_256.hash_len(), <Sha3_256 as Hasher>::OUTPUT_LEN);
522 assert_eq!(HashAlg::Sha3_384.hash_len(), <Sha3_384 as Hasher>::OUTPUT_LEN);
523 assert_eq!(HashAlg::Sha3_512.hash_len(), <Sha3_512 as Hasher>::OUTPUT_LEN);
524 assert_eq!(HashAlg::Ripemd160.hash_len(), <Ripemd160 as Hasher>::OUTPUT_LEN);
525 }
526}