/* * Multiplier.cpp * */ #include #include "FHEOffline/PairwiseGenerator.h" #include "FHEOffline/PairwiseMachine.h" #include "Math/modp.hpp" template Multiplier::Multiplier(int offset, PairwiseGenerator& generator) : Multiplier(offset, generator.machine, generator.P, generator.timers) { } template Multiplier::Multiplier(int offset, PairwiseMachine& machine, Player& P, map& timers) : machine(machine), P(P, offset), num_players(P.num_players()), my_num(P.my_num()), other_pk(machine.other_pks[(my_num + num_players - offset) % num_players]), other_enc_alpha(machine.enc_alphas[(my_num + num_players - offset) % num_players]), timers(timers), C(machine.pk), mask(machine.pk), product_share(machine.setup().FieldD), rc(machine.pk), volatile_capacity(0) { product_share.allocate_slots(machine.pk.p() << 64); } template void Multiplier::multiply_and_add(Plaintext_& res, const Ciphertext& enc_a, const Plaintext_& b) { Rq_Element bb(enc_a.get_params(), evaluation, evaluation); bb.from(b.get_iterator()); multiply_and_add(res, enc_a, bb); } template void Multiplier::multiply_and_add(Plaintext_& res, const Ciphertext& enc_a, const Rq_Element& b, OT_ROLE role) { o.reset_write_head(); if (role & SENDER) { PRNG G; G.ReSeed(); timers["Ciphertext multiplication"].start(); C.mul(enc_a, b); timers["Ciphertext multiplication"].stop(); timers["Mask randomization"].start(); product_share.randomize(G); bigint B = 6 * machine.setup().params.get_R(); B *= machine.setup().FieldD.get_prime(); B <<= machine.drown_sec; // slack B *= NonInteractiveProof::slack(machine.sec, machine.setup().params.phi_m()); B <<= machine.extra_slack; rc.generateUniform(G, 0, B, B); timers["Mask randomization"].stop(); timers["Encryption"].start(); other_pk.encrypt(mask, product_share, rc); timers["Encryption"].stop(); mask += C; mask.pack(o); res -= product_share; } timers["Multiplied ciphertext sending"].start(); if (role == BOTH) P.reverse_exchange(o); else if (role == SENDER) P.reverse_send(o); else if (role == RECEIVER) P.receive(o); timers["Multiplied ciphertext sending"].stop(); if (role & RECEIVER) { timers["Decryption"].start(); C.unpack(o); machine.sk.decrypt_any(product_share, C); res += product_share; timers["Decryption"].stop(); } memory_usage.update("multiplied ciphertext", C.report_size(CAPACITY)); memory_usage.update("mask ciphertext", mask.report_size(CAPACITY)); memory_usage.update("product shares", product_share.report_size(CAPACITY)); memory_usage.update("masking random coins", rc.report_size(CAPACITY)); } template void Multiplier::multiply_alpha_and_add(Plaintext_& res, const Rq_Element& b, OT_ROLE role) { multiply_and_add(res, other_enc_alpha, b, role); } template size_t Multiplier::report_size(ReportType type) { return C.report_size(type) + mask.report_size(type) + product_share.report_size(type) + rc.report_size(type); } template void Multiplier::report_size(ReportType type, MemoryUsage& res) { (void)type; res += memory_usage; } template class Multiplier; template class Multiplier;