uberzahl modexp_mm_crt(mm_t & mm1, mm_t & mm2, crt_t & crt, uberzahl base, uberzahl exp, uberzahl p, uberzahl q){ if(!crt.initialized){ crt.p_inverse = p.inverse(q); crt.q_inverse = q.inverse(p); crt.initialized = true; } return ( crt_helper(MONTGOMERY,mm1,base,exp,p,q, crt.q_inverse) + crt_helper(MONTGOMERY, mm2, base, exp, q, p, crt.p_inverse) ) % (p * q); }
uberzahl modexp_crt(crt_t & crt, uberzahl base, uberzahl exp, uberzahl p, uberzahl q){ mm_t mm; if(!crt.initialized){ crt.p_inverse = p.inverse(q); crt.q_inverse = q.inverse(p); crt.initialized = true; } return ( crt_helper(CLASSIC,mm, base,exp,p,q,crt.q_inverse) + crt_helper(CLASSIC, mm, base, exp, q, p, crt.p_inverse) ) % (p * q); }
//we don't have to bother with making sure that gcd(R,M) == 1 since M is odd. uberzahl modexp_mm(mm_t & mm, uberzahl base, uberzahl exp, uberzahl M){ if(!mm.initialized){ mm.R = next_power(M); mm.Rbits = mm.R.bitLength(); mm.Mprime = (mm.R-M.inverse(mm.R)); uberzahl z("1"); uberzahl t("2"); mm.Rsq = modexp(mm.R,t,M); //mm.z_init = mm.R % M; mm.z_init = montgomery_reduction(mm.Rsq, M, mm.Mprime, mm.Rbits, mm.R); mm.initialized = true; } //convert into Montgomery space uberzahl z = mm.z_init; //According to Piazza post we don't even need to calculate the residues with mod if(base * mm.Rsq < mm.R*M) base = montgomery_reduction(base * mm.Rsq, M, mm.Mprime, mm.Rbits, mm.R); else base = base * mm.R % M; mediumType i = exp.bitLength() - 1; while(i >= 0) { z = montgomery_reduction(z * z, M, mm.Mprime, mm.Rbits, mm.R); if(exp.bit(i) == 1){ z = montgomery_reduction(z * base , M, mm.Mprime, mm.Rbits, mm.R); } if(i == 0) break; i -= 1; } return montgomery_reduction(z, M, mm.Mprime, mm.Rbits, mm.R); }
uberzahl chineseModExp2(uberzahl c, uberzahl a, uberzahl p, uberzahl q){ //a^c mod pq auto start = chrono::steady_clock::now(); uberzahl dp = c % (p-1); uberzahl dq = c % (q-1); uberzahl T = q.inverse(p); uberzahl S = p.inverse(q); uberzahl m1 = originalModExp(dp,a,p,1); uberzahl m2 = originalModExp(dq,a,q,1); uberzahl m = (m1*q*T + m2*p*S) % (p*q); auto current = chrono::steady_clock::now(); auto elapsed = chrono::duration_cast<chrono::duration<double>>(current-start); double chrono_time = elapsed.count(); cerr << "\tSqMult_CRT time: " << chrono_time << "\n"; return m; }