From 01cfdb01491840a57fd32ae219603176eae3c968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolai=20M=C3=BCller?= Date: Fri, 20 Sep 2024 11:21:20 +0200 Subject: [PATCH] Improved Sharing --- inc/Util/Sharing.hpp | 30 ++-- src/Util/Sharing.cpp | 332 ++++++++++++++++++++----------------------- 2 files changed, 163 insertions(+), 199 deletions(-) diff --git a/inc/Util/Sharing.hpp b/inc/Util/Sharing.hpp index bfa7d22..7779ddd 100644 --- a/inc/Util/Sharing.hpp +++ b/inc/Util/Sharing.hpp @@ -127,26 +127,13 @@ class Sharing { std::vector SampleRandomBitslicedPolynomial(); private: - /** - * @brief Converts a polynomial represented as coefficient vector to an fq_t - * polynomial. - * @param polynomial The polynomial represented as coefficient vector. - * @param polynomial_fq The converted polynomial stored as an fq_t. - */ - void ConvertPolynomialToFq(Polynomial& polynomial, fq_t& polynomial_fq) const; - /** * @brief Converts an fq_t polynomial to a polynomial represented as * coefficient vector. * @param polynomial_fq The polynomial represented as an fq_t. * @param polynomial_fq The converted polynomial stored as coefficient vector. */ - void ConvertFqToPolynomial(fq_t& polynomial_fq, Polynomial& polynomial) const; - - Polynomial ConvertBitsetToPolynomial( - const boost::dynamic_bitset<>& bitset) const; - boost::dynamic_bitset<> ConvertPolynomialToBitset( - const Polynomial& polynomial) const; + void ConvertFqToPolynomial(fq_t& polynomial_fq, Polynomial& polynomial); void SampleRandomPolynomial(fq_t& random_polynomial_fq); @@ -173,8 +160,6 @@ class Sharing { */ bool IsInField(const Polynomial& polynomial) const; - uint64_t GetLengthOfElementsInBits() const; - /** * @brief Encodes an unshared polynomial X into its shared representation * Sh(X). @@ -185,7 +170,7 @@ class Sharing { * that it satisfies the additive sharing property. Further, 'o' denotes the * operation under the finite field. * - * @param polynomial The unshared polynomial to be encoded. + * @param polynomial_fq The unshared polynomial to be encoded. * @param number_of_shares The number of shares to generate, denoted as d. * @param is_additive_masking A boolean indicating the operation used: * - true: The operation is additive, so '+' is used. @@ -194,7 +179,7 @@ class Sharing { * * @return A vector of d polynomials representing the shared * representation Sh(X). */ - std::vector Encode(Polynomial& polynomial, + std::vector Encode(fq_t& polynomial_fq, uint64_t number_of_shares, bool is_additive_masking); @@ -213,16 +198,17 @@ class Sharing { * finite field. * @return The decoded (unshared) polynomial. */ - Polynomial Decode(std::vector shared_polynomial, - bool is_additive_masking) const; + Polynomial Decode(std::vector& shared_polynomial_fq, + bool is_additive_masking); uint64_t prime_base_; uint64_t extension_degree_; uint64_t size_coefficients_bits_; - boost::uniform_int dist_; - boost::variate_generator> gen_; + uint64_t length_of_elements_in_bits_; fmpz_t prime_fmpz_; fq_ctx_t ctx_fq_; + flint_rand_t random_state_; + fmpz_mod_poly_t fmpz_poly_; fmpz_mod_ctx_t ctx_fmpz_mod_; }; \ No newline at end of file diff --git a/src/Util/Sharing.cpp b/src/Util/Sharing.cpp index c94b2c1..99e51c9 100644 --- a/src/Util/Sharing.cpp +++ b/src/Util/Sharing.cpp @@ -5,36 +5,45 @@ Sharing::Sharing(uint64_t prime_base, uint64_t extension_degree, : prime_base_(prime_base), extension_degree_(extension_degree), size_coefficients_bits_(std::ceil(std::log2l(prime_base))), - dist_(0, std::numeric_limits::max()), - gen_(rng, dist_) { + length_of_elements_in_bits_(size_coefficients_bits_ * extension_degree) { fmpz_init(prime_fmpz_); fmpz_set_ui(prime_fmpz_, prime_base_); + flint_randinit(random_state_); + + boost::uniform_int dist_(0, std::numeric_limits::max()); + boost::variate_generator> gen_( + rng, dist_); + + mp_limb_t seed1 = gen_(); + mp_limb_t seed2 = gen_(); + flint_randseed(random_state_, seed1, seed2); if (!irreducible_polynomial.empty()) { fmpz_mod_ctx_init(ctx_fmpz_mod_, prime_fmpz_); - fmpz_mod_poly_t modulus_poly; - fmpz_mod_poly_init(modulus_poly, ctx_fmpz_mod_); + fmpz_mod_poly_init(fmpz_poly_, ctx_fmpz_mod_); for (uint64_t index = 0; index < irreducible_polynomial.size(); ++index) { fmpz_t coeff_fmpz; fmpz_init_set_ui(coeff_fmpz, irreducible_polynomial[index]); - fmpz_mod_poly_set_coeff_fmpz(modulus_poly, index, coeff_fmpz, + fmpz_mod_poly_set_coeff_fmpz(fmpz_poly_, index, coeff_fmpz, ctx_fmpz_mod_); fmpz_clear(coeff_fmpz); } - fq_ctx_init_modulus(ctx_fq_, modulus_poly, ctx_fmpz_mod_, "x"); - fmpz_mod_poly_clear(modulus_poly, ctx_fmpz_mod_); + fq_ctx_init_modulus(ctx_fq_, fmpz_poly_, ctx_fmpz_mod_, "x"); fmpz_clear(prime_fmpz_); } else { fq_ctx_init(ctx_fq_, prime_fmpz_, extension_degree_, "x"); fmpz_mod_ctx_init(ctx_fmpz_mod_, prime_fmpz_); + fmpz_mod_poly_init(fmpz_poly_, ctx_fmpz_mod_); } } Sharing::~Sharing() { fmpz_clear(prime_fmpz_); fq_ctx_clear(ctx_fq_); + flint_randclear(random_state_); + fmpz_mod_poly_clear(fmpz_poly_, ctx_fmpz_mod_); fmpz_mod_ctx_clear(ctx_fmpz_mod_); } @@ -43,181 +52,193 @@ std::vector> Sharing::EncodeBitsliced( uint64_t number_of_shares, bool is_additive_masking) { std::string error_context = "Error while encoding a bitsliced polynomial."; std::vector> bitsliced_shared_polynomial( - number_of_shares, std::vector(GetLengthOfElementsInBits(), 0)); - boost::dynamic_bitset<> bitset(GetLengthOfElementsInBits()); - uint64_t bit_index, share_index, simulation_index; + number_of_shares, std::vector(length_of_elements_in_bits_, 0)); + uint64_t coefficient_index, bit_index, share_index, simulation_index, index; std::vector shared_polynomial; - Polynomial polynomial; + + uint64_t coefficient; + fmpz_t coefficient_fmpz; + fmpz_init(coefficient_fmpz); + + fq_t polynomial_fq; + fq_init(polynomial_fq, ctx_fq_); for (simulation_index = 0; simulation_index < 64; ++simulation_index) { - for (bit_index = 0; bit_index < GetLengthOfElementsInBits(); ++bit_index) { - bitset[bit_index] = - (bitsliced_polynomial[bit_index] >> (63 - simulation_index)) & 1; - } + fmpz_mod_poly_zero(fmpz_poly_, ctx_fmpz_mod_); + + for (coefficient_index = 0; coefficient_index < extension_degree_; + ++coefficient_index) { + coefficient = 0; + index = (coefficient_index + 1) * size_coefficients_bits_ - 1; + + for (bit_index = 0; bit_index < size_coefficients_bits_; ++bit_index) { + coefficient <<= 1; + coefficient |= + (bitsliced_polynomial[index] >> (63 - simulation_index)) & 1; + --index; + } - polynomial = ConvertBitsetToPolynomial(bitset); + if (coefficient >= prime_base_) { + throw std::invalid_argument( + error_context + + " The unshared input polynomial is not in the field!"); + } + + fmpz_set_ui(coefficient_fmpz, coefficient); + fmpz_mod_poly_set_coeff_fmpz(fmpz_poly_, coefficient_index, + coefficient_fmpz, ctx_fmpz_mod_); + } - if (IsInField(polynomial)) { - shared_polynomial = - Encode(polynomial, number_of_shares, is_additive_masking); + fq_set_fmpz_mod_poly(polynomial_fq, fmpz_poly_, ctx_fq_); - for (share_index = 0; share_index < number_of_shares; ++share_index) { - if (IsInField(shared_polynomial[share_index])) { - bitset = ConvertPolynomialToBitset(shared_polynomial[share_index]); + shared_polynomial = + Encode(polynomial_fq, number_of_shares, is_additive_masking); - for (bit_index = 0; bit_index < GetLengthOfElementsInBits(); + for (share_index = 0; share_index < number_of_shares; ++share_index) { + if (IsInField(shared_polynomial[share_index])) { + index = 0; + for (coefficient_index = 0; coefficient_index < extension_degree_; + ++coefficient_index) { + for (bit_index = 0; bit_index < size_coefficients_bits_; ++bit_index) { - bitsliced_shared_polynomial[share_index][bit_index] <<= 1; - bitsliced_shared_polynomial[share_index][bit_index] |= - bitset[bit_index]; + bitsliced_shared_polynomial[share_index][index] <<= 1; + bitsliced_shared_polynomial[share_index][index] |= + shared_polynomial[share_index][coefficient_index] & 1; + shared_polynomial[share_index][coefficient_index] >>= 1; + ++index; } - } else { - throw std::invalid_argument( - error_context + - " One of the shared output polynomials is not in the field!"); } + } else { + throw std::invalid_argument( + error_context + + " One of the shared output polynomials is not in the field!"); } - - } else { - throw std::invalid_argument( - error_context + - " The unshared input polynomial is not in the field!"); } } + fq_clear(polynomial_fq, ctx_fq_); + fmpz_clear(coefficient_fmpz); return bitsliced_shared_polynomial; } std::vector Sharing::DecodeBitsliced( const std::vector>& bitsliced_shared_polynomial, bool is_additive_masking) { - std::vector bitsliced_polynomial(GetLengthOfElementsInBits(), 0); - boost::dynamic_bitset<> bitset(GetLengthOfElementsInBits()); - std::vector shared_polynomial(bitsliced_shared_polynomial.size()); - uint64_t bit_index, share_index, simulation_index; + uint64_t number_of_shares = bitsliced_shared_polynomial.size(); + std::vector bitsliced_polynomial(length_of_elements_in_bits_, 0); + std::vector shared_polynomial_fq(number_of_shares); + uint64_t bit_index, coefficient_index, share_index, simulation_index, index; Polynomial polynomial; + uint64_t coefficient; + fmpz_t coefficient_fmpz; + fmpz_init(coefficient_fmpz); + + for (fq_t& polynomial_fq : shared_polynomial_fq) { + fq_init(polynomial_fq, ctx_fq_); + } + for (simulation_index = 0; simulation_index < 64; ++simulation_index) { - for (share_index = 0; share_index < bitsliced_shared_polynomial.size(); - ++share_index) { - for (bit_index = 0; bit_index < GetLengthOfElementsInBits(); - ++bit_index) { - bitset[bit_index] = - (bitsliced_shared_polynomial[share_index][bit_index] >> - (63 - simulation_index)) & - 1; - } + for (share_index = 0; share_index < number_of_shares; ++share_index) { + fmpz_mod_poly_zero(fmpz_poly_, ctx_fmpz_mod_); + + for (coefficient_index = 0; coefficient_index < extension_degree_; + ++coefficient_index) { + coefficient = 0; + index = (coefficient_index + 1) * size_coefficients_bits_ - 1; + + for (bit_index = 0; bit_index < size_coefficients_bits_; ++bit_index) { + coefficient <<= 1; + coefficient |= (bitsliced_shared_polynomial[share_index][index] >> + (63 - simulation_index)) & + 1; + --index; + } - shared_polynomial[share_index] = ConvertBitsetToPolynomial(bitset); + fmpz_set_ui(coefficient_fmpz, coefficient); + fmpz_mod_poly_set_coeff_fmpz(fmpz_poly_, coefficient_index, + coefficient_fmpz, ctx_fmpz_mod_); + } - /*if (!IsInField(shared_polynomial[share_index])) { - throw std::invalid_argument( - "Error while decoding a bitsliced shared polynomial. The " - "polynomial is not in the field!"); - }*/ + fq_set_fmpz_mod_poly(shared_polynomial_fq[share_index], fmpz_poly_, + ctx_fq_); } - polynomial = Decode(shared_polynomial, is_additive_masking); - bitset = ConvertPolynomialToBitset(polynomial); - - for (bit_index = 0; bit_index < GetLengthOfElementsInBits(); ++bit_index) { - bitsliced_polynomial[bit_index] <<= 1; - bitsliced_polynomial[bit_index] |= bitset[bit_index]; + polynomial = Decode(shared_polynomial_fq, is_additive_masking); + index = 0; + for (coefficient_index = 0; coefficient_index < extension_degree_; + ++coefficient_index) { + for (bit_index = 0; bit_index < size_coefficients_bits_; ++bit_index) { + bitsliced_polynomial[index] <<= 1; + bitsliced_polynomial[index] |= polynomial[coefficient_index] & 1; + polynomial[coefficient_index] >>= 1; + ++index; + } } } - return bitsliced_polynomial; -} - -uint64_t Sharing::GetLengthOfElementsInBits() const { - return size_coefficients_bits_ * extension_degree_; -} - -void Sharing::ConvertPolynomialToFq(Polynomial& polynomial, - fq_t& polynomial_fq) const { - fmpz_t coefficient_fmpz; - fmpz_init(coefficient_fmpz); - fmpz_mod_poly_t polynomial_fmpz; - fmpz_mod_poly_init(polynomial_fmpz, ctx_fmpz_mod_); - - for (uint64_t index = 0; index < polynomial.size(); ++index) { - fmpz_set_ui(coefficient_fmpz, polynomial[index]); - fmpz_mod_poly_set_coeff_fmpz(polynomial_fmpz, index, coefficient_fmpz, - ctx_fmpz_mod_); + for (fq_t& polynomial_fq : shared_polynomial_fq) { + fq_clear(polynomial_fq, ctx_fq_); } - fq_set_fmpz_mod_poly(polynomial_fq, polynomial_fmpz, ctx_fq_); - fmpz_mod_poly_clear(polynomial_fmpz, ctx_fmpz_mod_); fmpz_clear(coefficient_fmpz); + return bitsliced_polynomial; } void Sharing::ConvertFqToPolynomial(fq_t& polynomial_fq, - Polynomial& polynomial) const { - fmpz_t coefficient_fmpz; - fmpz_init(coefficient_fmpz); - fmpz_mod_poly_t polynomial_fmpz; - fmpz_mod_poly_init(polynomial_fmpz, ctx_fmpz_mod_); - fq_get_fmpz_mod_poly(polynomial_fmpz, polynomial_fq, ctx_fq_); - - for (uint64_t index = 0; index < (uint64_t)fq_ctx_degree(ctx_fq_); ++index) { - fmpz_mod_poly_get_coeff_fmpz(coefficient_fmpz, polynomial_fmpz, index, - ctx_fmpz_mod_); - polynomial.push_back(fmpz_get_ui(coefficient_fmpz)); + Polynomial& polynomial) { + fmpz_t fmpz_coef; + fmpz_init(fmpz_coef); + fmpz_mod_poly_zero(fmpz_poly_, ctx_fmpz_mod_); + fq_get_fmpz_mod_poly(fmpz_poly_, polynomial_fq, ctx_fq_); + + for (uint64_t index = 0; index < extension_degree_; ++index) { + fmpz_mod_poly_get_coeff_fmpz(fmpz_coef, fmpz_poly_, index, ctx_fmpz_mod_); + polynomial[index] = fmpz_get_ui(fmpz_coef); } - fmpz_mod_poly_clear(polynomial_fmpz, ctx_fmpz_mod_); - fmpz_clear(coefficient_fmpz); + fmpz_clear(fmpz_coef); } void Sharing::SampleRandomPolynomial(fq_t& random_polynomial_fq) { - fmpz_mod_poly_t random_fmpz; - fmpz_mod_poly_init(random_fmpz, ctx_fmpz_mod_); - - fmpz_t coefficient; - fmpz_init(coefficient); - - for (uint64_t index = 0; index < extension_degree_; ++index) { - fmpz_set_ui(coefficient, gen_()); - fmpz_mod_poly_set_coeff_fmpz(random_fmpz, index, coefficient, - ctx_fmpz_mod_); - } - - fq_set_fmpz_mod_poly(random_polynomial_fq, random_fmpz, ctx_fq_); - fmpz_mod_poly_clear(random_fmpz, ctx_fmpz_mod_); - fmpz_clear(coefficient); + fmpz_mod_poly_randtest(fmpz_poly_, random_state_, extension_degree_, + ctx_fmpz_mod_); + fq_set_fmpz_mod_poly(random_polynomial_fq, fmpz_poly_, ctx_fq_); } std::vector Sharing::SampleRandomBitslicedPolynomial() { - uint64_t index, bit_index, bit_width = GetLengthOfElementsInBits(); - std::vector bitsliced_polynomial(bit_width); - boost::dynamic_bitset<> bitset; + uint64_t bit_index, coefficient_index, simulation_index, index; + std::vector bitsliced_polynomial(length_of_elements_in_bits_, 0); - for (index = 0; index < 64; ++index) { - fq_t polynomial_fq; - Polynomial polynomial; - fq_init(polynomial_fq, ctx_fq_); - SampleRandomPolynomial(polynomial_fq); - ConvertFqToPolynomial(polynomial_fq, polynomial); - bitset = ConvertPolynomialToBitset(polynomial); + uint64_t coefficient; + fmpz_t fmpz_coef; + fmpz_init(fmpz_coef); - for (bit_index = 0; bit_index < bit_width; ++bit_index) { - bitsliced_polynomial[bit_index] <<= 1; - bitsliced_polynomial[bit_index] |= bitset[bit_index]; + for (simulation_index = 0; simulation_index < 64; ++simulation_index) { + index = 0; + fmpz_mod_poly_randtest(fmpz_poly_, random_state_, extension_degree_, ctx_fmpz_mod_); + for (coefficient_index = 0; coefficient_index < extension_degree_; + ++coefficient_index) { + fmpz_mod_poly_get_coeff_fmpz(fmpz_coef, fmpz_poly_, index, ctx_fmpz_mod_); + coefficient = fmpz_get_ui(fmpz_coef); + for (bit_index = 0; bit_index < size_coefficients_bits_; ++bit_index) { + bitsliced_polynomial[index] <<= 1; + bitsliced_polynomial[index] |= coefficient & 1; + coefficient >>= 1; + ++index; + } } - - fq_clear(polynomial_fq, ctx_fq_); } + fmpz_clear(fmpz_coef); return bitsliced_polynomial; } -std::vector Sharing::Encode(Polynomial& polynomial, +std::vector Sharing::Encode(fq_t& polynomial_fq, uint64_t number_of_shares, bool is_additive_masking) { - fq_t polynomial_fq; - fq_init(polynomial_fq, ctx_fq_); - ConvertPolynomialToFq(polynomial, polynomial_fq); - std::vector shared_polynomial(number_of_shares); + std::vector shared_polynomial(number_of_shares, + Polynomial(extension_degree_)); std::vector shared_polynomial_fq(number_of_shares); for (fq_t& share_fq : shared_polynomial_fq) { @@ -261,74 +282,31 @@ std::vector Sharing::Encode(Polynomial& polynomial, fq_clear(share_fq, ctx_fq_); } - fq_clear(polynomial_fq, ctx_fq_); return shared_polynomial; } -Polynomial Sharing::Decode(std::vector shared_polynomial, - bool is_additive_masking) const { - Polynomial polynomial; - fq_t polynomial_fq, operand_fq; +Polynomial Sharing::Decode(std::vector& shared_polynomial_fq, + bool is_additive_masking) { + Polynomial polynomial(extension_degree_); + fq_t polynomial_fq; fq_init(polynomial_fq, ctx_fq_); - fq_init(operand_fq, ctx_fq_); if (is_additive_masking) { - for (auto& share : shared_polynomial) { - ConvertPolynomialToFq(share, operand_fq); + for (fq_t& operand_fq : shared_polynomial_fq) { fq_add(polynomial_fq, polynomial_fq, operand_fq, ctx_fq_); } } else { fq_one(polynomial_fq, ctx_fq_); - for (auto& share : shared_polynomial) { - ConvertPolynomialToFq(share, operand_fq); + for (fq_t& operand_fq : shared_polynomial_fq) { fq_mul(polynomial_fq, polynomial_fq, operand_fq, ctx_fq_); } } ConvertFqToPolynomial(polynomial_fq, polynomial); fq_clear(polynomial_fq, ctx_fq_); - fq_clear(operand_fq, ctx_fq_); - return polynomial; -} - -Polynomial Sharing::ConvertBitsetToPolynomial( - const boost::dynamic_bitset<>& bitset) const { - uint64_t number_of_coefficients = bitset.size() / size_coefficients_bits_; - uint64_t mask = (1 << size_coefficients_bits_) - 1; - uint64_t bitset_as_integer = bitset.to_ulong(); - Polynomial polynomial(number_of_coefficients, 0); - - if (bitset.size() == GetLengthOfElementsInBits()) { - for (uint64_t& coefficient : polynomial) { - coefficient = bitset_as_integer & mask; - bitset_as_integer >>= size_coefficients_bits_; - } - } else { - throw std::invalid_argument( - "Error while converting a bitset to a coefficient vector. The bitset " - "size is not a multiple of the coefficient size!"); - } - return polynomial; } -boost::dynamic_bitset<> Sharing::ConvertPolynomialToBitset( - const Polynomial& polynomial) const { - uint64_t number_of_bits = GetLengthOfElementsInBits(); - uint64_t bit_index, coefficient_index; - boost::dynamic_bitset<> bitset(number_of_bits); - - for (coefficient_index = 0; coefficient_index < polynomial.size(); - ++coefficient_index) { - for (bit_index = 0; bit_index < size_coefficients_bits_; ++bit_index) { - bitset[coefficient_index * size_coefficients_bits_ + bit_index] = - (polynomial[coefficient_index] >> bit_index) & 1; - } - } - - return bitset; -} - bool Sharing::IsInField(const Polynomial& polynomial) const { if (polynomial.size() != extension_degree_) { return false;