bool paillier_pub::encrypt (crypt_ctext *c, const bigint &msg, bool recover) const { assert (c); assert (c->type == CRYPT_PAILLIER); if (msg >= n) { warn << "paillier_pub::encrypt: input too large [m " << msg.nbits () << " n " << n.nbits () << "]\n"; return false; } bigint &m = *c->paillier; bigint r; do r = random_zn (n); while (r == 0); if (fast) // g^(nr) mod n^2 m = powm (gn, r, nsq); else // r^n mod n^2 m = powm (r, n, nsq); // g^m mod n^2 // r^n g^m mod n^2 OR g^{m+nr} mod n^2 m *= powm (g, msg, nsq); m %= nsq; return true; }
Values encrypt(const MPI & data, const Values & pub){ RNG::BBS(static_cast <MPI> (static_cast <unsigned int> (now()))); // seed just in case not seeded MPI k = bintompi(RNG::BBS().rand(bitsize(pub[0]))); k %= pub[0]; MPI r, s; r = powm(pub[1], k, pub[0]); s = powm(pub[2], k, pub[0]); return {r, (data * s) % pub[0]}; }
Values new_public(const uint32_t & L, const uint32_t & N){ // L = 1024, N = 160 // L = 2048, N = 224 // L = 2048, N = 256 // L = 3072, N = 256 RNG::BBS(static_cast <MPI> (static_cast <unsigned int> (now()))); // seed just in case not seeded // random prime q MPI q = bintompi("1" + RNG::BBS().rand(N - 1)); q = nextprime(q); while (bitsize(q) > N){ q = bintompi("1" + RNG::BBS().rand(N - 1)); q = nextprime(q); } // random prime p = kq + 1 MPI p = bintompi("1" + RNG::BBS().rand(L - 1)); // pick random starting point p = ((p - 1) / q) * q + 1; // set starting point to value such that p = kq + 1 for some k, while maintaining bitsize while (!knuth_prime_test(p, 25)){ p += q; } // generator g with order q MPI g = 1, h = 1; MPI exp = (p - 1) / q; while (g == 1){ h++; g = powm(h, exp, p); } return {p, q, g}; }
Values sign(const MPI & data, const Values & pri, const Values & pub, MPI k){ RNG::BBS(static_cast <MPI> (static_cast <unsigned int> (now()))); // seed just in case not seeded bool set_k = (k == 0); MPI r = 0, s = 0; while ((r == 0) || (s == 0)){ // 0 < k < q if ( set_k ) { k = bintompi(RNG::BBS().rand(bitsize(pub[1]))); k %= pub[1]; } // r = (g^k mod p) mod q r = powm(pub[2], k, pub[0]); r %= pub[1]; // if r == 0, don't bother calculating s if (r == 0){ continue; } // s = k^-1 (m + x * r) mod q s = invert(k, pub[1]); s *= data + pri[0] * r; s %= pub[1]; } return {r, s}; }
Values keygen(Values & pub){ RNG::BBS(static_cast <MPI> (static_cast <unsigned int> (now()))); // seed just in case not seeded MPI x = 0; std::string test = "testing testing 123"; // a string to test the key with, just in case the key doesn't work for some reason unsigned int bits = bitsize(pub[1]) - 1; while (true){ // 0 < x < q while ((x == 0) || (pub[1] <= x)){ x = bintompi(RNG::BBS().rand(bits)); } // y = g^x mod p MPI y; y = powm(pub[2], x, pub[0]); // public key = p, q, g, y // private key = x pub.push_back(y); // check that this key works Values rs = sign(test, {x}, pub); // if it works, break if (verify(test, rs, pub)){ break; } pub.pop_back(); } return {x}; }
int main() { std::cout << pow(3, 10) << '\n'; std::cout << powm(7, 99, 100) << '\n'; return 0; }
std::string decrypt(const Values & c, const Values & pri, const Values & pub){ MPI s, m; s = powm(c[0], pri[0], pub[0]); m = invert(s, pub[0]); m *= c[1]; m %= pub[0]; return mpitoraw(m); }
void paillier_pub::init () { nsq = n; mpz_square (&nsq, &n); if (fast) gn = powm (g, n, nsq); }
inline typename enable_if_c<is_integral<I1>::value && is_signed<I2>::value && is_integral<I3>::value, I1>::type powm(const I1& a, I2 b, I3 c) { if(b < 0) { BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); } return powm(a, static_cast<typename make_unsigned<I2>::type>(b), c); }
// Resulting ciphertext is msg's corresponding plaintext * constant // ctext = ctext^const ==> ptext = const * ptext void paillier_pub::mult (crypt_ctext *c, const crypt_ctext &msg, const bigint &cons) const { assert (c); assert (c->type == CRYPT_PAILLIER); assert (msg.type == CRYPT_PAILLIER); *c->paillier = powm (*msg.paillier, cons, nsq); }
void fips186_gen::gen_g (bigint *g, const bigint &p, const bigint &q) { bigint e = (p - 1) / q; bigint h; bigint p_3 = p - 3; do h = random_zn (p_3); while ((*g = powm (++h, e, p)) == 1); }
// Computes (exponent_le32 * 2^doublings) % group_order boost::multiprecision::cpp_int compute_exponent(const bytestring &exponent_le32, uint64_t doublings) { boost::multiprecision::cpp_int pow(doublings); boost::multiprecision::cpp_int mod("0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed"); // group order boost::multiprecision::cpp_int base(2); boost::multiprecision::cpp_int result = powm(base, pow, mod); result = result * le32_to_cpp_int(exponent_le32); result = result % mod; return result; }
Values keygen(unsigned int bits){ RNG::BBS(static_cast <MPI> (static_cast <unsigned int> (now()))); // seed just in case not seeded bits /= 5; // random prime q - only used for key generation MPI q = bintompi(RNG::BBS().rand(bits)); q = nextprime(q); while (bitsize(q) > bits){ q = bintompi(RNG::BBS().rand(bits)); q = nextprime(q); } bits *= 5; // random prime p = kq + 1 MPI p = bintompi("1" + RNG::BBS().rand(bits - 1)); // pick random starting point p = ((p - 1) / q) * q + 1; // set starting point to value such that p = kq + 1 for some k, while maintaining bitsize while (!knuth_prime_test(p, 25)){ p += q; } // generator g with order p MPI g = 1; MPI h = 1; MPI exp = (p - 1) / q; while (g == 1){ g = powm(++h, exp, p); } // 0 < x < p MPI x = 0; while ((x == 0) || (p <= x)){ x = bintompi(RNG::BBS().rand(bits)); } // y = g^x mod p MPI y; y = powm(g, x, p); return {p, g, y, x}; }
void t5() { // // Now integer functions: // ref_type z1, z2; test_type t1, t2; divide_qr(a, b, z1, z2); divide_qr(a1, b1, t1, t2); BOOST_TEST_EQ(z1.str(), t1.str()); BOOST_TEST_EQ(z2.str(), t2.str()); BOOST_TEST_EQ(integer_modulus(a, si), integer_modulus(a1, si)); BOOST_TEST_EQ(lsb(a), lsb(a1)); for(unsigned i = 0; i < 1000; i += 13) { BOOST_TEST_EQ(bit_test(a, i), bit_test(a1, i)); } // We have to take care that our powers don't grow too large, otherwise this takes "forever", // also don't test for modulo types, as these may give a different result from arbitrary // precision types: BOOST_TEST_EQ(ref_type(pow(d, ui % 19)).str(), test_type(pow(d1, ui % 19)).str()); BOOST_TEST_EQ(ref_type(powm(a, b, c)).str(), test_type(powm(a1, b1, c1)).str()); BOOST_TEST_EQ(ref_type(powm(a, b, ui)).str(), test_type(powm(a1, b1, ui)).str()); BOOST_TEST_EQ(ref_type(powm(a, ui, c)).str(), test_type(powm(a1, ui, c1)).str()); }
bool verify(const MPI & data, const Values & sig, const Values & pub){ // 0 < r < q or 0 < s < q if (!((0 < sig[0]) && (sig[0] < pub[1])) & !((0 < sig[0]) && (sig[1] < pub[1]))){ return false; } // w = s^-1 mod q MPI w = invert(sig[1], pub[1]); // u1 = H(m) * w mod q MPI u1 = (data * w) % pub[1]; // u2 = r * w mod q MPI u2 = (sig[0] * w) % pub[1]; // v = ((g ^ u1 * y ^ u2) mod p) mod q MPI g, y; g = powm(pub[2], u1, pub[0]); y = powm(pub[3], u2, pub[0]); // check v == r return ((((g * y) % pub[0]) % pub[1]) == sig[0]); }
// Calculate fast decryption with chinese remainder and pre-computed values void paillier_priv::D (bigint &m, const bigint &msg) const { #if _PAILLIER_CRT_ // mq = Lq (msg^a mod q^2) hq mod q bigint mq; if (fast) mq = powm (msg, a, qsq); else mq = powm (msg, q1, qsq); // Compute Lq (m) mq -= 1; mq *= lq; mq %= two_q; m %= q; mq *= hq; mq %= q; // mp = Lp (msg^a mod p^2) hp mod p if (fast) m = powm (msg, a, psq); else m = powm (msg, p1, psq); // Compute L_p(m) m -= 1; m *= lp; m %= two_p; m %= p; m *= hp; m %= p; // Recombine modulo residues CRT (m, mq); #else /* PAILLIER_CRT */ if (fast) m = powm (msg, a, nsq); else m = powm (msg, k, nsq); m -= 1; m *= ln; m %= two_n; m %= n; m *= hn; m %= n; #endif }
static void paillier_gen (const bigint &p, const bigint &q, const bigint &n, const bigint &a, bigint &g, bigint &k) { bigint p1 = p - 1; bigint q1 = q - 1; bigint kgcd; mpz_gcd (&kgcd, &p1, &q1); k = p1 * q1; k /= kgcd; if (!p.probab_prime (5) || !q.probab_prime (5) || !a.probab_prime (5)) fatal ("paillier_keygen: failed primality test\n"); if ((k % a) != 0) fatal << "paillier_keygen: failed div test: " << (k % a) << "\n"; g = powm (2, (k/a), n); }
int decrypt_mpz_d(mpz_t m, mpz_t d, const char *n_str, const char *c_str) { int rc = 0; mpz_t n, c; rc += mpz_init_set_str(n, n_str, 0); rc += mpz_init_set_str(c, c_str, 0); if (rc != 0) { fprintf(stderr, "Invalid number argument\n"); rc = 1; goto cleanup; } powm(m, c, d, n); cleanup: mpz_clear(n); mpz_clear(c); return rc; }
void paillier_priv::init () { assert (p < q); psq = p; mpz_square (&psq, &p); qsq = q; mpz_square (&qsq, &q); p1 = p - 1; q1 = q - 1; if (!fast) { bigint kgcd; mpz_gcd (&kgcd, &p1, &q1); k = p1 * q1; k /= kgcd; } #if _PAILLIER_CRT_ rp = invert (q, p); rq = invert (p, q); two_p = pow (2, p.nbits ()); two_q = pow (2, q.nbits ()); lp = invert (p, two_p); lq = invert (q, two_q); if (fast) { hp = powm (g, a, psq); hq = powm (g, a, qsq); } else { hp = powm (g, p1, psq); hq = powm (g, q1, qsq); } hp -= 1; hp *= lp; hp %= two_p; hp = invert (hp, p); hq -= 1; hq *= lq; hq %= two_q; hq = invert (hq, q); #else /* PAILLIER_CRT */ two_n = pow (2, n.nbits ()); ln = invert (n, two_n); if (fast) hn = powm (g, a, nsq); else hn = powm (g, k, nsq); hn -= 1; hn *= ln; hn %= two_n; hn = invert (hn, n); #endif }
Int RSA::encrypt(std::pair<Int, Int> pk, Int message){ //modexp(m, pk) return powm(message, pk.second, pk.first); }
int main (int argc, char **argv) { random_update (); bigint m, m2, r, r2, ri, s1, s2; montgom b; for (int i = 120; i < 162; i++) { int res = 0; m = random_bigint (i); m.setbit (0, 1); b.set (m); m2 = m * b.getr (); for (int j = i - 33; j <= 2 * i; j++) { r = random_zn (m2); r.trunc (j); s1 = mod (r * b.getri (), m); //s2 = b.mreduce (r); b.mpz_mreduce (&s2, &r); if (s1 != s2) { res |= 1; int sz = mpz_sizeinbase (&s1, 16); panic << "mreduce failed\n" << " m = " << m << "\n" << " r = " << r << "\n" << " " << s1 << "\n != " << s2 << "\n" << " [" << strbuf ("%*s", sz, bigint (abs (s1 - s2)).cstr ()) << "]\n"; } } // r = s1; r = random_zn (m); r2 = random_zn (m); assert (r < m && r2 < m); s1 = mod (r * r2 * b.getri (), m); b.mpz_mmul (&s2, &r, &r2); if (s1 != s2) { res |= 2; int sz = mpz_sizeinbase (&s1, 16); panic << "mmul failed\n" << " m = " << m << "\n" << " r = " << r << "\n" << " " << s1 << "\n != " << s2 << "\n" << " [" << strbuf ("%*s", sz, bigint (abs (s1 - s2)).cstr ()) << "]\n"; } s1 = powm (r, r2, m); b.mpz_powm (&s2, &r, &r2); if (s1 != s2) { res |= 4; int sz = mpz_sizeinbase (&s1, 16); panic << "powm failed\n" << " m = " << m << "\n" << " r = " << r << "\n" << " " << s1 << "\n != " << s2 << "\n" << " [" << strbuf ("%*s", sz, bigint (abs (s1 - s2)).cstr ()) << "]\n"; } #if 0 warn ("%s mreduce.. %d\n", (res&1) ? "fail" : "ok", i); warn ("%s mmul.. %d\n", (res&2) ? "fail" : "ok", i); warn ("%s powm.. %d\n", (res&4) ? "fail" : "ok", i); #endif } return 0; }
Int RSA::decrypt(std::pair<Int, Int> sk, Int ciphertext){ return powm(ciphertext, sk.second, sk.first); }
void BBS::r_number(){ state = powm(state, two, m); }