From 3fd2d08e741cab37d4feeb824b1a1256c7a9901a Mon Sep 17 00:00:00 2001 From: Phi Hung Le Date: Mon, 11 Dec 2023 17:37:28 -0500 Subject: [PATCH 01/10] Add test to verify aes against NIST test vector. --- .../math/open_ssl_uniform_random_generator.h | 9 ++++ .../open_ssl_uniform_random_generator_test.cc | 46 +++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/main/cc/math/open_ssl_uniform_random_generator.h b/src/main/cc/math/open_ssl_uniform_random_generator.h index 1292f64..c5eb91f 100644 --- a/src/main/cc/math/open_ssl_uniform_random_generator.h +++ b/src/main/cc/math/open_ssl_uniform_random_generator.h @@ -62,6 +62,15 @@ class OpenSslUniformRandomGenerator { int status(); }; +// A uniform pseudorandom generator based on AES-256 counter mode. This is one +// of the approved Deterministic Random Bit Generators specified in the NIST +// SP 800-90A Rev.1 documentation. +// +// The AES is initialized with a key and an IV. The IV is used as the initial +// counter and has the same length as the block length. +// +// Any implementation of the AES-256 counter mode must be verified against the +// test vectors specified in the NIST SP 800-38A documentation. class OpenSslUniformPseudorandomGenerator : public UniformPseudorandomGenerator { public: diff --git a/src/test/cc/math/open_ssl_uniform_random_generator_test.cc b/src/test/cc/math/open_ssl_uniform_random_generator_test.cc index 1d9eb6c..cb1de9b 100644 --- a/src/test/cc/math/open_ssl_uniform_random_generator_test.cc +++ b/src/test/cc/math/open_ssl_uniform_random_generator_test.cc @@ -201,5 +201,51 @@ TEST(OpenSslUniformPseudorandomGenerator, ASSERT_EQ(seq1, seq2); } +TEST(OpenSslUniformPseudorandomGenerator, + OpenSslPRNGCompliceWithNISTTestVectorSucceeds) { + std::vector key = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, + 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, + 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4}; + std::vector iv = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, + 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, + 0xfc, 0xfd, 0xfe, 0xff}; + std::vector output_block_1 = { + 0x0b, 0xdf, 0x7d, 0xf1, 0x59, 0x17, 0x16, 0x33, + 0x5e, 0x9a, 0x8b, 0x15, 0xc8, 0x60, 0xc5, 0x02}; + std::vector output_block_2 = { + 0x5a, 0x6e, 0x69, 0x9d, 0x53, 0x61, 0x19, 0x06, + 0x54, 0x33, 0x86, 0x3c, 0x8f, 0x65, 0x7b, 0x94}; + std::vector output_block_3 = { + 0x1b, 0xc1, 0x2c, 0x9c, 0x01, 0x61, 0x0d, 0x5d, + 0x0d, 0x8b, 0xd6, 0xa3, 0x37, 0x8e, 0xca, 0x62}; + std::vector output_block_4 = { + 0x29, 0x56, 0xe1, 0xc8, 0x69, 0x35, 0x36, 0xb1, + 0xbe, 0xe9, 0x9c, 0x73, 0xa3, 0x15, 0x76, 0xb6}; + + ASSERT_OK_AND_ASSIGN(std::unique_ptr prng, + OpenSslUniformPseudorandomGenerator::Create(key, iv)); + + int kNumRandomBytes = 16; + ASSERT_OK_AND_ASSIGN(std::vector seq1, + prng->GetPseudorandomBytes(kNumRandomBytes)); + ASSERT_OK_AND_ASSIGN(std::vector seq2, + prng->GetPseudorandomBytes(kNumRandomBytes)); + ASSERT_OK_AND_ASSIGN(std::vector seq3, + prng->GetPseudorandomBytes(kNumRandomBytes)); + ASSERT_OK_AND_ASSIGN(std::vector seq4, + prng->GetPseudorandomBytes(kNumRandomBytes)); + + ASSERT_EQ(seq1.size(), kNumRandomBytes); + ASSERT_EQ(seq2.size(), kNumRandomBytes); + ASSERT_EQ(seq3.size(), kNumRandomBytes); + ASSERT_EQ(seq4.size(), kNumRandomBytes); + + ASSERT_EQ(seq1, output_block_1); + ASSERT_EQ(seq2, output_block_2); + ASSERT_EQ(seq3, output_block_3); + ASSERT_EQ(seq4, output_block_4); +} + } // namespace } // namespace wfa::math From f0e59b69b628ebb5603a3ff8b6ca54aa481b73cc Mon Sep 17 00:00:00 2001 From: Phi Hung Le Date: Mon, 11 Dec 2023 17:46:47 -0500 Subject: [PATCH 02/10] Update test variable names. --- .../open_ssl_uniform_random_generator_test.cc | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/test/cc/math/open_ssl_uniform_random_generator_test.cc b/src/test/cc/math/open_ssl_uniform_random_generator_test.cc index cb1de9b..af8ab2f 100644 --- a/src/test/cc/math/open_ssl_uniform_random_generator_test.cc +++ b/src/test/cc/math/open_ssl_uniform_random_generator_test.cc @@ -203,48 +203,51 @@ TEST(OpenSslUniformPseudorandomGenerator, TEST(OpenSslUniformPseudorandomGenerator, OpenSslPRNGCompliceWithNISTTestVectorSucceeds) { - std::vector key = { + // The NIST's test vectors are defined at + // https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38a.pdf + std::vector kTestKey = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4}; - std::vector iv = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, - 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, - 0xfc, 0xfd, 0xfe, 0xff}; - std::vector output_block_1 = { + std::vector kTestIv = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, + 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, + 0xfc, 0xfd, 0xfe, 0xff}; + std::vector kOutputBlock1 = { 0x0b, 0xdf, 0x7d, 0xf1, 0x59, 0x17, 0x16, 0x33, 0x5e, 0x9a, 0x8b, 0x15, 0xc8, 0x60, 0xc5, 0x02}; - std::vector output_block_2 = { + std::vector kOutputBlock2 = { 0x5a, 0x6e, 0x69, 0x9d, 0x53, 0x61, 0x19, 0x06, 0x54, 0x33, 0x86, 0x3c, 0x8f, 0x65, 0x7b, 0x94}; - std::vector output_block_3 = { + std::vector kOutputBlock3 = { 0x1b, 0xc1, 0x2c, 0x9c, 0x01, 0x61, 0x0d, 0x5d, 0x0d, 0x8b, 0xd6, 0xa3, 0x37, 0x8e, 0xca, 0x62}; - std::vector output_block_4 = { + std::vector kOutputBlock4 = { 0x29, 0x56, 0xe1, 0xc8, 0x69, 0x35, 0x36, 0xb1, 0xbe, 0xe9, 0x9c, 0x73, 0xa3, 0x15, 0x76, 0xb6}; - ASSERT_OK_AND_ASSIGN(std::unique_ptr prng, - OpenSslUniformPseudorandomGenerator::Create(key, iv)); + ASSERT_OK_AND_ASSIGN( + std::unique_ptr prng, + OpenSslUniformPseudorandomGenerator::Create(kTestKey, kTestIv)); - int kNumRandomBytes = 16; + int kBlockSize = 16; ASSERT_OK_AND_ASSIGN(std::vector seq1, - prng->GetPseudorandomBytes(kNumRandomBytes)); + prng->GetPseudorandomBytes(kBlockSize)); ASSERT_OK_AND_ASSIGN(std::vector seq2, - prng->GetPseudorandomBytes(kNumRandomBytes)); + prng->GetPseudorandomBytes(kBlockSize)); ASSERT_OK_AND_ASSIGN(std::vector seq3, - prng->GetPseudorandomBytes(kNumRandomBytes)); + prng->GetPseudorandomBytes(kBlockSize)); ASSERT_OK_AND_ASSIGN(std::vector seq4, - prng->GetPseudorandomBytes(kNumRandomBytes)); + prng->GetPseudorandomBytes(kBlockSize)); - ASSERT_EQ(seq1.size(), kNumRandomBytes); - ASSERT_EQ(seq2.size(), kNumRandomBytes); - ASSERT_EQ(seq3.size(), kNumRandomBytes); - ASSERT_EQ(seq4.size(), kNumRandomBytes); + ASSERT_EQ(seq1.size(), kBlockSize); + ASSERT_EQ(seq2.size(), kBlockSize); + ASSERT_EQ(seq3.size(), kBlockSize); + ASSERT_EQ(seq4.size(), kBlockSize); - ASSERT_EQ(seq1, output_block_1); - ASSERT_EQ(seq2, output_block_2); - ASSERT_EQ(seq3, output_block_3); - ASSERT_EQ(seq4, output_block_4); + ASSERT_EQ(seq1, kOutputBlock1); + ASSERT_EQ(seq2, kOutputBlock2); + ASSERT_EQ(seq3, kOutputBlock3); + ASSERT_EQ(seq4, kOutputBlock4); } } // namespace From 6a86480081a6d4cd5604da17c322a9ce9f3595d1 Mon Sep 17 00:00:00 2001 From: Phi Hung Le Date: Tue, 19 Dec 2023 18:29:22 +0000 Subject: [PATCH 03/10] add secret share generator class. --- src/main/cc/any_sketch/crypto/BUILD.bazel | 12 ++ src/main/cc/any_sketch/crypto/secret_share.cc | 109 ++++++++++++++++ src/main/cc/any_sketch/crypto/secret_share.h | 49 ++++++++ src/main/cc/math/BUILD.bazel | 1 + .../math/open_ssl_uniform_random_generator.cc | 68 ++++++++++ .../math/open_ssl_uniform_random_generator.h | 12 +- .../cc/math/uniform_pseudorandom_generator.h | 4 + src/main/proto/wfa/any_sketch/BUILD.bazel | 11 ++ .../proto/wfa/any_sketch/secret_share.proto | 40 ++++++ src/test/cc/any_sketch/crypto/BUILD.bazel | 16 +++ .../cc/any_sketch/crypto/secret_share_test.cc | 117 ++++++++++++++++++ .../open_ssl_uniform_random_generator_test.cc | 74 +++++++++++ 12 files changed, 511 insertions(+), 2 deletions(-) create mode 100644 src/main/cc/any_sketch/crypto/secret_share.cc create mode 100644 src/main/cc/any_sketch/crypto/secret_share.h create mode 100644 src/main/proto/wfa/any_sketch/secret_share.proto create mode 100644 src/test/cc/any_sketch/crypto/secret_share_test.cc diff --git a/src/main/cc/any_sketch/crypto/BUILD.bazel b/src/main/cc/any_sketch/crypto/BUILD.bazel index d8421e2..15e2bd3 100644 --- a/src/main/cc/any_sketch/crypto/BUILD.bazel +++ b/src/main/cc/any_sketch/crypto/BUILD.bazel @@ -21,6 +21,18 @@ cc_library( ], ) +cc_library( + name = "secret_share", + srcs = [":secret_share.cc"], + hdrs = [":secret_share.h"], + strip_include_prefix = _INCLUDE_PREFIX, + deps = [ + "//src/main/proto/wfa/any_sketch:secret_share_cc_proto", + "//src/main/cc/math:open_ssl_uniform_random_generator", + "@wfa_common_cpp//src/main/cc/common_cpp/macros", + ], +) + cc_library( name = "sketch_encrypter_adapter", srcs = [":sketch_encrypter_adapter.cc"], diff --git a/src/main/cc/any_sketch/crypto/secret_share.cc b/src/main/cc/any_sketch/crypto/secret_share.cc new file mode 100644 index 0000000..ef4f7b0 --- /dev/null +++ b/src/main/cc/any_sketch/crypto/secret_share.cc @@ -0,0 +1,109 @@ +// Copyright 2023 The Cross-Media Measurement Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "any_sketch/crypto/secret_share.h" + +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "common_cpp/macros/macros.h" +#include "math/open_ssl_uniform_random_generator.h" + +namespace wfa::any_sketch::crypto { + +using wfa::any_sketch::crypto::SecretShareGenerator; +using wfa::math::kBytesPerAes256Iv; +using wfa::math::kBytesPerAes256Key; +using wfa::math::OpenSslUniformPseudorandomGenerator; +using wfa::math::UniformPseudorandomGenerator; + +uint32_t SubMod(uint32_t x, uint32_t y, uint32_t modulus) { + if (x >= y) { + return x - y; + } else { + return x + (modulus - y); + } +} + +class SecretShareGeneratorImpl : public SecretShareGenerator { + public: + SecretShareGeneratorImpl() = default; + ~SecretShareGeneratorImpl() override = default; + + SecretShareGeneratorImpl(SecretShareGeneratorImpl&& other) = delete; + SecretShareGeneratorImpl& operator=(SecretShareGeneratorImpl&& other) = + delete; + SecretShareGeneratorImpl(const SecretShareGeneratorImpl&) = delete; + SecretShareGeneratorImpl& operator=(const SecretShareGeneratorImpl&) = delete; + + absl::StatusOr GenerateSecretShares( + const SecretShareParameter& secret_share_parameter, + const std::vector& input) override; +}; + +absl::StatusOr SecretShareGeneratorImpl::GenerateSecretShares( + const SecretShareParameter& secret_share_parameter, + const std::vector& input) { + if (input.size() == 0) { + return absl::InvalidArgumentError("Input must be a non-empty vector."); + } + + if (secret_share_parameter.modulus() <= 1) { + return absl::InvalidArgumentError("The modulus must be greater than 1."); + } + + // Verify OpenSSL random generator seed has been seeded with enough entropy. + if (RAND_status() != 1) { + return absl::InternalError( + "OpenSSL random generator has been seeded with enough entropy."); + } + + // Sample random seed as the first share. + std::vector key(kBytesPerAes256Key); + std::vector iv(kBytesPerAes256Iv); + + if (RAND_bytes(key.data(), kBytesPerAes256Key) != 1) { + return absl::InternalError("Failed to sample the AES 256 key."); + } + + if (RAND_bytes(iv.data(), kBytesPerAes256Iv) != 1) { + return absl::InternalError("Failed to sample the AES 256 IV."); + } + + // Expanse the seed to get a random string. + ASSIGN_OR_RETURN(std::unique_ptr prng, + OpenSslUniformPseudorandomGenerator::Create(key, iv)); + + ASSIGN_OR_RETURN(std::vector share_vector, + prng->GetUniformRandomRange( + input.size(), secret_share_parameter.modulus())); + for (int i = 0; i < input.size(); i++) { + share_vector[i] = + SubMod(input[i], share_vector[i], secret_share_parameter.modulus()); + } + SecretShare secret_share; + secret_share.mutable_share_vector()->Add(share_vector.begin(), + share_vector.end()); + std::string key_str(key.begin(), key.end()); + std::string iv_str(iv.begin(), iv.end()); + secret_share.mutable_share_seed()->set_key(key_str); + secret_share.mutable_share_seed()->set_iv(iv_str); + + return secret_share; +} + +std::unique_ptr CreateSecretShareGenerator() { + return absl::WrapUnique(new SecretShareGeneratorImpl()); +} + +} // namespace wfa::any_sketch::crypto \ No newline at end of file diff --git a/src/main/cc/any_sketch/crypto/secret_share.h b/src/main/cc/any_sketch/crypto/secret_share.h new file mode 100644 index 0000000..7c4b1ac --- /dev/null +++ b/src/main/cc/any_sketch/crypto/secret_share.h @@ -0,0 +1,49 @@ +// Copyright 2023 The Cross-Media Measurement Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_MAIN_CC_ANY_SKETCH_CRYPTO_SECRET_SHARE_H_ +#define SRC_MAIN_CC_ANY_SKETCH_CRYPTO_SECRET_SHARE_H_ + +#include + +#include "absl/status/statusor.h" +#include "wfa/any_sketch/secret_share.pb.h" + +using wfa::any_sketch::SecretShare; +using wfa::any_sketch::SecretShareParameter; + +namespace wfa::any_sketch::crypto { + +class SecretShareGenerator { + public: + virtual ~SecretShareGenerator(){}; + + SecretShareGenerator(SecretShareGenerator&& other) = delete; + SecretShareGenerator& operator=(SecretShareGenerator&& other) = delete; + SecretShareGenerator(const SecretShareGenerator&) = delete; + SecretShareGenerator& operator=(const SecretShareGenerator&) = delete; + + virtual absl::StatusOr GenerateSecretShares( + const SecretShareParameter& secret_share_parameter, + const std::vector& input) = 0; + + protected: + SecretShareGenerator() = default; +}; + +std::unique_ptr CreateSecretShareGenerator(); + +} // namespace wfa::any_sketch::crypto + +#endif // SRC_MAIN_CC_ANY_SKETCH_CRYPTO_SECRET_SHARE_H_ diff --git a/src/main/cc/math/BUILD.bazel b/src/main/cc/math/BUILD.bazel index 81ab935..5c5ff99 100644 --- a/src/main/cc/math/BUILD.bazel +++ b/src/main/cc/math/BUILD.bazel @@ -38,6 +38,7 @@ cc_library( "@boringssl//:ssl", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", + "@wfa_common_cpp//src/main/cc/common_cpp/macros", ], ) diff --git a/src/main/cc/math/open_ssl_uniform_random_generator.cc b/src/main/cc/math/open_ssl_uniform_random_generator.cc index 3fbd15e..98dadca 100644 --- a/src/main/cc/math/open_ssl_uniform_random_generator.cc +++ b/src/main/cc/math/open_ssl_uniform_random_generator.cc @@ -16,6 +16,7 @@ #include +#include "common_cpp/macros/macros.h" #include "openssl/rand.h" namespace wfa::math { @@ -86,4 +87,71 @@ OpenSslUniformPseudorandomGenerator::GetPseudorandomBytes(uint64_t size) { return ret; } +absl::StatusOr> +OpenSslUniformPseudorandomGenerator::GetUniformRandomRange(uint64_t size, + uint32_t modulus) { + if (size == 0) { + return absl::InvalidArgumentError( + "Number of pseudorandom elements must be a positive value."); + } + + if (modulus <= 1) { + return absl::InvalidArgumentError("The modulus must be greater than 1."); + } + + // Compute the bit length of the modulus. + int bit_length = std::ceil(std::log2(modulus)); + // The number of bytes needed per element. + int bytes_per_value = (bit_length + 7) / 8; + // The mask to extract the last bit_length bits. + uint32_t mask = (1 << bit_length) - 1; + + // Compute the failure probability, which happens when the sampled value is + // greater than or equal to modulus. As 2^{bit_length - 1} < modulus <= + // 2^{bit_length}, the failure probability is guaranteed to be less than 0.5. + double failure_rate = + (double)((1 << bit_length) - modulus) / (double)(1 << bit_length); + + // Compute the expected number of samples needed. + uint64_t sample_size = + (uint64_t)(size + 2 * failure_rate * size / (1 - failure_rate)); + std::vector arr(sample_size * bytes_per_value, 0); + std::vector ret; + ret.reserve(size); + int length; + if (EVP_EncryptUpdate(ctx_, arr.data(), &length, arr.data(), arr.size()) != + 1) { + return absl::InternalError( + "Error updating the uniform pseudorandom generator context."); + } + if (EVP_EncryptFinal_ex(ctx_, arr.data() + length, &length) != 1) { + return absl::InternalError("Error finalizing the generating random bytes."); + } + + for (uint64_t i = 0; i < sample_size; i++) { + if (ret.size() >= size) { + break; + } + uint32_t temp = 0; + for (int j = 0; j < bytes_per_value; j++) { + temp = (temp << 8) + arr[i * bytes_per_value + j]; + } + temp &= mask; + + // Accept the value if it is less than modulus. + if (temp < modulus) { + ret.push_back(temp); + } + } + + // In case the number of rejections is higher than expected, sample more + // random values in the range and append to the current result. + if (ret.size() < size) { + ASSIGN_OR_RETURN(std::vector appendix, + GetUniformRandomRange(size - ret.size(), modulus)); + ret.insert(ret.end(), appendix.begin(), appendix.end()); + } + return ret; +} + } // namespace wfa::math diff --git a/src/main/cc/math/open_ssl_uniform_random_generator.h b/src/main/cc/math/open_ssl_uniform_random_generator.h index c5eb91f..293a36a 100644 --- a/src/main/cc/math/open_ssl_uniform_random_generator.h +++ b/src/main/cc/math/open_ssl_uniform_random_generator.h @@ -82,11 +82,19 @@ class OpenSslUniformPseudorandomGenerator const std::vector& iv); // Destructor. - ~OpenSslUniformPseudorandomGenerator() { EVP_CIPHER_CTX_free(ctx_); } + ~OpenSslUniformPseudorandomGenerator() override { EVP_CIPHER_CTX_free(ctx_); } // Generate a vector of pseudorandom bytes with the given size. absl::StatusOr> GetPseudorandomBytes( - uint64_t size); + uint64_t size) override; + + // Generate a vector of pseudorandom values in the range [0, modulus). + // First, we sample n random values in [0, 2^k) where k is the smallest value + // such that modulus <= 2^k. Only values in [0, modulus) are accepted. n is + // chosen such that the expected number of accepted values meets the given + // `size`. + absl::StatusOr> GetUniformRandomRange( + uint64_t size, uint32_t modulus) override; private: explicit OpenSslUniformPseudorandomGenerator(EVP_CIPHER_CTX* ctx) diff --git a/src/main/cc/math/uniform_pseudorandom_generator.h b/src/main/cc/math/uniform_pseudorandom_generator.h index 17dd0cb..6d9427d 100644 --- a/src/main/cc/math/uniform_pseudorandom_generator.h +++ b/src/main/cc/math/uniform_pseudorandom_generator.h @@ -43,6 +43,10 @@ class UniformPseudorandomGenerator { virtual absl::StatusOr> GetPseudorandomBytes( uint64_t size) = 0; + // Generate a vector of pseudorandom values in the range [0, modulus). + virtual absl::StatusOr> GetUniformRandomRange( + uint64_t size, uint32_t modulus) = 0; + protected: UniformPseudorandomGenerator() = default; }; diff --git a/src/main/proto/wfa/any_sketch/BUILD.bazel b/src/main/proto/wfa/any_sketch/BUILD.bazel index 25aa93f..77ff531 100644 --- a/src/main/proto/wfa/any_sketch/BUILD.bazel +++ b/src/main/proto/wfa/any_sketch/BUILD.bazel @@ -26,3 +26,14 @@ cc_proto_library( name = "differential_privacy_cc_proto", deps = [":differential_privacy_proto"], ) + +proto_library( + name = "secret_share_proto", + srcs = ["secret_share.proto"], + strip_import_prefix = IMPORT_PREFIX, +) + +cc_proto_library( + name = "secret_share_cc_proto", + deps = [":secret_share_proto"], +) \ No newline at end of file diff --git a/src/main/proto/wfa/any_sketch/secret_share.proto b/src/main/proto/wfa/any_sketch/secret_share.proto new file mode 100644 index 0000000..a400bdb --- /dev/null +++ b/src/main/proto/wfa/any_sketch/secret_share.proto @@ -0,0 +1,40 @@ +// Copyright 2023 The Cross-Media Measurement Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Protobuffer for the generalized enriched cardinality sketch. +// SketchConfig is configuration of the sketch. +// Sketch is the sketch itself. + +syntax = "proto3"; + +package wfa.any_sketch; + +option java_package = "org.wfanet.anysketch"; +option java_multiple_files = true; +option java_outer_classname = "SecretShareProto"; + +message SecretShareParameter { + uint32 modulus = 1; +} + +message SecretShare { + // Seed to initialize the AES 256 counter mode. + message ShareSeed { + bytes key = 1; + bytes iv = 2; + } + + ShareSeed share_seed = 1; + repeated uint32 share_vector = 2; +} \ No newline at end of file diff --git a/src/test/cc/any_sketch/crypto/BUILD.bazel b/src/test/cc/any_sketch/crypto/BUILD.bazel index 5544abc..37fee19 100644 --- a/src/test/cc/any_sketch/crypto/BUILD.bazel +++ b/src/test/cc/any_sketch/crypto/BUILD.bazel @@ -28,3 +28,19 @@ cc_test( "@wfa_common_cpp//src/main/cc/common_cpp/testing:status", ], ) + +cc_test( + name = "secret_share_test", + size = "small", + srcs = [ + ":secret_share_test.cc", + ], + deps = [ + "//src/main/cc/any_sketch/crypto:secret_share", + "//src/main/proto/wfa/any_sketch:secret_share_cc_proto", + "//src/main/cc/math:open_ssl_uniform_random_generator", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + "@wfa_common_cpp//src/main/cc/common_cpp/testing:status", + ], +) \ No newline at end of file diff --git a/src/test/cc/any_sketch/crypto/secret_share_test.cc b/src/test/cc/any_sketch/crypto/secret_share_test.cc new file mode 100644 index 0000000..137ef9e --- /dev/null +++ b/src/test/cc/any_sketch/crypto/secret_share_test.cc @@ -0,0 +1,117 @@ +// Copyright 2023 The Cross-Media Measurement Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "any_sketch/crypto/secret_share.h" + +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "common_cpp/testing/status_macros.h" +#include "common_cpp/testing/status_matchers.h" +#include "gtest/gtest.h" +#include "math/open_ssl_uniform_random_generator.h" + +namespace wfa::any_sketch::crypto { +namespace { + +using math::OpenSslUniformPseudorandomGenerator; +using math::UniformPseudorandomGenerator; + +TEST(AdditiveSecretSharing, EmptyInputVectorFails) { + std::vector input(0); + std::unique_ptr secret_share_generator = + CreateSecretShareGenerator(); + SecretShareParameter param; + param.set_modulus(128); + auto ret = secret_share_generator->GenerateSecretShares(param, input); + EXPECT_THAT(ret.status(), StatusIs(absl::StatusCode::kInvalidArgument, + "Input must be a non-empty vector.")); +} + +TEST(AdditiveSecretSharing, InvalidModulusFails) { + std::vector input = {0, 1, 2}; + std::unique_ptr secret_share_generator = + CreateSecretShareGenerator(); + SecretShareParameter param; + param.set_modulus(1); + auto ret = secret_share_generator->GenerateSecretShares(param, input); + EXPECT_THAT(ret.status(), StatusIs(absl::StatusCode::kInvalidArgument, + "The modulus must be greater than 1.")); +} + +TEST(AdditiveSecretSharing, SecretShareOverRingZ2kElementsSucceeds) { + std::vector input = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + std::unique_ptr secret_share_generator = + CreateSecretShareGenerator(); + SecretShareParameter param; + param.set_modulus(128); + ASSERT_OK_AND_ASSIGN( + SecretShare secret_share, + secret_share_generator->GenerateSecretShares(param, input)); + + std::string key = secret_share.share_seed().key(); + std::string iv = secret_share.share_seed().iv(); + + std::vector key_vec, iv_vec; + key_vec.insert(key_vec.end(), key.begin(), key.end()); + iv_vec.insert(iv_vec.end(), iv.begin(), iv.end()); + + ASSERT_OK_AND_ASSIGN( + std::unique_ptr prng, + OpenSslUniformPseudorandomGenerator::Create(key_vec, iv_vec)); + + ASSERT_OK_AND_ASSIGN( + std::vector share_vector_from_seed, + prng->GetUniformRandomRange(input.size(), param.modulus())); + + for (int i = 0; i < input.size(); i++) { + ASSERT_EQ(input[i], + (share_vector_from_seed[i] + secret_share.share_vector(i)) % + param.modulus()); + } +} + +TEST(AdditiveSecretSharing, SecretShareOverPrimeFieldElementsSucceeds) { + std::vector input = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + std::unique_ptr secret_share_generator = + CreateSecretShareGenerator(); + SecretShareParameter param; + param.set_modulus(127); + ASSERT_OK_AND_ASSIGN( + SecretShare secret_share, + secret_share_generator->GenerateSecretShares(param, input)); + + std::string key = secret_share.share_seed().key(); + std::string iv = secret_share.share_seed().iv(); + + std::vector key_vec, iv_vec; + key_vec.insert(key_vec.end(), key.begin(), key.end()); + iv_vec.insert(iv_vec.end(), iv.begin(), iv.end()); + + ASSERT_OK_AND_ASSIGN( + std::unique_ptr prng, + OpenSslUniformPseudorandomGenerator::Create(key_vec, iv_vec)); + + ASSERT_OK_AND_ASSIGN( + std::vector share_vector_from_seed, + prng->GetUniformRandomRange(input.size(), param.modulus())); + + for (int i = 0; i < input.size(); i++) { + ASSERT_EQ(input[i], + (share_vector_from_seed[i] + secret_share.share_vector(i)) % + param.modulus()); + } +} + +} // namespace +} // namespace wfa::any_sketch::crypto \ No newline at end of file diff --git a/src/test/cc/math/open_ssl_uniform_random_generator_test.cc b/src/test/cc/math/open_ssl_uniform_random_generator_test.cc index af8ab2f..816b494 100644 --- a/src/test/cc/math/open_ssl_uniform_random_generator_test.cc +++ b/src/test/cc/math/open_ssl_uniform_random_generator_test.cc @@ -250,5 +250,79 @@ TEST(OpenSslUniformPseudorandomGenerator, ASSERT_EQ(seq4, kOutputBlock4); } +TEST(OpenSslUniformPseudorandomGenerator, + GeneratingNonPositiveNumberOfRandomElementsFails) { + std::vector key(kBytesPerAes256Key); + std::vector iv(kBytesPerAes256Iv); + RAND_bytes(key.data(), key.size()); + RAND_bytes(iv.data(), iv.size()); + ASSERT_OK_AND_ASSIGN(std::unique_ptr prng, + OpenSslUniformPseudorandomGenerator::Create(key, iv)); + + uint32_t kModulus = 128; + uint64_t kNumRandomElements = 0; + auto seq = prng->GetUniformRandomRange(kNumRandomElements, kModulus); + EXPECT_THAT( + seq.status(), + StatusIs(absl::StatusCode::kInvalidArgument, + "Number of pseudorandom elements must be a positive value.")); +} + +TEST(OpenSslUniformPseudorandomGenerator, + GeneratingUniformlyRandomWithInvalidModulusFails) { + std::vector key(kBytesPerAes256Key); + std::vector iv(kBytesPerAes256Iv); + RAND_bytes(key.data(), key.size()); + RAND_bytes(iv.data(), iv.size()); + ASSERT_OK_AND_ASSIGN(std::unique_ptr prng, + OpenSslUniformPseudorandomGenerator::Create(key, iv)); + + uint32_t kModulus = 1; + uint64_t kNumRandomElements = 1; + auto seq = prng->GetUniformRandomRange(kNumRandomElements, kModulus); + EXPECT_THAT(seq.status(), StatusIs(absl::StatusCode::kInvalidArgument, + "The modulus must be greater than 1.")); +} + +TEST(OpenSslUniformPseudorandomGenerator, + SampleUniformlyRandomOverRingZ2kElementsSucceeds) { + std::vector key(kBytesPerAes256Key); + std::vector iv(kBytesPerAes256Iv); + RAND_bytes(key.data(), key.size()); + RAND_bytes(iv.data(), iv.size()); + + ASSERT_OK_AND_ASSIGN(std::unique_ptr prng, + OpenSslUniformPseudorandomGenerator::Create(key, iv)); + uint32_t kModulus = 128; + uint64_t kNumRandomElements = 111; + ASSERT_OK_AND_ASSIGN( + std::vector seq, + prng->GetUniformRandomRange(kNumRandomElements, kModulus)); + ASSERT_EQ(seq.size(), kNumRandomElements); + for (int i = 0; i < kNumRandomElements; i++) { + ASSERT_LT(seq[i], kModulus); + } +} + +TEST(OpenSslUniformPseudorandomGenerator, + SampleUniformlyRandomOverPrimeFieldElementsSucceeds) { + std::vector key(kBytesPerAes256Key); + std::vector iv(kBytesPerAes256Iv); + RAND_bytes(key.data(), key.size()); + RAND_bytes(iv.data(), iv.size()); + + ASSERT_OK_AND_ASSIGN(std::unique_ptr prng, + OpenSslUniformPseudorandomGenerator::Create(key, iv)); + uint32_t kModulus = 127; + uint64_t kNumRandomElements = 111; + ASSERT_OK_AND_ASSIGN( + std::vector seq, + prng->GetUniformRandomRange(kNumRandomElements, kModulus)); + ASSERT_EQ(seq.size(), kNumRandomElements); + for (int i = 0; i < kNumRandomElements; i++) { + ASSERT_LT(seq[i], kModulus); + } +} + } // namespace } // namespace wfa::math From 8625e7f6c3ce412fb7cc50d3113790d1d28e1f61 Mon Sep 17 00:00:00 2001 From: Phi Hung Le Date: Tue, 19 Dec 2023 23:30:08 +0000 Subject: [PATCH 04/10] Adding comments. --- src/main/cc/any_sketch/crypto/BUILD.bazel | 8 +- ...ret_share.cc => secret_share_generator.cc} | 58 +++++++-------- ...ecret_share.h => secret_share_generator.h} | 27 ++----- .../math/open_ssl_uniform_random_generator.cc | 74 +++++++++---------- .../math/open_ssl_uniform_random_generator.h | 14 ++-- .../cc/math/uniform_pseudorandom_generator.h | 8 +- src/main/proto/wfa/any_sketch/BUILD.bazel | 2 +- .../proto/wfa/any_sketch/secret_share.proto | 2 +- src/test/cc/any_sketch/crypto/BUILD.bazel | 10 +-- ...test.cc => secret_share_generator_test.cc} | 40 +++++----- .../open_ssl_uniform_random_generator_test.cc | 46 ++++++------ 11 files changed, 132 insertions(+), 157 deletions(-) rename src/main/cc/any_sketch/crypto/{secret_share.cc => secret_share_generator.cc} (64%) rename src/main/cc/any_sketch/crypto/{secret_share.h => secret_share_generator.h} (52%) rename src/test/cc/any_sketch/crypto/{secret_share_test.cc => secret_share_generator_test.cc} (77%) diff --git a/src/main/cc/any_sketch/crypto/BUILD.bazel b/src/main/cc/any_sketch/crypto/BUILD.bazel index 15e2bd3..7786bb8 100644 --- a/src/main/cc/any_sketch/crypto/BUILD.bazel +++ b/src/main/cc/any_sketch/crypto/BUILD.bazel @@ -22,13 +22,13 @@ cc_library( ) cc_library( - name = "secret_share", - srcs = [":secret_share.cc"], - hdrs = [":secret_share.h"], + name = "secret_share_generator", + srcs = [":secret_share_generator.cc"], + hdrs = [":secret_share_generator.h"], strip_include_prefix = _INCLUDE_PREFIX, deps = [ - "//src/main/proto/wfa/any_sketch:secret_share_cc_proto", "//src/main/cc/math:open_ssl_uniform_random_generator", + "//src/main/proto/wfa/any_sketch:secret_share_cc_proto", "@wfa_common_cpp//src/main/cc/common_cpp/macros", ], ) diff --git a/src/main/cc/any_sketch/crypto/secret_share.cc b/src/main/cc/any_sketch/crypto/secret_share_generator.cc similarity index 64% rename from src/main/cc/any_sketch/crypto/secret_share.cc rename to src/main/cc/any_sketch/crypto/secret_share_generator.cc index ef4f7b0..2451117 100644 --- a/src/main/cc/any_sketch/crypto/secret_share.cc +++ b/src/main/cc/any_sketch/crypto/secret_share_generator.cc @@ -12,7 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "any_sketch/crypto/secret_share.h" +#include "any_sketch/crypto/secret_share_generator.h" + +#include #include "absl/status/status.h" #include "absl/status/statusor.h" @@ -21,13 +23,20 @@ namespace wfa::any_sketch::crypto { -using wfa::any_sketch::crypto::SecretShareGenerator; using wfa::math::kBytesPerAes256Iv; using wfa::math::kBytesPerAes256Key; using wfa::math::OpenSslUniformPseudorandomGenerator; using wfa::math::UniformPseudorandomGenerator; -uint32_t SubMod(uint32_t x, uint32_t y, uint32_t modulus) { +namespace { + +// This function computes (x + y) mod modulus and returns the result. +// The input values x, y, and the output are all in [0, modulus) +absl::StatusOr SubMod(uint32_t x, uint32_t y, uint32_t modulus) { + if (x >= modulus || y >= modulus) { + return absl::InvalidArgumentError(absl::Substitute( + "Inputs must be less than the modulus, which is $0.", modulus)); + } if (x >= y) { return x - y; } else { @@ -35,25 +44,11 @@ uint32_t SubMod(uint32_t x, uint32_t y, uint32_t modulus) { } } -class SecretShareGeneratorImpl : public SecretShareGenerator { - public: - SecretShareGeneratorImpl() = default; - ~SecretShareGeneratorImpl() override = default; - - SecretShareGeneratorImpl(SecretShareGeneratorImpl&& other) = delete; - SecretShareGeneratorImpl& operator=(SecretShareGeneratorImpl&& other) = - delete; - SecretShareGeneratorImpl(const SecretShareGeneratorImpl&) = delete; - SecretShareGeneratorImpl& operator=(const SecretShareGeneratorImpl&) = delete; +} // namespace - absl::StatusOr GenerateSecretShares( - const SecretShareParameter& secret_share_parameter, - const std::vector& input) override; -}; - -absl::StatusOr SecretShareGeneratorImpl::GenerateSecretShares( +absl::StatusOr GenerateSecretShares( const SecretShareParameter& secret_share_parameter, - const std::vector& input) { + const absl::Span input) { if (input.size() == 0) { return absl::InvalidArgumentError("Input must be a non-empty vector."); } @@ -84,16 +79,21 @@ absl::StatusOr SecretShareGeneratorImpl::GenerateSecretShares( ASSIGN_OR_RETURN(std::unique_ptr prng, OpenSslUniformPseudorandomGenerator::Create(key, iv)); - ASSIGN_OR_RETURN(std::vector share_vector, - prng->GetUniformRandomRange( + // share_vector_1 holds the random share generated from the random seed. + ASSIGN_OR_RETURN(std::vector share_vector_1, + prng->GenerateUniformRandomRange( input.size(), secret_share_parameter.modulus())); + // share_vector_2 is the share computed from the input and share_vector_1. + std::vector share_vector_2(input.size()); for (int i = 0; i < input.size(); i++) { - share_vector[i] = - SubMod(input[i], share_vector[i], secret_share_parameter.modulus()); + // share_vector_2[i] = (input[i] - share_vector_1[i]) mod modulus. + ASSIGN_OR_RETURN( + share_vector_2[i], + SubMod(input[i], share_vector_1[i], secret_share_parameter.modulus())); } SecretShare secret_share; - secret_share.mutable_share_vector()->Add(share_vector.begin(), - share_vector.end()); + secret_share.mutable_share_vector()->Add(share_vector_2.begin(), + share_vector_2.end()); std::string key_str(key.begin(), key.end()); std::string iv_str(iv.begin(), iv.end()); secret_share.mutable_share_seed()->set_key(key_str); @@ -102,8 +102,4 @@ absl::StatusOr SecretShareGeneratorImpl::GenerateSecretShares( return secret_share; } -std::unique_ptr CreateSecretShareGenerator() { - return absl::WrapUnique(new SecretShareGeneratorImpl()); -} - -} // namespace wfa::any_sketch::crypto \ No newline at end of file +} // namespace wfa::any_sketch::crypto diff --git a/src/main/cc/any_sketch/crypto/secret_share.h b/src/main/cc/any_sketch/crypto/secret_share_generator.h similarity index 52% rename from src/main/cc/any_sketch/crypto/secret_share.h rename to src/main/cc/any_sketch/crypto/secret_share_generator.h index 7c4b1ac..d0a4377 100644 --- a/src/main/cc/any_sketch/crypto/secret_share.h +++ b/src/main/cc/any_sketch/crypto/secret_share_generator.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef SRC_MAIN_CC_ANY_SKETCH_CRYPTO_SECRET_SHARE_H_ -#define SRC_MAIN_CC_ANY_SKETCH_CRYPTO_SECRET_SHARE_H_ +#ifndef SRC_MAIN_CC_ANY_SKETCH_CRYPTO_SECRET_SHARE_GENERATOR_H_ +#define SRC_MAIN_CC_ANY_SKETCH_CRYPTO_SECRET_SHARE_GENERATOR_H_ #include @@ -25,25 +25,10 @@ using wfa::any_sketch::SecretShareParameter; namespace wfa::any_sketch::crypto { -class SecretShareGenerator { - public: - virtual ~SecretShareGenerator(){}; - - SecretShareGenerator(SecretShareGenerator&& other) = delete; - SecretShareGenerator& operator=(SecretShareGenerator&& other) = delete; - SecretShareGenerator(const SecretShareGenerator&) = delete; - SecretShareGenerator& operator=(const SecretShareGenerator&) = delete; - - virtual absl::StatusOr GenerateSecretShares( - const SecretShareParameter& secret_share_parameter, - const std::vector& input) = 0; - - protected: - SecretShareGenerator() = default; -}; - -std::unique_ptr CreateSecretShareGenerator(); +absl::StatusOr GenerateSecretShares( + const SecretShareParameter& secret_share_parameter, + const absl::Span input); } // namespace wfa::any_sketch::crypto -#endif // SRC_MAIN_CC_ANY_SKETCH_CRYPTO_SECRET_SHARE_H_ +#endif // SRC_MAIN_CC_ANY_SKETCH_CRYPTO_SECRET_SHARE_GENERATOR_H_ diff --git a/src/main/cc/math/open_ssl_uniform_random_generator.cc b/src/main/cc/math/open_ssl_uniform_random_generator.cc index 98dadca..645dc73 100644 --- a/src/main/cc/math/open_ssl_uniform_random_generator.cc +++ b/src/main/cc/math/open_ssl_uniform_random_generator.cc @@ -14,6 +14,7 @@ #include "math/open_ssl_uniform_random_generator.h" +#include #include #include "common_cpp/macros/macros.h" @@ -69,7 +70,7 @@ OpenSslUniformPseudorandomGenerator::Create( } absl::StatusOr> -OpenSslUniformPseudorandomGenerator::GetPseudorandomBytes(uint64_t size) { +OpenSslUniformPseudorandomGenerator::GeneratePseudorandomBytes(uint64_t size) { if (size == 0) { return absl::InvalidArgumentError( "Number of pseudorandom bytes must be a positive value."); @@ -87,9 +88,11 @@ OpenSslUniformPseudorandomGenerator::GetPseudorandomBytes(uint64_t size) { return ret; } +// Rejection sampling is used to generate uniformly random values in the range +// [0, modulus). absl::StatusOr> -OpenSslUniformPseudorandomGenerator::GetUniformRandomRange(uint64_t size, - uint32_t modulus) { +OpenSslUniformPseudorandomGenerator::GenerateUniformRandomRange( + uint64_t size, uint32_t modulus) { if (size == 0) { return absl::InvalidArgumentError( "Number of pseudorandom elements must be a positive value."); @@ -109,48 +112,41 @@ OpenSslUniformPseudorandomGenerator::GetUniformRandomRange(uint64_t size, // Compute the failure probability, which happens when the sampled value is // greater than or equal to modulus. As 2^{bit_length - 1} < modulus <= // 2^{bit_length}, the failure probability is guaranteed to be less than 0.5. - double failure_rate = - (double)((1 << bit_length) - modulus) / (double)(1 << bit_length); + double failure_rate = static_cast((1 << bit_length) - modulus) / + static_cast(1 << bit_length); - // Compute the expected number of samples needed. - uint64_t sample_size = - (uint64_t)(size + 2 * failure_rate * size / (1 - failure_rate)); - std::vector arr(sample_size * bytes_per_value, 0); std::vector ret; ret.reserve(size); - int length; - if (EVP_EncryptUpdate(ctx_, arr.data(), &length, arr.data(), arr.size()) != - 1) { - return absl::InternalError( - "Error updating the uniform pseudorandom generator context."); - } - if (EVP_EncryptFinal_ex(ctx_, arr.data() + length, &length) != 1) { - return absl::InternalError("Error finalizing the generating random bytes."); - } - - for (uint64_t i = 0; i < sample_size; i++) { - if (ret.size() >= size) { - break; - } - uint32_t temp = 0; - for (int j = 0; j < bytes_per_value; j++) { - temp = (temp << 8) + arr[i * bytes_per_value + j]; - } - temp &= mask; - // Accept the value if it is less than modulus. - if (temp < modulus) { - ret.push_back(temp); + while (ret.size() < size) { + uint64_t current_size = size - ret.size(); + // To get current_size `good` elements, it is expected to sample + // 1 + current_size*(1 + failure_rate/(1-failure_rate)) elements in + // [0, 2^{bit_length}). + uint64_t sample_size = + (uint64_t)(current_size + 1 + + failure_rate * current_size / (1 - failure_rate)); + + ASSIGN_OR_RETURN(std::vector arr, + GeneratePseudorandomBytes(sample_size * bytes_per_value)); + + // Rejection sampling step. + for (uint64_t i = 0; i < sample_size; i++) { + if (ret.size() >= size) { + break; + } + uint32_t temp = 0; + for (int j = 0; j < bytes_per_value; j++) { + temp = (temp << 8) + arr[i * bytes_per_value + j]; + } + temp &= mask; + + // Accept the value if it is less than modulus. + if (temp < modulus) { + ret.push_back(temp); + } } } - - // In case the number of rejections is higher than expected, sample more - // random values in the range and append to the current result. - if (ret.size() < size) { - ASSIGN_OR_RETURN(std::vector appendix, - GetUniformRandomRange(size - ret.size(), modulus)); - ret.insert(ret.end(), appendix.begin(), appendix.end()); - } return ret; } diff --git a/src/main/cc/math/open_ssl_uniform_random_generator.h b/src/main/cc/math/open_ssl_uniform_random_generator.h index 293a36a..eae407c 100644 --- a/src/main/cc/math/open_ssl_uniform_random_generator.h +++ b/src/main/cc/math/open_ssl_uniform_random_generator.h @@ -74,7 +74,7 @@ class OpenSslUniformRandomGenerator { class OpenSslUniformPseudorandomGenerator : public UniformPseudorandomGenerator { public: - // Create a uniform pseudorandom generator from a key and an IV. + // Creates a uniform pseudorandom generator from a key and an IV. // The key and IV needs to have the length of kBytesPerAes256Key and // kBytesPerAes256Iv respectively. static absl::StatusOr> Create( @@ -84,16 +84,12 @@ class OpenSslUniformPseudorandomGenerator // Destructor. ~OpenSslUniformPseudorandomGenerator() override { EVP_CIPHER_CTX_free(ctx_); } - // Generate a vector of pseudorandom bytes with the given size. - absl::StatusOr> GetPseudorandomBytes( + // Generates a vector of pseudorandom bytes with the given size. + absl::StatusOr> GeneratePseudorandomBytes( uint64_t size) override; - // Generate a vector of pseudorandom values in the range [0, modulus). - // First, we sample n random values in [0, 2^k) where k is the smallest value - // such that modulus <= 2^k. Only values in [0, modulus) are accepted. n is - // chosen such that the expected number of accepted values meets the given - // `size`. - absl::StatusOr> GetUniformRandomRange( + // Generates a vector of `size` pseudorandom values in the range [0, modulus). + absl::StatusOr> GenerateUniformRandomRange( uint64_t size, uint32_t modulus) override; private: diff --git a/src/main/cc/math/uniform_pseudorandom_generator.h b/src/main/cc/math/uniform_pseudorandom_generator.h index 6d9427d..3c1520b 100644 --- a/src/main/cc/math/uniform_pseudorandom_generator.h +++ b/src/main/cc/math/uniform_pseudorandom_generator.h @@ -39,12 +39,12 @@ class UniformPseudorandomGenerator { UniformPseudorandomGenerator(UniformPseudorandomGenerator&& other) = delete; virtual ~UniformPseudorandomGenerator() = default; - // Generate a vector of pseudorandom bytes with the given size. - virtual absl::StatusOr> GetPseudorandomBytes( + // Generates a vector of pseudorandom bytes with the given size. + virtual absl::StatusOr> GeneratePseudorandomBytes( uint64_t size) = 0; - // Generate a vector of pseudorandom values in the range [0, modulus). - virtual absl::StatusOr> GetUniformRandomRange( + // Generates a vector of pseudorandom values in the range [0, modulus). + virtual absl::StatusOr> GenerateUniformRandomRange( uint64_t size, uint32_t modulus) = 0; protected: diff --git a/src/main/proto/wfa/any_sketch/BUILD.bazel b/src/main/proto/wfa/any_sketch/BUILD.bazel index 77ff531..6d973d7 100644 --- a/src/main/proto/wfa/any_sketch/BUILD.bazel +++ b/src/main/proto/wfa/any_sketch/BUILD.bazel @@ -36,4 +36,4 @@ proto_library( cc_proto_library( name = "secret_share_cc_proto", deps = [":secret_share_proto"], -) \ No newline at end of file +) diff --git a/src/main/proto/wfa/any_sketch/secret_share.proto b/src/main/proto/wfa/any_sketch/secret_share.proto index a400bdb..bc9b0e5 100644 --- a/src/main/proto/wfa/any_sketch/secret_share.proto +++ b/src/main/proto/wfa/any_sketch/secret_share.proto @@ -37,4 +37,4 @@ message SecretShare { ShareSeed share_seed = 1; repeated uint32 share_vector = 2; -} \ No newline at end of file +} diff --git a/src/test/cc/any_sketch/crypto/BUILD.bazel b/src/test/cc/any_sketch/crypto/BUILD.bazel index 37fee19..8ea8514 100644 --- a/src/test/cc/any_sketch/crypto/BUILD.bazel +++ b/src/test/cc/any_sketch/crypto/BUILD.bazel @@ -30,17 +30,17 @@ cc_test( ) cc_test( - name = "secret_share_test", + name = "secret_share_generator_test", size = "small", srcs = [ - ":secret_share_test.cc", + ":secret_share_generator_test.cc", ], deps = [ - "//src/main/cc/any_sketch/crypto:secret_share", - "//src/main/proto/wfa/any_sketch:secret_share_cc_proto", + "//src/main/cc/any_sketch/crypto:secret_share_generator", "//src/main/cc/math:open_ssl_uniform_random_generator", + "//src/main/proto/wfa/any_sketch:secret_share_cc_proto", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", "@wfa_common_cpp//src/main/cc/common_cpp/testing:status", ], -) \ No newline at end of file +) diff --git a/src/test/cc/any_sketch/crypto/secret_share_test.cc b/src/test/cc/any_sketch/crypto/secret_share_generator_test.cc similarity index 77% rename from src/test/cc/any_sketch/crypto/secret_share_test.cc rename to src/test/cc/any_sketch/crypto/secret_share_generator_test.cc index 137ef9e..ab24462 100644 --- a/src/test/cc/any_sketch/crypto/secret_share_test.cc +++ b/src/test/cc/any_sketch/crypto/secret_share_generator_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "any_sketch/crypto/secret_share.h" +#include "any_sketch/crypto/secret_share_generator.h" #include "absl/status/status.h" #include "absl/status/statusor.h" @@ -29,35 +29,28 @@ using math::UniformPseudorandomGenerator; TEST(AdditiveSecretSharing, EmptyInputVectorFails) { std::vector input(0); - std::unique_ptr secret_share_generator = - CreateSecretShareGenerator(); SecretShareParameter param; param.set_modulus(128); - auto ret = secret_share_generator->GenerateSecretShares(param, input); + auto ret = GenerateSecretShares(param, input); EXPECT_THAT(ret.status(), StatusIs(absl::StatusCode::kInvalidArgument, "Input must be a non-empty vector.")); } TEST(AdditiveSecretSharing, InvalidModulusFails) { std::vector input = {0, 1, 2}; - std::unique_ptr secret_share_generator = - CreateSecretShareGenerator(); SecretShareParameter param; param.set_modulus(1); - auto ret = secret_share_generator->GenerateSecretShares(param, input); + auto ret = GenerateSecretShares(param, input); EXPECT_THAT(ret.status(), StatusIs(absl::StatusCode::kInvalidArgument, "The modulus must be greater than 1.")); } TEST(AdditiveSecretSharing, SecretShareOverRingZ2kElementsSucceeds) { std::vector input = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::unique_ptr secret_share_generator = - CreateSecretShareGenerator(); SecretShareParameter param; param.set_modulus(128); - ASSERT_OK_AND_ASSIGN( - SecretShare secret_share, - secret_share_generator->GenerateSecretShares(param, input)); + ASSERT_OK_AND_ASSIGN(SecretShare secret_share, + GenerateSecretShares(param, input)); std::string key = secret_share.share_seed().key(); std::string iv = secret_share.share_seed().iv(); @@ -72,7 +65,7 @@ TEST(AdditiveSecretSharing, SecretShareOverRingZ2kElementsSucceeds) { ASSERT_OK_AND_ASSIGN( std::vector share_vector_from_seed, - prng->GetUniformRandomRange(input.size(), param.modulus())); + prng->GenerateUniformRandomRange(input.size(), param.modulus())); for (int i = 0; i < input.size(); i++) { ASSERT_EQ(input[i], @@ -83,13 +76,10 @@ TEST(AdditiveSecretSharing, SecretShareOverRingZ2kElementsSucceeds) { TEST(AdditiveSecretSharing, SecretShareOverPrimeFieldElementsSucceeds) { std::vector input = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::unique_ptr secret_share_generator = - CreateSecretShareGenerator(); SecretShareParameter param; param.set_modulus(127); - ASSERT_OK_AND_ASSIGN( - SecretShare secret_share, - secret_share_generator->GenerateSecretShares(param, input)); + ASSERT_OK_AND_ASSIGN(SecretShare secret_share, + GenerateSecretShares(param, input)); std::string key = secret_share.share_seed().key(); std::string iv = secret_share.share_seed().iv(); @@ -104,7 +94,7 @@ TEST(AdditiveSecretSharing, SecretShareOverPrimeFieldElementsSucceeds) { ASSERT_OK_AND_ASSIGN( std::vector share_vector_from_seed, - prng->GetUniformRandomRange(input.size(), param.modulus())); + prng->GenerateUniformRandomRange(input.size(), param.modulus())); for (int i = 0; i < input.size(); i++) { ASSERT_EQ(input[i], @@ -113,5 +103,17 @@ TEST(AdditiveSecretSharing, SecretShareOverPrimeFieldElementsSucceeds) { } } +TEST(AdditiveSecretSharing, InputOutOfBoundFails) { + std::vector input = {0, 1, 2, 3, 4, 5, 6, 7}; + SecretShareParameter param; + param.set_modulus(7); + auto secret_share = GenerateSecretShares(param, input); + EXPECT_THAT(secret_share.status(), + StatusIs(absl::StatusCode::kInvalidArgument, + absl::Substitute( + "Inputs must be less than the modulus, which is $0.", + param.modulus()))); +} + } // namespace } // namespace wfa::any_sketch::crypto \ No newline at end of file diff --git a/src/test/cc/math/open_ssl_uniform_random_generator_test.cc b/src/test/cc/math/open_ssl_uniform_random_generator_test.cc index 816b494..dedf231 100644 --- a/src/test/cc/math/open_ssl_uniform_random_generator_test.cc +++ b/src/test/cc/math/open_ssl_uniform_random_generator_test.cc @@ -75,7 +75,7 @@ TEST(OpenSslUniformPseudorandomGenerator, ASSERT_OK_AND_ASSIGN(std::unique_ptr prng, OpenSslUniformPseudorandomGenerator::Create(key, iv)); - auto seq = prng->GetPseudorandomBytes(0); + auto seq = prng->GeneratePseudorandomBytes(0); EXPECT_THAT( seq.status(), StatusIs(absl::StatusCode::kInvalidArgument, @@ -97,9 +97,9 @@ TEST(OpenSslUniformPseudorandomGenerator, int kNumRandomBytes = 100; ASSERT_OK_AND_ASSIGN(std::vector seq1, - prng1->GetPseudorandomBytes(kNumRandomBytes)); + prng1->GeneratePseudorandomBytes(kNumRandomBytes)); ASSERT_OK_AND_ASSIGN(std::vector seq2, - prng2->GetPseudorandomBytes(kNumRandomBytes)); + prng2->GeneratePseudorandomBytes(kNumRandomBytes)); ASSERT_EQ(seq1.size(), kNumRandomBytes); ASSERT_EQ(seq2.size(), kNumRandomBytes); @@ -121,13 +121,13 @@ TEST(OpenSslUniformPseudorandomGenerator, int kNumRandomBytes = 100; ASSERT_OK_AND_ASSIGN(std::vector seq10, - prng1->GetPseudorandomBytes(kNumRandomBytes)); + prng1->GeneratePseudorandomBytes(kNumRandomBytes)); ASSERT_OK_AND_ASSIGN(std::vector seq20, - prng2->GetPseudorandomBytes(kNumRandomBytes)); + prng2->GeneratePseudorandomBytes(kNumRandomBytes)); ASSERT_OK_AND_ASSIGN(std::vector seq11, - prng1->GetPseudorandomBytes(kNumRandomBytes)); + prng1->GeneratePseudorandomBytes(kNumRandomBytes)); ASSERT_OK_AND_ASSIGN(std::vector seq21, - prng2->GetPseudorandomBytes(kNumRandomBytes)); + prng2->GeneratePseudorandomBytes(kNumRandomBytes)); ASSERT_EQ(seq10.size(), kNumRandomBytes); ASSERT_EQ(seq20.size(), kNumRandomBytes); ASSERT_EQ(seq11.size(), kNumRandomBytes); @@ -151,13 +151,13 @@ TEST(OpenSslUniformPseudorandomGenerator, int kNumRandomBytes = 1; ASSERT_OK_AND_ASSIGN(std::vector seq10, - prng1->GetPseudorandomBytes(kNumRandomBytes)); + prng1->GeneratePseudorandomBytes(kNumRandomBytes)); ASSERT_OK_AND_ASSIGN(std::vector seq20, - prng2->GetPseudorandomBytes(kNumRandomBytes)); + prng2->GeneratePseudorandomBytes(kNumRandomBytes)); ASSERT_OK_AND_ASSIGN(std::vector seq11, - prng1->GetPseudorandomBytes(kNumRandomBytes)); + prng1->GeneratePseudorandomBytes(kNumRandomBytes)); ASSERT_OK_AND_ASSIGN(std::vector seq21, - prng2->GetPseudorandomBytes(kNumRandomBytes)); + prng2->GeneratePseudorandomBytes(kNumRandomBytes)); ASSERT_EQ(seq10.size(), kNumRandomBytes); ASSERT_EQ(seq20.size(), kNumRandomBytes); ASSERT_EQ(seq11.size(), kNumRandomBytes); @@ -182,13 +182,13 @@ TEST(OpenSslUniformPseudorandomGenerator, int kNumRandomBytes1 = 45; int kNumRandomBytes2 = 55; ASSERT_OK_AND_ASSIGN(std::vector seq10, - prng1->GetPseudorandomBytes(kNumRandomBytes1)); + prng1->GeneratePseudorandomBytes(kNumRandomBytes1)); ASSERT_OK_AND_ASSIGN(std::vector seq20, - prng2->GetPseudorandomBytes(kNumRandomBytes2)); + prng2->GeneratePseudorandomBytes(kNumRandomBytes2)); ASSERT_OK_AND_ASSIGN(std::vector seq11, - prng1->GetPseudorandomBytes(kNumRandomBytes2)); + prng1->GeneratePseudorandomBytes(kNumRandomBytes2)); ASSERT_OK_AND_ASSIGN(std::vector seq21, - prng2->GetPseudorandomBytes(kNumRandomBytes1)); + prng2->GeneratePseudorandomBytes(kNumRandomBytes1)); ASSERT_EQ(seq10.size(), kNumRandomBytes1); ASSERT_EQ(seq20.size(), kNumRandomBytes2); ASSERT_EQ(seq11.size(), kNumRandomBytes2); @@ -231,13 +231,13 @@ TEST(OpenSslUniformPseudorandomGenerator, int kBlockSize = 16; ASSERT_OK_AND_ASSIGN(std::vector seq1, - prng->GetPseudorandomBytes(kBlockSize)); + prng->GeneratePseudorandomBytes(kBlockSize)); ASSERT_OK_AND_ASSIGN(std::vector seq2, - prng->GetPseudorandomBytes(kBlockSize)); + prng->GeneratePseudorandomBytes(kBlockSize)); ASSERT_OK_AND_ASSIGN(std::vector seq3, - prng->GetPseudorandomBytes(kBlockSize)); + prng->GeneratePseudorandomBytes(kBlockSize)); ASSERT_OK_AND_ASSIGN(std::vector seq4, - prng->GetPseudorandomBytes(kBlockSize)); + prng->GeneratePseudorandomBytes(kBlockSize)); ASSERT_EQ(seq1.size(), kBlockSize); ASSERT_EQ(seq2.size(), kBlockSize); @@ -261,7 +261,7 @@ TEST(OpenSslUniformPseudorandomGenerator, uint32_t kModulus = 128; uint64_t kNumRandomElements = 0; - auto seq = prng->GetUniformRandomRange(kNumRandomElements, kModulus); + auto seq = prng->GenerateUniformRandomRange(kNumRandomElements, kModulus); EXPECT_THAT( seq.status(), StatusIs(absl::StatusCode::kInvalidArgument, @@ -279,7 +279,7 @@ TEST(OpenSslUniformPseudorandomGenerator, uint32_t kModulus = 1; uint64_t kNumRandomElements = 1; - auto seq = prng->GetUniformRandomRange(kNumRandomElements, kModulus); + auto seq = prng->GenerateUniformRandomRange(kNumRandomElements, kModulus); EXPECT_THAT(seq.status(), StatusIs(absl::StatusCode::kInvalidArgument, "The modulus must be greater than 1.")); } @@ -297,7 +297,7 @@ TEST(OpenSslUniformPseudorandomGenerator, uint64_t kNumRandomElements = 111; ASSERT_OK_AND_ASSIGN( std::vector seq, - prng->GetUniformRandomRange(kNumRandomElements, kModulus)); + prng->GenerateUniformRandomRange(kNumRandomElements, kModulus)); ASSERT_EQ(seq.size(), kNumRandomElements); for (int i = 0; i < kNumRandomElements; i++) { ASSERT_LT(seq[i], kModulus); @@ -317,7 +317,7 @@ TEST(OpenSslUniformPseudorandomGenerator, uint64_t kNumRandomElements = 111; ASSERT_OK_AND_ASSIGN( std::vector seq, - prng->GetUniformRandomRange(kNumRandomElements, kModulus)); + prng->GenerateUniformRandomRange(kNumRandomElements, kModulus)); ASSERT_EQ(seq.size(), kNumRandomElements); for (int i = 0; i < kNumRandomElements; i++) { ASSERT_LT(seq[i], kModulus); From 3537d597f6d62f33eebc481a04f73e2939106990 Mon Sep 17 00:00:00 2001 From: Phi Hung Le Date: Tue, 19 Dec 2023 23:34:01 +0000 Subject: [PATCH 05/10] Format files. --- src/test/cc/any_sketch/crypto/secret_share_generator_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/cc/any_sketch/crypto/secret_share_generator_test.cc b/src/test/cc/any_sketch/crypto/secret_share_generator_test.cc index ab24462..ba11bc4 100644 --- a/src/test/cc/any_sketch/crypto/secret_share_generator_test.cc +++ b/src/test/cc/any_sketch/crypto/secret_share_generator_test.cc @@ -116,4 +116,4 @@ TEST(AdditiveSecretSharing, InputOutOfBoundFails) { } } // namespace -} // namespace wfa::any_sketch::crypto \ No newline at end of file +} // namespace wfa::any_sketch::crypto From 6a01d5b71416bf7dbbc9f789c84613830977e058 Mon Sep 17 00:00:00 2001 From: Phi Hung Le Date: Tue, 19 Dec 2023 23:38:12 +0000 Subject: [PATCH 06/10] Format files. --- src/main/cc/any_sketch/crypto/secret_share_generator.cc | 1 + src/main/cc/math/open_ssl_uniform_random_generator.cc | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/cc/any_sketch/crypto/secret_share_generator.cc b/src/main/cc/any_sketch/crypto/secret_share_generator.cc index 2451117..95be052 100644 --- a/src/main/cc/any_sketch/crypto/secret_share_generator.cc +++ b/src/main/cc/any_sketch/crypto/secret_share_generator.cc @@ -14,6 +14,7 @@ #include "any_sketch/crypto/secret_share_generator.h" +#include #include #include "absl/status/status.h" diff --git a/src/main/cc/math/open_ssl_uniform_random_generator.cc b/src/main/cc/math/open_ssl_uniform_random_generator.cc index 645dc73..e09ad4c 100644 --- a/src/main/cc/math/open_ssl_uniform_random_generator.cc +++ b/src/main/cc/math/open_ssl_uniform_random_generator.cc @@ -123,9 +123,8 @@ OpenSslUniformPseudorandomGenerator::GenerateUniformRandomRange( // To get current_size `good` elements, it is expected to sample // 1 + current_size*(1 + failure_rate/(1-failure_rate)) elements in // [0, 2^{bit_length}). - uint64_t sample_size = - (uint64_t)(current_size + 1 + - failure_rate * current_size / (1 - failure_rate)); + uint64_t sample_size = static_cast( + current_size + 1.0 + failure_rate * current_size / (1 - failure_rate)); ASSIGN_OR_RETURN(std::vector arr, GeneratePseudorandomBytes(sample_size * bytes_per_value)); From 565ca96622cc03c10b1961e85a96d1f04dfefc11 Mon Sep 17 00:00:00 2001 From: Phi Hung Le Date: Thu, 21 Dec 2023 18:56:23 +0000 Subject: [PATCH 07/10] Update comments. --- src/main/cc/math/open_ssl_uniform_random_generator.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/cc/math/open_ssl_uniform_random_generator.cc b/src/main/cc/math/open_ssl_uniform_random_generator.cc index e09ad4c..fca23b9 100644 --- a/src/main/cc/math/open_ssl_uniform_random_generator.cc +++ b/src/main/cc/math/open_ssl_uniform_random_generator.cc @@ -88,8 +88,8 @@ OpenSslUniformPseudorandomGenerator::GeneratePseudorandomBytes(uint64_t size) { return ret; } -// Rejection sampling is used to generate uniformly random values in the range -// [0, modulus). +// Generates uniformly random values in the range [0, modulus) using rejection +// sampling method. absl::StatusOr> OpenSslUniformPseudorandomGenerator::GenerateUniformRandomRange( uint64_t size, uint32_t modulus) { From 6c981f50bfc7e7954954289a5b6de4d9a7e9bdcb Mon Sep 17 00:00:00 2001 From: Phi Hung Le Date: Tue, 26 Dec 2023 21:21:14 +0000 Subject: [PATCH 08/10] Update the SubMod function to make constant-time. --- .../cc/any_sketch/crypto/secret_share_generator.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/cc/any_sketch/crypto/secret_share_generator.cc b/src/main/cc/any_sketch/crypto/secret_share_generator.cc index 95be052..6fefd87 100644 --- a/src/main/cc/any_sketch/crypto/secret_share_generator.cc +++ b/src/main/cc/any_sketch/crypto/secret_share_generator.cc @@ -31,18 +31,16 @@ using wfa::math::UniformPseudorandomGenerator; namespace { -// This function computes (x + y) mod modulus and returns the result. +// Computes (x + y) mod modulus and returns the result with constant time. // The input values x, y, and the output are all in [0, modulus) absl::StatusOr SubMod(uint32_t x, uint32_t y, uint32_t modulus) { if (x >= modulus || y >= modulus) { return absl::InvalidArgumentError(absl::Substitute( "Inputs must be less than the modulus, which is $0.", modulus)); } - if (x >= y) { - return x - y; - } else { - return x + (modulus - y); - } + + uint32_t cmp = (x < y) ? 1 : 0; + return x - y + cmp * modulus; } } // namespace @@ -61,7 +59,7 @@ absl::StatusOr GenerateSecretShares( // Verify OpenSSL random generator seed has been seeded with enough entropy. if (RAND_status() != 1) { return absl::InternalError( - "OpenSSL random generator has been seeded with enough entropy."); + "OpenSSL random generator has not been seeded with enough entropy."); } // Sample random seed as the first share. From 36f39ace27e51bd6737b1c5a642c4e7f9a912054 Mon Sep 17 00:00:00 2001 From: Phi Hung Le Date: Tue, 26 Dec 2023 22:18:27 +0000 Subject: [PATCH 09/10] Removes all branching code from SubMod. --- src/main/cc/any_sketch/crypto/secret_share_generator.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cc/any_sketch/crypto/secret_share_generator.cc b/src/main/cc/any_sketch/crypto/secret_share_generator.cc index 6fefd87..2a39082 100644 --- a/src/main/cc/any_sketch/crypto/secret_share_generator.cc +++ b/src/main/cc/any_sketch/crypto/secret_share_generator.cc @@ -39,7 +39,7 @@ absl::StatusOr SubMod(uint32_t x, uint32_t y, uint32_t modulus) { "Inputs must be less than the modulus, which is $0.", modulus)); } - uint32_t cmp = (x < y) ? 1 : 0; + uint32_t cmp = (x < y); return x - y + cmp * modulus; } From 080dfec3429d139bfc862db8894b1c97d9243118 Mon Sep 17 00:00:00 2001 From: Phi Hung Le Date: Fri, 5 Jan 2024 11:25:55 -0500 Subject: [PATCH 10/10] Update tests. --- .../cc/any_sketch/crypto/secret_share_generator_test.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test/cc/any_sketch/crypto/secret_share_generator_test.cc b/src/test/cc/any_sketch/crypto/secret_share_generator_test.cc index ba11bc4..d7983f1 100644 --- a/src/test/cc/any_sketch/crypto/secret_share_generator_test.cc +++ b/src/test/cc/any_sketch/crypto/secret_share_generator_test.cc @@ -67,6 +67,9 @@ TEST(AdditiveSecretSharing, SecretShareOverRingZ2kElementsSucceeds) { std::vector share_vector_from_seed, prng->GenerateUniformRandomRange(input.size(), param.modulus())); + ASSERT_EQ(secret_share.share_vector().size(), input.size()); + ASSERT_EQ(share_vector_from_seed.size(), input.size()); + for (int i = 0; i < input.size(); i++) { ASSERT_EQ(input[i], (share_vector_from_seed[i] + secret_share.share_vector(i)) % @@ -96,6 +99,9 @@ TEST(AdditiveSecretSharing, SecretShareOverPrimeFieldElementsSucceeds) { std::vector share_vector_from_seed, prng->GenerateUniformRandomRange(input.size(), param.modulus())); + ASSERT_EQ(secret_share.share_vector().size(), input.size()); + ASSERT_EQ(share_vector_from_seed.size(), input.size()); + for (int i = 0; i < input.size(); i++) { ASSERT_EQ(input[i], (share_vector_from_seed[i] + secret_share.share_vector(i)) %