modpow.rs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. static BIG_B: &str = "\
  2. efac3c0a_0de55551_fee0bfe4_67fa017a_1a898fa1_6ca57cb1\
  3. ca9e3248_cacc09a9_b99d6abc_38418d0f_82ae4238_d9a68832\
  4. aadec7c1_ac5fed48_7a56a71b_67ac59d5_afb28022_20d9592d\
  5. 247c4efc_abbd9b75_586088ee_1dc00dc4_232a8e15_6e8191dd\
  6. 675b6ae0_c80f5164_752940bc_284b7cee_885c1e10_e495345b\
  7. 8fbe9cfd_e5233fe1_19459d0b_d64be53c_27de5a02_a829976b\
  8. 33096862_82dad291_bd38b6a9_be396646_ddaf8039_a2573c39\
  9. 1b14e8bc_2cb53e48_298c047e_d9879e9c_5a521076_f0e27df3\
  10. 990e1659_d3d8205b_6443ebc0_9918ebee_6764f668_9f2b2be3\
  11. b59cbc76_d76d0dfc_d737c3ec_0ccf9c00_ad0554bf_17e776ad\
  12. b4edf9cc_6ce540be_76229093_5c53893b";
  13. static BIG_E: &str = "\
  14. be0e6ea6_08746133_e0fbc1bf_82dba91e_e2b56231_a81888d2\
  15. a833a1fc_f7ff002a_3c486a13_4f420bf3_a5435be9_1a5c8391\
  16. 774d6e6c_085d8357_b0c97d4d_2bb33f7c_34c68059_f78d2541\
  17. eacc8832_426f1816_d3be001e_b69f9242_51c7708e_e10efe98\
  18. 449c9a4a_b55a0f23_9d797410_515da00d_3ea07970_4478a2ca\
  19. c3d5043c_bd9be1b4_6dce479d_4302d344_84a939e6_0ab5ada7\
  20. 12ae34b2_30cc473c_9f8ee69d_2cac5970_29f5bf18_bc8203e4\
  21. f3e895a2_13c94f1e_24c73d77_e517e801_53661fdd_a2ce9e47\
  22. a73dd7f8_2f2adb1e_3f136bf7_8ae5f3b8_08730de1_a4eff678\
  23. e77a06d0_19a522eb_cbefba2a_9caf7736_b157c5c6_2d192591\
  24. 17946850_2ddb1822_117b68a0_32f7db88";
  25. // This modulus is the prime from the 2048-bit MODP DH group:
  26. // https://tools.ietf.org/html/rfc3526#section-3
  27. static BIG_M: &str = "\
  28. FFFFFFFF_FFFFFFFF_C90FDAA2_2168C234_C4C6628B_80DC1CD1\
  29. 29024E08_8A67CC74_020BBEA6_3B139B22_514A0879_8E3404DD\
  30. EF9519B3_CD3A431B_302B0A6D_F25F1437_4FE1356D_6D51C245\
  31. E485B576_625E7EC6_F44C42E9_A637ED6B_0BFF5CB6_F406B7ED\
  32. EE386BFB_5A899FA5_AE9F2411_7C4B1FE6_49286651_ECE45B3D\
  33. C2007CB8_A163BF05_98DA4836_1C55D39A_69163FA8_FD24CF5F\
  34. 83655D23_DCA3AD96_1C62F356_208552BB_9ED52907_7096966D\
  35. 670C354E_4ABC9804_F1746C08_CA18217C_32905E46_2E36CE3B\
  36. E39E772C_180E8603_9B2783A2_EC07A28F_B5C55DF0_6F4C52C9\
  37. DE2BCBF6_95581718_3995497C_EA956AE5_15D22618_98FA0510\
  38. 15728E5A_8AACAA68_FFFFFFFF_FFFFFFFF";
  39. static BIG_R: &str = "\
  40. a1468311_6e56edc9_7a98228b_5e924776_0dd7836e_caabac13\
  41. eda5373b_4752aa65_a1454850_40dc770e_30aa8675_6be7d3a8\
  42. 9d3085e4_da5155cf_b451ef62_54d0da61_cf2b2c87_f495e096\
  43. 055309f7_77802bbb_37271ba8_1313f1b5_075c75d1_024b6c77\
  44. fdb56f17_b05bce61_e527ebfd_2ee86860_e9907066_edd526e7\
  45. 93d289bf_6726b293_41b0de24_eff82424_8dfd374b_4ec59542\
  46. 35ced2b2_6b195c90_10042ffb_8f58ce21_bc10ec42_64fda779\
  47. d352d234_3d4eaea6_a86111ad_a37e9555_43ca78ce_2885bed7\
  48. 5a30d182_f1cf6834_dc5b6e27_1a41ac34_a2e91e11_33363ff0\
  49. f88a7b04_900227c9_f6e6d06b_7856b4bb_4e354d61_060db6c8\
  50. 109c4735_6e7db425_7b5d74c7_0b709508";
  51. mod biguint {
  52. use num_bigint::BigUint;
  53. use num_integer::Integer;
  54. use num_traits::Num;
  55. fn check_modpow<T: Into<BigUint>>(b: T, e: T, m: T, r: T) {
  56. let b: BigUint = b.into();
  57. let e: BigUint = e.into();
  58. let m: BigUint = m.into();
  59. let r: BigUint = r.into();
  60. assert_eq!(b.modpow(&e, &m), r);
  61. let even_m = &m << 1;
  62. let even_modpow = b.modpow(&e, &even_m);
  63. assert!(even_modpow < even_m);
  64. assert_eq!(even_modpow.mod_floor(&m), r);
  65. }
  66. #[test]
  67. fn test_modpow_single() {
  68. check_modpow::<u32>(1, 0, 11, 1);
  69. check_modpow::<u32>(0, 15, 11, 0);
  70. check_modpow::<u32>(3, 7, 11, 9);
  71. check_modpow::<u32>(5, 117, 19, 1);
  72. check_modpow::<u32>(20, 1, 2, 0);
  73. check_modpow::<u32>(20, 1, 3, 2);
  74. }
  75. #[test]
  76. fn test_modpow_small() {
  77. for b in 0u64..11 {
  78. for e in 0u64..11 {
  79. for m in 1..11 {
  80. check_modpow::<u64>(b, e, m, b.pow(e as u32) % m);
  81. }
  82. }
  83. }
  84. }
  85. #[test]
  86. fn test_modpow_big() {
  87. let b = BigUint::from_str_radix(super::BIG_B, 16).unwrap();
  88. let e = BigUint::from_str_radix(super::BIG_E, 16).unwrap();
  89. let m = BigUint::from_str_radix(super::BIG_M, 16).unwrap();
  90. let r = BigUint::from_str_radix(super::BIG_R, 16).unwrap();
  91. assert_eq!(b.modpow(&e, &m), r);
  92. let even_m = &m << 1;
  93. let even_modpow = b.modpow(&e, &even_m);
  94. assert!(even_modpow < even_m);
  95. assert_eq!(even_modpow % m, r);
  96. }
  97. }
  98. mod bigint {
  99. use num_bigint::BigInt;
  100. use num_integer::Integer;
  101. use num_traits::{Num, One, Signed};
  102. fn check_modpow<T: Into<BigInt>>(b: T, e: T, m: T, r: T) {
  103. fn check(b: &BigInt, e: &BigInt, m: &BigInt, r: &BigInt) {
  104. assert_eq!(&b.modpow(e, m), r, "{} ** {} (mod {}) != {}", b, e, m, r);
  105. let even_m = m << 1u8;
  106. let even_modpow = b.modpow(e, m);
  107. assert!(even_modpow.abs() < even_m.abs());
  108. assert_eq!(&even_modpow.mod_floor(&m), r);
  109. // the sign of the result follows the modulus like `mod_floor`, not `rem`
  110. assert_eq!(b.modpow(&BigInt::one(), m), b.mod_floor(m));
  111. }
  112. let b: BigInt = b.into();
  113. let e: BigInt = e.into();
  114. let m: BigInt = m.into();
  115. let r: BigInt = r.into();
  116. let neg_b_r = if e.is_odd() {
  117. (-&r).mod_floor(&m)
  118. } else {
  119. r.clone()
  120. };
  121. let neg_m_r = r.mod_floor(&-&m);
  122. let neg_bm_r = neg_b_r.mod_floor(&-&m);
  123. check(&b, &e, &m, &r);
  124. check(&-&b, &e, &m, &neg_b_r);
  125. check(&b, &e, &-&m, &neg_m_r);
  126. check(&-b, &e, &-&m, &neg_bm_r);
  127. }
  128. #[test]
  129. fn test_modpow() {
  130. check_modpow(1, 0, 11, 1);
  131. check_modpow(0, 15, 11, 0);
  132. check_modpow(3, 7, 11, 9);
  133. check_modpow(5, 117, 19, 1);
  134. check_modpow(-20, 1, 2, 0);
  135. check_modpow(-20, 1, 3, 1);
  136. }
  137. #[test]
  138. fn test_modpow_small() {
  139. for b in -10i64..11 {
  140. for e in 0i64..11 {
  141. for m in -10..11 {
  142. if m == 0 {
  143. continue;
  144. }
  145. check_modpow(b, e, m, b.pow(e as u32).mod_floor(&m));
  146. }
  147. }
  148. }
  149. }
  150. #[test]
  151. fn test_modpow_big() {
  152. let b = BigInt::from_str_radix(super::BIG_B, 16).unwrap();
  153. let e = BigInt::from_str_radix(super::BIG_E, 16).unwrap();
  154. let m = BigInt::from_str_radix(super::BIG_M, 16).unwrap();
  155. let r = BigInt::from_str_radix(super::BIG_R, 16).unwrap();
  156. check_modpow(b, e, m, r);
  157. }
  158. }