161 lines
16 KiB
Rust
161 lines
16 KiB
Rust
|
|
extern crate num_bigint_dig as num_bigint;
|
||
|
|
extern crate num_integer;
|
||
|
|
extern crate num_traits;
|
||
|
|
|
||
|
|
static BIG_B: &'static str = "\
|
||
|
|
efac3c0a_0de55551_fee0bfe4_67fa017a_1a898fa1_6ca57cb1\
|
||
|
|
ca9e3248_cacc09a9_b99d6abc_38418d0f_82ae4238_d9a68832\
|
||
|
|
aadec7c1_ac5fed48_7a56a71b_67ac59d5_afb28022_20d9592d\
|
||
|
|
247c4efc_abbd9b75_586088ee_1dc00dc4_232a8e15_6e8191dd\
|
||
|
|
675b6ae0_c80f5164_752940bc_284b7cee_885c1e10_e495345b\
|
||
|
|
8fbe9cfd_e5233fe1_19459d0b_d64be53c_27de5a02_a829976b\
|
||
|
|
33096862_82dad291_bd38b6a9_be396646_ddaf8039_a2573c39\
|
||
|
|
1b14e8bc_2cb53e48_298c047e_d9879e9c_5a521076_f0e27df3\
|
||
|
|
990e1659_d3d8205b_6443ebc0_9918ebee_6764f668_9f2b2be3\
|
||
|
|
b59cbc76_d76d0dfc_d737c3ec_0ccf9c00_ad0554bf_17e776ad\
|
||
|
|
b4edf9cc_6ce540be_76229093_5c53893b";
|
||
|
|
|
||
|
|
static BIG_E: &'static str = "\
|
||
|
|
be0e6ea6_08746133_e0fbc1bf_82dba91e_e2b56231_a81888d2\
|
||
|
|
a833a1fc_f7ff002a_3c486a13_4f420bf3_a5435be9_1a5c8391\
|
||
|
|
774d6e6c_085d8357_b0c97d4d_2bb33f7c_34c68059_f78d2541\
|
||
|
|
eacc8832_426f1816_d3be001e_b69f9242_51c7708e_e10efe98\
|
||
|
|
449c9a4a_b55a0f23_9d797410_515da00d_3ea07970_4478a2ca\
|
||
|
|
c3d5043c_bd9be1b4_6dce479d_4302d344_84a939e6_0ab5ada7\
|
||
|
|
12ae34b2_30cc473c_9f8ee69d_2cac5970_29f5bf18_bc8203e4\
|
||
|
|
f3e895a2_13c94f1e_24c73d77_e517e801_53661fdd_a2ce9e47\
|
||
|
|
a73dd7f8_2f2adb1e_3f136bf7_8ae5f3b8_08730de1_a4eff678\
|
||
|
|
e77a06d0_19a522eb_cbefba2a_9caf7736_b157c5c6_2d192591\
|
||
|
|
17946850_2ddb1822_117b68a0_32f7db88";
|
||
|
|
|
||
|
|
// This modulus is the prime from the 2048-bit MODP DH group:
|
||
|
|
// https://tools.ietf.org/html/rfc3526#section-3
|
||
|
|
static BIG_M: &'static str = "\
|
||
|
|
FFFFFFFF_FFFFFFFF_C90FDAA2_2168C234_C4C6628B_80DC1CD1\
|
||
|
|
29024E08_8A67CC74_020BBEA6_3B139B22_514A0879_8E3404DD\
|
||
|
|
EF9519B3_CD3A431B_302B0A6D_F25F1437_4FE1356D_6D51C245\
|
||
|
|
E485B576_625E7EC6_F44C42E9_A637ED6B_0BFF5CB6_F406B7ED\
|
||
|
|
EE386BFB_5A899FA5_AE9F2411_7C4B1FE6_49286651_ECE45B3D\
|
||
|
|
C2007CB8_A163BF05_98DA4836_1C55D39A_69163FA8_FD24CF5F\
|
||
|
|
83655D23_DCA3AD96_1C62F356_208552BB_9ED52907_7096966D\
|
||
|
|
670C354E_4ABC9804_F1746C08_CA18217C_32905E46_2E36CE3B\
|
||
|
|
E39E772C_180E8603_9B2783A2_EC07A28F_B5C55DF0_6F4C52C9\
|
||
|
|
DE2BCBF6_95581718_3995497C_EA956AE5_15D22618_98FA0510\
|
||
|
|
15728E5A_8AACAA68_FFFFFFFF_FFFFFFFF";
|
||
|
|
|
||
|
|
static BIG_R: &'static str = "\
|
||
|
|
a1468311_6e56edc9_7a98228b_5e924776_0dd7836e_caabac13\
|
||
|
|
eda5373b_4752aa65_a1454850_40dc770e_30aa8675_6be7d3a8\
|
||
|
|
9d3085e4_da5155cf_b451ef62_54d0da61_cf2b2c87_f495e096\
|
||
|
|
055309f7_77802bbb_37271ba8_1313f1b5_075c75d1_024b6c77\
|
||
|
|
fdb56f17_b05bce61_e527ebfd_2ee86860_e9907066_edd526e7\
|
||
|
|
93d289bf_6726b293_41b0de24_eff82424_8dfd374b_4ec59542\
|
||
|
|
35ced2b2_6b195c90_10042ffb_8f58ce21_bc10ec42_64fda779\
|
||
|
|
d352d234_3d4eaea6_a86111ad_a37e9555_43ca78ce_2885bed7\
|
||
|
|
5a30d182_f1cf6834_dc5b6e27_1a41ac34_a2e91e11_33363ff0\
|
||
|
|
f88a7b04_900227c9_f6e6d06b_7856b4bb_4e354d61_060db6c8\
|
||
|
|
109c4735_6e7db425_7b5d74c7_0b709508";
|
||
|
|
|
||
|
|
mod biguint {
|
||
|
|
use crate::num_bigint::BigUint;
|
||
|
|
use num_integer::Integer;
|
||
|
|
use num_traits::Num;
|
||
|
|
|
||
|
|
fn check_modpow<T: Into<BigUint>>(b: T, e: T, m: T, r: T) {
|
||
|
|
let b: BigUint = b.into();
|
||
|
|
let e: BigUint = e.into();
|
||
|
|
let m: BigUint = m.into();
|
||
|
|
let r: BigUint = r.into();
|
||
|
|
|
||
|
|
assert_eq!(b.modpow(&e, &m), r);
|
||
|
|
|
||
|
|
let even_m = &m << 1;
|
||
|
|
let even_modpow = b.modpow(&e, &even_m);
|
||
|
|
assert!(even_modpow < even_m);
|
||
|
|
assert_eq!(even_modpow.mod_floor(&m), r);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_modpow_single() {
|
||
|
|
check_modpow::<u32>(1, 0, 11, 1);
|
||
|
|
check_modpow::<u32>(0, 15, 11, 0);
|
||
|
|
check_modpow::<u32>(3, 7, 11, 9);
|
||
|
|
check_modpow::<u32>(5, 117, 19, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_modpow_big() {
|
||
|
|
let b = BigUint::from_str_radix(super::BIG_B, 16).unwrap();
|
||
|
|
let e = BigUint::from_str_radix(super::BIG_E, 16).unwrap();
|
||
|
|
let m = BigUint::from_str_radix(super::BIG_M, 16).unwrap();
|
||
|
|
let r = BigUint::from_str_radix(super::BIG_R, 16).unwrap();
|
||
|
|
|
||
|
|
assert_eq!(b.modpow(&e, &m), r);
|
||
|
|
|
||
|
|
let even_m = &m << 1;
|
||
|
|
let even_modpow = b.modpow(&e, &even_m);
|
||
|
|
assert!(even_modpow < even_m);
|
||
|
|
assert_eq!(even_modpow % m, r);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
mod bigint {
|
||
|
|
use crate::num_bigint::BigInt;
|
||
|
|
use num_integer::Integer;
|
||
|
|
use num_traits::{Num, One, Signed, Zero};
|
||
|
|
|
||
|
|
fn check_modpow<T: Into<BigInt>>(b: T, e: T, m: T, r: T) {
|
||
|
|
fn check(b: &BigInt, e: &BigInt, m: &BigInt, r: &BigInt) {
|
||
|
|
assert_eq!(&b.modpow(e, m), r, "{} ** {} (mod {}) != {}", b, e, m, r);
|
||
|
|
|
||
|
|
let even_m = m << 1;
|
||
|
|
let even_modpow = b.modpow(e, m);
|
||
|
|
assert!(even_modpow.abs() < even_m.abs());
|
||
|
|
assert_eq!(&even_modpow.mod_floor(&m), r);
|
||
|
|
|
||
|
|
// the sign of the result follows the modulus like `mod_floor`, not `rem`
|
||
|
|
assert_eq!(b.modpow(&BigInt::one(), m), b.mod_floor(m));
|
||
|
|
}
|
||
|
|
|
||
|
|
let b: BigInt = b.into();
|
||
|
|
let e: BigInt = e.into();
|
||
|
|
let m: BigInt = m.into();
|
||
|
|
let r: BigInt = r.into();
|
||
|
|
|
||
|
|
let neg_r = if r.is_zero() { BigInt::zero() } else { &m - &r };
|
||
|
|
|
||
|
|
check(&b, &e, &m, &r);
|
||
|
|
check(&-&b, &e, &m, &neg_r);
|
||
|
|
check(&b, &e, &-&m, &-neg_r);
|
||
|
|
check(&-b, &e, &-m, &-r);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_modpow() {
|
||
|
|
check_modpow(1, 0, 11, 1);
|
||
|
|
check_modpow(0, 15, 11, 0);
|
||
|
|
check_modpow(3, 7, 11, 9);
|
||
|
|
check_modpow(5, 117, 19, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_modpow_big() {
|
||
|
|
let b = BigInt::from_str_radix(super::BIG_B, 16).unwrap();
|
||
|
|
let e = BigInt::from_str_radix(super::BIG_E, 16).unwrap();
|
||
|
|
let m = BigInt::from_str_radix(super::BIG_M, 16).unwrap();
|
||
|
|
let r = BigInt::from_str_radix(super::BIG_R, 16).unwrap();
|
||
|
|
|
||
|
|
check_modpow(b, e, m, r);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_modpow_regressions() {
|
||
|
|
let b = BigInt::from_str_radix("148481812629898028922243452517931778859", 10).unwrap();
|
||
|
|
let e = BigInt::from_str_radix("16435098172839837512196516812311093499490569878670367297267289860424512256538463266532022959266408018416567852684734588497916416136187078839267739725978336166999745821005936179018593835587756359392947871482504083674816495731435909345199760797177161154754925779360919525237676614128172648647911500379914471412818366569671457846739381412022752648258523984044578756763235473395195780234538671587124848304788149795652586624794482927796752606882278841162544955460064019689137847317780206834609575881714327516616748397737961237762873336834171905330546027429451135083776362686122899557888725948796224331193506222592112813363831262143794551999281828845346509870880135240743362989202264955851866873901952298529047382760952171260699800940203402411590316814425576804212932086536870842277932348256749768043376764627290016100654533004010428822265777286908656208089099092127972984005423839794664919506655326778604546219324509900610384631322406912665486036474377366152870915918416233189024602696846807585489500461444056256340396657108889884128774646550997081242980833837010531430817686546137565915999440512389126670933761230331781136785051903105551761360605955153965526507916363188341112254533546900918856149056234010024185866739707052283320137894508236708030393073746008591358978131033220284308440578997552336051551872429260495985290788472383410930103701098181040046982178942615030023837891063716495142291240064914406958131879790488522903319933096991747358362736027700320934244411581744233440969990871980397112958555221772016347271519743458219201647341522048641037636447020961393459361689115783772205215959561908213132905241847117897974907021064660348841187743233768666941906402014667799467564589078462903164562993104402151640205531799393472161660856369614893457740931170824508390675779110363769029251016554706340138552799705695412166547788255707729220955445949691798249233948722968814153076315069262262327279544452984601038421220171744835435447139031339494464142053772979407761657121288075911455394239969956797427550194380645051965653715482087787615335129043812999940402546026415056992324767180334773843861233955071202237294274359271475430657380828260571703203327581987534317555366980188198832338578536244104618138054121041486372199423386597615624191901853830483809698685374742667028940101816441951685363276882038336210700422797603510613111846954595022436035698754819942936505375274808169963123351107405117829639109757444830482546427068781651231740137534948467348030188662785964966008271360777175080360694608469974412342938544607421548114141514495964049562813034862446876683638176204251093678130072248611548806332602729145102403976639233590818408676822884759652755061679020567408021354840822976303739234096947267659560227055640107138404802060432790993450156525229379379720714634623735318118065089763507834865168286468254568494700670919425439694439642319235322529773576101769203189201053088694005219042889707060814542388489796173129303968340222350964210993220349324326308484232576487996842812967725937146079271570789571573722407894976135324761616238006103719195005048746346781252865616440032023462930422334551974597077525082161767973920966395077750625348166621383843516378555270171945199640597389857294640731470764493477858132235990664086928429400805461818404494416807771646933055371060791947508619873682273141110676794051751311706734092071395650419895838197502039647304259292352469720219978961426660652268425757287499531795549521832719319675383154504693003194799814792785134977216710693145907094228423958371660859295256059854089728777723290866100915365160160426967824702050566494940713413045584852011754762254190673287210044664094462605006489005405838932875983605163759076970996419045136183597722465725815484142724512834391464175879969057970622659591084356613314239934380308401875076502420942375838125211134043459845763044126317240104203712933951248021656185923748548517931664271525779812664938118365669410124160395259744944490912019715352272149091369489735502035520484940517165633428139087981001557557938452691509729424035366740726955805943712523410057160165505866316
|
||
|
|
let m = BigInt::from_str_radix("243440964008985994185807471607210276717", 10).unwrap();
|
||
|
|
let r = BigInt::from_str_radix("138995801145388806366366393471481216294", 10).unwrap();
|
||
|
|
|
||
|
|
check_modpow(b, e, m, r);
|
||
|
|
}
|
||
|
|
}
|