1use big_number::Uint;
9
10use crate::{Hasher, RsaError};
11
12const RSA_MAX_BITS: usize = 4096;
14const RSA_MAX_LIMBS: usize = RSA_MAX_BITS / 64;
15const RSA_MAX_BYTES: usize = RSA_MAX_BITS / 8;
16
17pub const DIGEST_INFO_SHA256_PREFIX: &[u8] = &[
19 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20,
20];
21
22pub const DIGEST_INFO_SHA384_PREFIX: &[u8] = &[
24 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30,
25];
26
27pub const DIGEST_INFO_SHA512_PREFIX: &[u8] = &[
29 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40,
30];
31
32pub struct PublicKey {
34 n: Uint<RSA_MAX_BITS, RSA_MAX_LIMBS>,
36 e: Uint<RSA_MAX_BITS, RSA_MAX_LIMBS>,
38 n_len: usize,
40 e_len: usize,
42 mu: [u64; big_number::MAX_LIMBS],
44}
45
46impl PublicKey {
47 #[inline]
54 pub fn from_n_e(n_bytes: &[u8], e: &[u8]) -> Result<Self, RsaError> {
55 let n = uint_from_variable_be(n_bytes)?;
56 let e_uint = uint_from_variable_be(e)?;
57 let e_len = {
58 let mut start: usize = 0;
59 while start < e.len().saturating_sub(1) && e[start] == 0 {
60 start += 1;
61 }
62 e.len() - start
63 };
64 Ok(PublicKey {
65 n_len: n_bytes.len(),
66 mu: n.compute_mu_for_barrett(),
67 e: e_uint,
68 e_len,
69 n,
70 })
71 }
72
73 pub fn from_pkcs1_der(mut data: &[u8]) -> Result<Self, RsaError> {
78 if data.is_empty() || data[0] != 0x30 {
79 return Err(RsaError::Unspecified);
80 }
81 let (seq_len, len_size) = read_length(&data[1..])?;
82 data = &data[1 + len_size..];
83 if data.len() < seq_len {
84 return Err(RsaError::Unspecified);
85 }
86 data = &data[..seq_len];
87
88 let mut n_buf = [0u8; RSA_MAX_BYTES];
89 let n_len = read_integer_bytes(data, &mut n_buf)?;
90 let consumed = asn1_integer_size(data);
91 data = &data[consumed..];
92
93 let mut e_buf = [0u8; RSA_MAX_BYTES];
94 let e_len = read_integer_bytes(data, &mut e_buf)?;
95
96 Self::from_n_e(&n_buf[..n_len], &e_buf[..e_len])
97 }
98
99 pub fn verify_pkcs1_v1_5(
106 &self,
107 signature: &[u8],
108 message_digest: &[u8],
109 digest_info_prefix: &[u8],
110 ) -> Result<(), RsaError> {
111 if signature.len() != self.n_len {
112 return Err(RsaError::Unspecified);
113 }
114
115 let s = uint_from_variable_be(signature)?;
116
117 if s.ct_ge(&self.n) {
119 return Err(RsaError::Unspecified);
120 }
121
122 let m = s.modpow_barrett(&self.e, &self.n, &self.mu);
123
124 let mod_bytes = self.n_len;
125 let expected_len = digest_info_prefix.len() + message_digest.len();
126
127 let mut m_bytes = [0u8; RSA_MAX_BYTES];
128 write_uint_be(&m, &mut m_bytes, mod_bytes);
129
130 if m_bytes[0] != 0x00 || m_bytes[1] != 0x01 {
132 return Err(RsaError::Unspecified);
133 }
134
135 let mut sep = 2;
137 while sep < mod_bytes && m_bytes[sep] == 0xff {
138 sep += 1;
139 }
140 if sep >= mod_bytes || m_bytes[sep] != 0x00 {
141 return Err(RsaError::Unspecified);
142 }
143 if sep < 10 {
145 return Err(RsaError::Unspecified);
146 }
147 sep += 1;
148
149 let di_start = sep;
150 let di_end = di_start + expected_len;
151 if di_end > mod_bytes {
152 return Err(RsaError::Unspecified);
153 }
154
155 let mut ok = 0u8;
157 for i in 0..digest_info_prefix.len() {
158 ok |= m_bytes[di_start + i] ^ digest_info_prefix[i];
159 }
160 for i in 0..message_digest.len() {
162 ok |= m_bytes[di_start + digest_info_prefix.len() + i] ^ message_digest[i];
163 }
164
165 if ok != 0 {
166 return Err(RsaError::Unspecified);
167 }
168
169 for i in di_end..mod_bytes {
171 ok |= m_bytes[i];
172 }
173
174 if ok != 0 {
175 return Err(RsaError::Unspecified);
176 }
177
178 Ok(())
179 }
180
181 pub fn verify_pss<H: Hasher>(&self, signature: &[u8], message: &[u8], salt_len: usize) -> Result<(), RsaError> {
187 if signature.len() != self.n_len {
188 return Err(RsaError::Unspecified);
189 }
190
191 let s = uint_from_variable_be(signature)?;
192 if s.ct_ge(&self.n) {
193 return Err(RsaError::Unspecified);
194 }
195
196 let m = s.modpow_barrett(&self.e, &self.n, &self.mu);
197 let em_len = self.n_len;
198 let hash_len = H::OUTPUT_SIZE;
199
200 let mut em = [0u8; RSA_MAX_BYTES];
201 write_uint_be(&m, &mut em, em_len);
202
203 let em_bits = self.n_len * 8 - 1;
204 let leftmost_bits = 8 * em_len - em_bits;
205 if leftmost_bits > 0 && leftmost_bits < 8 {
206 if em[0] >> (8 - leftmost_bits) != 0 {
207 return Err(RsaError::Unspecified);
208 }
209 }
210
211 if em_len < hash_len + salt_len + 2 {
212 return Err(RsaError::Unspecified);
213 }
214 if em[em_len - 1] != 0xBC {
215 return Err(RsaError::Unspecified);
216 }
217
218 let masked_db_len = em_len - hash_len - 1;
219 let masked_db = &em[..masked_db_len];
220 let h = &em[masked_db_len..masked_db_len + hash_len];
221
222 let mut db_mask = [0u8; RSA_MAX_BYTES];
223 mgf1::<H>(h, &mut db_mask[..masked_db_len]);
224
225 let mut db = [0u8; RSA_MAX_BYTES];
226 for (i, (a, b)) in masked_db.iter().zip(db_mask[..masked_db_len].iter()).enumerate() {
227 db[i] = a ^ b;
228 }
229
230 if leftmost_bits > 0 && leftmost_bits < 8 {
231 db[0] &= 0xff >> leftmost_bits;
232 }
233
234 let ps_len = em_len - hash_len - salt_len - 2;
235 if ps_len > 0 {
236 for i in 0..ps_len {
237 if db[i] != 0x00 {
238 return Err(RsaError::Unspecified);
239 }
240 }
241 }
242 if db[ps_len] != 0x01 {
243 return Err(RsaError::Unspecified);
244 }
245
246 let salt = &db[ps_len + 1..ps_len + 1 + salt_len];
247
248 let m_hash = H::hash(message);
249 let mut mp = [0u8; 8 + 64 + RSA_MAX_BYTES];
250 let mp_len = 8 + hash_len + salt_len;
251 mp[8..8 + hash_len].copy_from_slice(m_hash.as_ref());
252 mp[8 + hash_len..mp_len].copy_from_slice(salt);
253
254 let hp = H::hash(&mp[..mp_len]);
255
256 let mut ok = 0u8;
257 for i in 0..hash_len {
258 ok |= h[i] ^ hp.as_ref()[i];
259 }
260 if ok != 0 {
261 return Err(RsaError::Unspecified);
262 }
263
264 Ok(())
265 }
266
267 #[cfg(feature = "alloc")]
270 pub fn n_bytes(&self) -> alloc::vec::Vec<u8> {
271 let full = self.n.to_be_bytes_fixed::<{ RSA_MAX_BYTES }>();
272 full[full.len() - self.n_len..].to_vec()
273 }
274
275 #[cfg(feature = "alloc")]
278 pub fn e_bytes(&self) -> smallvec::SmallVec<u8, 4> {
279 let full = self.e.to_be_bytes_fixed::<{ RSA_MAX_BYTES }>();
280 full[full.len() - self.e_len..].into()
281 }
282}
283
284fn mgf1<H: Hasher>(seed: &[u8], out: &mut [u8]) {
286 let out_len = out.len();
287 let hash_len = H::OUTPUT_SIZE;
288 let mut offset = 0;
289 let mut counter: u32 = 0;
290 let input_prefix = seed.len();
291 let mut input_buf = [0u8; RSA_MAX_BYTES + 4];
292 input_buf[..input_prefix].copy_from_slice(seed);
293 while offset < out_len {
294 input_buf[input_prefix..input_prefix + 4].copy_from_slice(&counter.to_be_bytes());
295 let hash = H::hash(&input_buf[..input_prefix + 4]);
296 let take = (out_len - offset).min(hash_len);
297 out[offset..offset + take].copy_from_slice(&hash.as_ref()[..take]);
298 offset += take;
299 counter += 1;
300 }
301}
302
303fn read_length(data: &[u8]) -> Result<(usize, usize), RsaError> {
305 if data.is_empty() {
306 return Err(RsaError::Unspecified);
307 }
308 if data[0] & 0x80 == 0 {
309 Ok((data[0] as usize, 1))
310 } else {
311 let num_bytes = (data[0] & 0x7f) as usize;
312 if num_bytes == 0 || num_bytes > 4 || data.len() < 1 + num_bytes {
313 return Err(RsaError::Unspecified);
314 }
315 let mut len = 0usize;
316 for i in 0..num_bytes {
317 len = (len << 8) | data[1 + i] as usize;
318 }
319 Ok((len, 1 + num_bytes))
320 }
321}
322
323fn read_integer_bytes(data: &[u8], out: &mut [u8]) -> Result<usize, RsaError> {
326 if data.len() < 2 || data[0] != 0x02 {
327 return Err(RsaError::Unspecified);
328 }
329 let (len, len_size) = read_length(&data[1..])?;
330 let value = &data[1 + len_size..];
331 if value.len() < len {
332 return Err(RsaError::Unspecified);
333 }
334 let bytes = &value[..len];
335 if bytes.is_empty() {
336 return Err(RsaError::Unspecified);
337 }
338 let start = if bytes[0] == 0x00 && bytes.len() > 1 { 1 } else { 0 };
339 let val_len = bytes.len() - start;
340 if out.len() < val_len {
341 return Err(RsaError::Unspecified);
342 }
343 out[..val_len].copy_from_slice(&bytes[start..]);
344 Ok(val_len)
345}
346
347fn asn1_integer_size(data: &[u8]) -> usize {
349 if data.len() < 2 || data[0] != 0x02 {
350 return 0;
351 }
352 let (len, len_size) = read_length(&data[1..]).unwrap_or((0, 0));
353 1 + len_size + len
354}
355
356fn uint_from_variable_be(bytes: &[u8]) -> Result<Uint<RSA_MAX_BITS, RSA_MAX_LIMBS>, RsaError> {
359 let max_bytes = RSA_MAX_BITS / 8;
360 if bytes.len() > max_bytes {
361 return Err(RsaError::NotSupported);
362 }
363 let mut limbs = [0u64; RSA_MAX_LIMBS];
364 let byte_count = bytes.len();
365 let mut i = 0;
366 while i < RSA_MAX_LIMBS {
367 let limb_start = byte_count.saturating_sub((i + 1) * 8);
368 let limb_end = byte_count.saturating_sub(i * 8);
369 let len = limb_end - limb_start;
370 let mut buf = [0u8; 8];
371 if len > 0 {
372 buf[8 - len..].copy_from_slice(&bytes[limb_start..limb_end]);
373 }
374 limbs[i] = u64::from_be_bytes(buf);
375 i += 1;
376 }
377 Ok(Uint::from_limbs(limbs))
378}
379
380fn write_uint_be(value: &Uint<RSA_MAX_BITS, RSA_MAX_LIMBS>, out: &mut [u8], byte_len: usize) {
383 assert!(byte_len <= RSA_MAX_BYTES);
384 let full = value.to_be_bytes_fixed::<{ RSA_MAX_BYTES }>();
385 let start = full.len() - byte_len;
386 out[..byte_len].copy_from_slice(&full[start..]);
387}
388
389pub fn verify_pkcs1_sha256(pkcs1_der: &[u8], signature: &[u8], message: &[u8]) -> Result<(), RsaError> {
391 let key = PublicKey::from_pkcs1_der(pkcs1_der)?;
392 let digest = crate::sha2::Sha256::hash(message);
393 key.verify_pkcs1_v1_5(signature, digest.as_ref(), DIGEST_INFO_SHA256_PREFIX)
394}
395
396pub fn verify_pkcs1_sha384(pkcs1_der: &[u8], signature: &[u8], message: &[u8]) -> Result<(), RsaError> {
398 let key = PublicKey::from_pkcs1_der(pkcs1_der)?;
399 let digest = crate::sha2::Sha384::hash(message);
400 key.verify_pkcs1_v1_5(signature, digest.as_ref(), DIGEST_INFO_SHA384_PREFIX)
401}
402
403pub fn verify_pkcs1_sha512(pkcs1_der: &[u8], signature: &[u8], message: &[u8]) -> Result<(), RsaError> {
405 let key = PublicKey::from_pkcs1_der(pkcs1_der)?;
406 let digest = crate::sha2::Sha512::hash(message);
407 key.verify_pkcs1_v1_5(signature, digest.as_ref(), DIGEST_INFO_SHA512_PREFIX)
408}
409
410pub fn verify_pss_sha256(pkcs1_der: &[u8], signature: &[u8], message: &[u8]) -> Result<(), RsaError> {
412 let key = PublicKey::from_pkcs1_der(pkcs1_der)?;
413 key.verify_pss::<crate::sha2::Sha256>(signature, message, 32)
414}
415
416pub fn verify_pss_sha384(pkcs1_der: &[u8], signature: &[u8], message: &[u8]) -> Result<(), RsaError> {
418 let key = PublicKey::from_pkcs1_der(pkcs1_der)?;
419 key.verify_pss::<crate::sha2::Sha384>(signature, message, 48)
420}
421
422pub fn verify_pss_sha512(pkcs1_der: &[u8], signature: &[u8], message: &[u8]) -> Result<(), RsaError> {
424 let key = PublicKey::from_pkcs1_der(pkcs1_der)?;
425 key.verify_pss::<crate::sha2::Sha512>(signature, message, 64)
426}
427
428#[cfg(test)]
429mod tests {
430 use hex;
431
432 use super::*;
433
434 macro_rules! wycheproof_rsa_test {
435 ($path:expr, $hasher:ty, $di_prefix:expr) => {{
436 let data: serde_json::Value = serde_json::from_str(include_str!($path)).unwrap();
437 let mut valid_tested = 0u64;
438 let mut invalid_tested = 0u64;
439
440 for group in data["testGroups"].as_array().unwrap() {
441 let pkcs1_der = hex::decode(group["publicKeyAsn"].as_str().unwrap()).unwrap();
442 let key = super::PublicKey::from_pkcs1_der(&pkcs1_der).unwrap();
443
444 for test in group["tests"].as_array().unwrap() {
445 let msg_hex = test["msg"].as_str().unwrap();
446 let sig_hex = test["sig"].as_str().unwrap();
447 let result = test["result"].as_str().unwrap();
448
449 let msg = hex::decode(msg_hex).unwrap();
450 let sig = hex::decode(sig_hex).unwrap();
451
452 let digest = <$hasher as crate::Hasher>::hash(&msg);
453 let verify_result = key.verify_pkcs1_v1_5(&sig, digest.as_ref(), $di_prefix);
454
455 match result {
456 "valid" => {
457 assert!(
458 verify_result.is_ok(),
459 "{}: tcId {}: expected valid, got error",
460 $path,
461 test["tcId"]
462 );
463 valid_tested += 1;
464 }
465 "invalid" => {
466 let flags = test.get("flags").and_then(|f| f.as_array());
471 let skip_asn1 = flags.map_or(false, |f| {
472 f.iter().any(|v| {
473 let s = v.as_str().unwrap_or("");
474 s == "InvalidAsnInPadding" || s == "BerEncodedPadding" || s == "ModifiedPadding"
475 })
476 });
477 if !skip_asn1 {
478 assert!(
479 verify_result.is_err(),
480 "{}: tcId {} ({:?}): expected invalid, got ok",
481 $path,
482 test["tcId"],
483 flags,
484 );
485 invalid_tested += 1;
486 }
487 }
488 "acceptable" => {}
489 _ => panic!("unknown result: {result}"),
490 }
491 }
492 }
493
494 assert!(valid_tested > 0, "no valid RSA tests were run");
495 assert!(invalid_tested > 0, "no invalid RSA tests were run");
496 }};
497 }
498
499 macro_rules! wycheproof_rsa_pss_test {
500 ($path:expr, $hasher:ty, $hash_len:expr) => {{
501 let data: serde_json::Value = serde_json::from_str(include_str!($path)).unwrap();
502 let mut valid_tested = 0u64;
503 let mut invalid_tested = 0u64;
504
505 for group in data["testGroups"].as_array().unwrap() {
506 let pkcs1_der = hex::decode(group["publicKeyAsn"].as_str().unwrap()).unwrap();
507 let key = super::PublicKey::from_pkcs1_der(&pkcs1_der).unwrap();
508
509 for test in group["tests"].as_array().unwrap() {
510 let msg_hex = test["msg"].as_str().unwrap();
511 let sig_hex = test["sig"].as_str().unwrap();
512 let result = test["result"].as_str().unwrap();
513
514 let msg = hex::decode(msg_hex).unwrap();
515 let sig = hex::decode(sig_hex).unwrap();
516
517 let verify_result = key.verify_pss::<$hasher>(&sig, &msg, $hash_len);
518
519 match result {
520 "valid" => {
521 assert!(
522 verify_result.is_ok(),
523 "{}: tcId {}: expected valid, got error: {:?}",
524 $path,
525 test["tcId"],
526 verify_result,
527 );
528 valid_tested += 1;
529 }
530 "invalid" => {
531 assert!(
532 verify_result.is_err(),
533 "{}: tcId {} ({:?}): expected invalid, got ok",
534 $path,
535 test["tcId"],
536 test.get("flags"),
537 );
538 invalid_tested += 1;
539 }
540 "acceptable" => {}
541 _ => panic!("unknown result: {result}"),
542 }
543 }
544 }
545
546 assert!(valid_tested > 0, "no valid RSA-PSS tests were run for {}", $path);
547 assert!(invalid_tested > 0, "no invalid RSA-PSS tests were run for {}", $path);
548 }};
549 }
550
551 #[test]
552 fn modpow_works() {
553 let base = uint_from_variable_be(&[3]).unwrap();
554 let exp = uint_from_variable_be(&[5]).unwrap();
555 let modulus = uint_from_variable_be(&[7]).unwrap();
556 let result = base.modpow(&exp, &modulus);
557 let bytes = result.to_be_bytes_fixed::<512>();
558 assert_eq!(bytes[511], 5, "3^5 mod 7 should be 5, got {}", bytes[511]);
559 }
560
561 #[test]
562 fn from_n_e_matches_der() {
563 let sig = hex::decode(
564 "9d00f18defaa95b474b06ac4674b1b9270e110c6f474ce29e3aa972eca09137c9a82267e634986ecd54734f2edb1b3d72b539b8608e23074898c56042f9f014bfff59abce81c57d606b60f80ae4e110fc6f9dea99ce2897ce1d90661ab3d3b3f1a5ddf258b920a51c8c8758ab2da3da20da99c84eb2f57859b36918447c4cdbfa16cc09523fd27d28d4e97fa9ff0ea4d633c937a904a196a64e934851ee02b7922a8f5a4534bb10b8e16b89c12ddc347d7b4317f8b9d3dfed07a442d47351b18db38f45cc92e5c577b866df21766094d1f737ea418852827be3aec10d3c5a65a40087d9647b91a4d9419ad784a31caf02254cfc01a682bb6f5a231307f0fc8d9",
565 ).unwrap();
566 let digest = hex::decode("41cb0773387b187c038b7015498534c11369f1cfd094a714f4f39cf63ebb42ba").unwrap();
567
568 let n = hex::decode(
570 "b1d59f746650c6a4360d26dc2e05581e1bd12cddcfc459a75dd2ef6d38cb6e977c72cad72f5e8ad4795484211e71e9a292d25a3901fca4cd242649f56cce50ad6ba148658d71f3a9c8b39e92a7a49543243df8ca2688292d47ff2a92a6ee0c9151162936791f522afccd6a7508251934b909d62fa805bae0d79f83f3c981b39c15ea79ce7b4ec2ff82240ce2a9fb93ae49d7697d1248f73d4ad23461055f469a3936ab959a0c6a067aa19521650f3649a028e2ebe355909aae7c95d3fc988684478b2bb11b307cb58c6c14727e1b62103d400ac8eed0e0d6d7f7d7cfc1f4ae4cbd9759372f8408c52174abb05f134ca6788fb60ba3f35c57c07cd44011bb113b",
571 ).unwrap();
572 let e = hex::decode("010001").unwrap();
573
574 let key = PublicKey::from_n_e(&n, &e).unwrap();
575 key.verify_pkcs1_v1_5(&sig, &digest, DIGEST_INFO_SHA256_PREFIX).unwrap();
576 }
577
578 #[cfg(feature = "std")]
579 #[test]
580 fn wycheproof_rsa_pss_2048_sha256() {
581 wycheproof_rsa_pss_test!(
582 "../testdata/wycheproof/testvectors_v1/rsa_pss_2048_sha256_mgf1_32_test.json",
583 crate::sha2::Sha256,
584 32
585 );
586 }
587
588 #[cfg(feature = "std")]
589 #[test]
590 fn wycheproof_rsa_pss_2048_sha384() {
591 wycheproof_rsa_pss_test!(
592 "../testdata/wycheproof/testvectors_v1/rsa_pss_2048_sha384_mgf1_48_test.json",
593 crate::sha2::Sha384,
594 48
595 );
596 }
597
598 #[cfg(feature = "std")]
599 #[test]
600 fn wycheproof_rsa_pss_4096_sha512() {
601 wycheproof_rsa_pss_test!(
602 "../testdata/wycheproof/testvectors_v1/rsa_pss_4096_sha512_mgf1_64_test.json",
603 crate::sha2::Sha512,
604 64
605 );
606 }
607
608 #[test]
609 fn rsa_pkcs1_sha256_verify_works() {
610 let pkcs1_der = hex::decode(
611 "3082010a0282010100b1d59f746650c6a4360d26dc2e05581e1bd12cddcfc459a75dd2ef6d38cb6e977c72cad72f5e8ad4795484211e71e9a292d25a3901fca4cd242649f56cce50ad6ba148658d71f3a9c8b39e92a7a49543243df8ca2688292d47ff2a92a6ee0c9151162936791f522afccd6a7508251934b909d62fa805bae0d79f83f3c981b39c15ea79ce7b4ec2ff82240ce2a9fb93ae49d7697d1248f73d4ad23461055f469a3936ab959a0c6a067aa19521650f3649a028e2ebe355909aae7c95d3fc988684478b2bb11b307cb58c6c14727e1b62103d400ac8eed0e0d6d7f7d7cfc1f4ae4cbd9759372f8408c52174abb05f134ca6788fb60ba3f35c57c07cd44011bb113b0203010001",
612 ).unwrap();
613 let sig = hex::decode(
614 "9d00f18defaa95b474b06ac4674b1b9270e110c6f474ce29e3aa972eca09137c9a82267e634986ecd54734f2edb1b3d72b539b8608e23074898c56042f9f014bfff59abce81c57d606b60f80ae4e110fc6f9dea99ce2897ce1d90661ab3d3b3f1a5ddf258b920a51c8c8758ab2da3da20da99c84eb2f57859b36918447c4cdbfa16cc09523fd27d28d4e97fa9ff0ea4d633c937a904a196a64e934851ee02b7922a8f5a4534bb10b8e16b89c12ddc347d7b4317f8b9d3dfed07a442d47351b18db38f45cc92e5c577b866df21766094d1f737ea418852827be3aec10d3c5a65a40087d9647b91a4d9419ad784a31caf02254cfc01a682bb6f5a231307f0fc8d9",
615 ).unwrap();
616 let digest = hex::decode("41cb0773387b187c038b7015498534c11369f1cfd094a714f4f39cf63ebb42ba").unwrap();
617
618 let key = PublicKey::from_pkcs1_der(&pkcs1_der).unwrap();
619 key.verify_pkcs1_v1_5(&sig, &digest, DIGEST_INFO_SHA256_PREFIX).unwrap();
620 }
621
622 #[cfg(feature = "std")]
623 #[test]
624 fn wycheproof_rsa_pkcs1_2048_sha256() {
625 use crate::sha2::Sha256;
626 wycheproof_rsa_test!(
627 "../testdata/wycheproof/testvectors_v1/rsa_signature_2048_sha256_test.json",
628 Sha256,
629 DIGEST_INFO_SHA256_PREFIX
630 );
631 }
632
633 #[cfg(feature = "std")]
634 #[test]
635 fn wycheproof_rsa_pkcs1_2048_sha384() {
636 use crate::sha2::Sha384;
637 wycheproof_rsa_test!(
638 "../testdata/wycheproof/testvectors_v1/rsa_signature_2048_sha384_test.json",
639 Sha384,
640 DIGEST_INFO_SHA384_PREFIX
641 );
642 }
643
644 #[cfg(feature = "std")]
645 #[test]
646 fn wycheproof_rsa_pkcs1_2048_sha512() {
647 use crate::sha2::Sha512;
648 wycheproof_rsa_test!(
649 "../testdata/wycheproof/testvectors_v1/rsa_signature_2048_sha512_test.json",
650 Sha512,
651 DIGEST_INFO_SHA512_PREFIX
652 );
653 }
654}