1 /*
2  * Copyright 2019 Google LLC.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     https://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 // Unit Tests for CamenischShoup.
17 
18 #include "private_join_and_compute/crypto/camenisch_shoup.h"
19 
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 
23 #include <cmath>
24 #include <cstdint>
25 #include <memory>
26 #include <tuple>
27 #include <utility>
28 #include <vector>
29 
30 #include "private_join_and_compute/crypto/big_num.h"
31 #include "private_join_and_compute/crypto/proto/camenisch_shoup.pb.h"
32 #include "private_join_and_compute/crypto/proto/proto_util.h"
33 #include "private_join_and_compute/util/status.inc"
34 #include "private_join_and_compute/util/status_testing.inc"
35 
36 namespace private_join_and_compute {
37 namespace {
38 using ::testing::Eq;
39 using ::testing::HasSubstr;
40 using testing::IsOkAndHolds;
41 using testing::StatusIs;
42 using ::testing::TestWithParam;
43 
PowInt(uint64_t base,int exponent)44 inline uint64_t PowInt(uint64_t base, int exponent) {
45   return static_cast<uint64_t>(std::pow(base, exponent));
46 }
47 
48 const uint64_t P = 5;
49 const uint64_t Q = 7;
50 const uint64_t N = P * Q;
51 const uint64_t S = 1;
52 const uint64_t N_TO_S_PLUS_1 = PowInt(N, S + 1);
53 const uint64_t G = 607;
54 const uint64_t X = 2;
55 const uint64_t Y = PowInt(G, X) % N_TO_S_PLUS_1;
56 
TEST(GenerateCamenischShoupKeyTest,GenerateKey)57 TEST(GenerateCamenischShoupKeyTest, GenerateKey) {
58   Context ctx;
59   int64_t n_length_bits = 32;
60   for (uint64_t s : {1, 2, 5}) {
61     for (uint64_t vector_commitment_length : {1, 2, 5}) {
62       CamenischShoupKey key = GenerateCamenischShoupKey(
63           &ctx, n_length_bits, s, vector_commitment_length);
64       // Check primes are the right length.
65       EXPECT_EQ(key.p.BitLength(), n_length_bits / 2);
66       EXPECT_EQ(key.q.BitLength(), n_length_bits / 2);
67       // Check n = p*q
68       EXPECT_EQ(key.n, key.p * key.q);
69       EXPECT_EQ(s, key.s);
70       BigNum n_to_s_plus_one = key.n.Exp(ctx.CreateBigNum(s + 1));
71       BigNum phi_n = (key.p - ctx.One()) * (key.q - ctx.One());
72       // Check that g has the right order.
73       EXPECT_EQ(ctx.One(), key.g.ModExp(phi_n, n_to_s_plus_one));
74       // Check that xs and ys have the right length and the right form.
75       EXPECT_EQ(key.ys.size(), vector_commitment_length);
76       EXPECT_EQ(key.xs.size(), vector_commitment_length);
77       for (uint64_t i = 0; i < vector_commitment_length; i++) {
78         EXPECT_EQ(key.ys[i], key.g.ModExp(key.xs[i], n_to_s_plus_one));
79         EXPECT_TRUE(key.xs[i].Gcd(key.n).IsOne());
80         EXPECT_LT(key.xs[i], key.n);
81       }
82     }
83   }
84 }
85 
TEST(GenerateCamenischShoupKeyTest,GenerateKeyPair)86 TEST(GenerateCamenischShoupKeyTest, GenerateKeyPair) {
87   Context ctx;
88   BigNum n = ctx.CreateBigNum(N);
89   BigNum phi_n = ctx.CreateBigNum((P - 1) * (Q - 1));
90   uint64_t s = 2;
91   uint64_t vector_commitment_length = 2;
92   std::unique_ptr<CamenischShoupPublicKey> public_key;
93   std::unique_ptr<CamenischShoupPrivateKey> private_key;
94 
95   std::tie(public_key, private_key) =
96       GenerateCamenischShoupKeyPair(&ctx, n, s, vector_commitment_length);
97   EXPECT_EQ(s, public_key->s);
98   BigNum n_to_s_plus_one = public_key->n.Exp(ctx.CreateBigNum(s + 1));
99 
100   // Check that g has the right order.
101   EXPECT_EQ(ctx.One(), public_key->g.ModExp(phi_n, n_to_s_plus_one));
102   // Check that xs and ys have the right length and the right form.
103   EXPECT_EQ(public_key->ys.size(), vector_commitment_length);
104   EXPECT_EQ(private_key->xs.size(), vector_commitment_length);
105   for (uint64_t i = 0; i < vector_commitment_length; i++) {
106     EXPECT_EQ(public_key->ys[i],
107               public_key->g.ModExp(private_key->xs[i], n_to_s_plus_one));
108     EXPECT_TRUE(private_key->xs[i].Gcd(public_key->n).IsOne());
109     EXPECT_LT(private_key->xs[i], public_key->n);
110   }
111 }
112 
113 // A test fixture for Serializing CamenischShoup Keys.
114 class SerializeCamenischShoupKeyTest : public ::testing::Test {
115  protected:
SetUp()116   void SetUp() override {
117     BigNum n = ctx_.CreateBigNum(N);
118     BigNum phi_n = ctx_.CreateBigNum((P - 1) * (Q - 1));
119     uint64_t s = 2;
120     int64_t vector_commitment_length = 2;
121 
122     std::tie(public_key_, private_key_) =
123         GenerateCamenischShoupKeyPair(&ctx_, n, s, vector_commitment_length);
124   }
125 
126   Context ctx_;
127   std::unique_ptr<CamenischShoupPublicKey> public_key_;
128   std::unique_ptr<CamenischShoupPrivateKey> private_key_;
129 };
130 
TEST_F(SerializeCamenischShoupKeyTest,SerializeAndDeserializeKeyPair)131 TEST_F(SerializeCamenischShoupKeyTest, SerializeAndDeserializeKeyPair) {
132   // Serialize and deserialize public key
133   proto::CamenischShoupPublicKey public_key_proto =
134       CamenischShoupPublicKeyToProto(*public_key_);
135   ASSERT_OK_AND_ASSIGN(
136       CamenischShoupPublicKey public_key_deserialized,
137       ParseCamenischShoupPublicKeyProto(&ctx_, public_key_proto));
138 
139   // Serialize and deserialize private key
140   proto::CamenischShoupPrivateKey private_key_proto =
141       CamenischShoupPrivateKeyToProto(*private_key_);
142   ASSERT_OK_AND_ASSIGN(
143       CamenischShoupPrivateKey private_key_deserialized,
144       ParseCamenischShoupPrivateKeyProto(&ctx_, private_key_proto));
145 
146   // Check that fields all line up correctly.
147   EXPECT_EQ(public_key_->n, public_key_deserialized.n);
148   EXPECT_EQ(public_key_->s, public_key_deserialized.s);
149   EXPECT_EQ(public_key_->vector_encryption_length,
150             public_key_deserialized.vector_encryption_length);
151   EXPECT_EQ(public_key_->g, public_key_deserialized.g);
152   EXPECT_EQ(public_key_->ys, public_key_deserialized.ys);
153   EXPECT_EQ(private_key_->xs, private_key_deserialized.xs);
154 }
155 
TEST_F(SerializeCamenischShoupKeyTest,DeserializingPublicKeyFailsWhenNIsMissing)156 TEST_F(SerializeCamenischShoupKeyTest,
157        DeserializingPublicKeyFailsWhenNIsMissing) {
158   // Serialize public key
159   proto::CamenischShoupPublicKey public_key_proto =
160       CamenischShoupPublicKeyToProto(*public_key_);
161 
162   // Clear n.
163   proto::CamenischShoupPublicKey public_key_proto_no_n = public_key_proto;
164   public_key_proto_no_n.clear_n();
165   EXPECT_THAT(ParseCamenischShoupPublicKeyProto(&ctx_, public_key_proto_no_n),
166               StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr(" n ")));
167 }
168 
TEST_F(SerializeCamenischShoupKeyTest,DeserializingPublicKeyFailsWhenSIsMissing)169 TEST_F(SerializeCamenischShoupKeyTest,
170        DeserializingPublicKeyFailsWhenSIsMissing) {
171   // Serialize public key
172   proto::CamenischShoupPublicKey public_key_proto =
173       CamenischShoupPublicKeyToProto(*public_key_);
174 
175   // Clear s.
176   proto::CamenischShoupPublicKey public_key_proto_no_s = public_key_proto;
177   public_key_proto_no_s.clear_s();
178   EXPECT_THAT(ParseCamenischShoupPublicKeyProto(&ctx_, public_key_proto_no_s),
179               StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr(" s ")));
180 }
181 
TEST_F(SerializeCamenischShoupKeyTest,DeserializingPublicKeyFailsWhenGIsMissing)182 TEST_F(SerializeCamenischShoupKeyTest,
183        DeserializingPublicKeyFailsWhenGIsMissing) {
184   // Serialize public key
185   proto::CamenischShoupPublicKey public_key_proto =
186       CamenischShoupPublicKeyToProto(*public_key_);
187   // Clear g.
188   proto::CamenischShoupPublicKey public_key_proto_no_g = public_key_proto;
189   public_key_proto_no_g.clear_g();
190   EXPECT_THAT(
191       ParseCamenischShoupPublicKeyProto(&ctx_, public_key_proto_no_g),
192       StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("invalid g")));
193 }
194 
TEST_F(SerializeCamenischShoupKeyTest,DeserializingPublicKeyFailsWhenYsIsMissing)195 TEST_F(SerializeCamenischShoupKeyTest,
196        DeserializingPublicKeyFailsWhenYsIsMissing) {
197   // Serialize public key
198   proto::CamenischShoupPublicKey public_key_proto =
199       CamenischShoupPublicKeyToProto(*public_key_);
200   // Clear ys.
201   proto::CamenischShoupPublicKey public_key_proto_no_ys = public_key_proto;
202   public_key_proto_no_ys.clear_ys();
203   EXPECT_THAT(
204       ParseCamenischShoupPublicKeyProto(&ctx_, public_key_proto_no_ys),
205       StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("empty ys")));
206 }
207 
TEST_F(SerializeCamenischShoupKeyTest,DeserializingPublicKeyFailsWhenGIsOutOfBounds)208 TEST_F(SerializeCamenischShoupKeyTest,
209        DeserializingPublicKeyFailsWhenGIsOutOfBounds) {
210   // Serialize public key
211   proto::CamenischShoupPublicKey public_key_proto =
212       CamenischShoupPublicKeyToProto(*public_key_);
213   BigNum out_of_bounds = ctx_.CreateBigNum(N).Exp(ctx_.CreateBigNum(2 * S));
214   // Set g out of bounds.
215   proto::CamenischShoupPublicKey public_key_proto_big_g = public_key_proto;
216   public_key_proto_big_g.set_g(out_of_bounds.ToBytes());
217   EXPECT_THAT(
218       ParseCamenischShoupPublicKeyProto(&ctx_, public_key_proto_big_g),
219       StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("invalid g")));
220 }
221 
TEST_F(SerializeCamenischShoupKeyTest,DeserializingPublicKeyFailsWhenYsIsOutOfBounds)222 TEST_F(SerializeCamenischShoupKeyTest,
223        DeserializingPublicKeyFailsWhenYsIsOutOfBounds) {
224   // Serialize public key
225   proto::CamenischShoupPublicKey public_key_proto =
226       CamenischShoupPublicKeyToProto(*public_key_);
227   // Set ys[0] out of bounds.
228   BigNum out_of_bounds = ctx_.CreateBigNum(N).Exp(ctx_.CreateBigNum(2 * S));
229   proto::CamenischShoupPublicKey public_key_proto_big_ys = public_key_proto;
230   std::vector<BigNum> big_ys = public_key_->ys;
231   big_ys[0] = out_of_bounds;
232   *public_key_proto_big_ys.mutable_ys() = BigNumVectorToProto(big_ys);
233   EXPECT_THAT(ParseCamenischShoupPublicKeyProto(&ctx_, public_key_proto_big_ys),
234               StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("ys")));
235 }
236 
237 // A test fixture for CamenischShoup.
238 class CamenischShoupTest : public ::testing::Test {
239  protected:
SetUp()240   void SetUp() override {
241     public_cam_shoup_ = std::make_unique<PublicCamenischShoup>(
242         &ctx_, ctx_.CreateBigNum(N), S, ctx_.CreateBigNum(G),
243         std::vector<BigNum>({ctx_.CreateBigNum(Y)}));
244     private_cam_shoup_ = std::make_unique<PrivateCamenischShoup>(
245         &ctx_, ctx_.CreateBigNum(N), S, ctx_.CreateBigNum(G),
246         std::vector<BigNum>({ctx_.CreateBigNum(Y)}),
247         std::vector<BigNum>({ctx_.CreateBigNum(X)}));
248   }
249 
250   Context ctx_;
251   std::unique_ptr<PublicCamenischShoup> public_cam_shoup_;
252   std::unique_ptr<PrivateCamenischShoup> private_cam_shoup_;
253 };
254 
TEST_F(CamenischShoupTest,TestEncryptWithRand)255 TEST_F(CamenischShoupTest, TestEncryptWithRand) {
256   BigNum r = ctx_.Three();
257   ASSERT_OK_AND_ASSIGN(
258       CamenischShoupCiphertext ct,
259       private_cam_shoup_->EncryptWithRand({ctx_.CreateBigNum(2)}, r));
260   EXPECT_EQ(ctx_.CreateBigNum(293),  // (607)^(3) mod 35^2
261             ct.u);
262   EXPECT_EQ(ctx_.CreateBigNum(904),  // (949)^(3) * (1 + 70) mod 35^2
263             ct.es[0]);
264 }
265 
TEST_F(CamenischShoupTest,TestEncryptAndGetRand)266 TEST_F(CamenischShoupTest, TestEncryptAndGetRand) {
267   ASSERT_OK_AND_ASSIGN(
268       CamenischShoupCiphertextWithRand ct_with_rand,
269       private_cam_shoup_->EncryptAndGetRand({ctx_.CreateBigNum(2)}));
270   ASSERT_OK_AND_ASSIGN(CamenischShoupCiphertext ct,
271                        private_cam_shoup_->EncryptWithRand(
272                            {ctx_.CreateBigNum(2)}, ct_with_rand.r));
273   EXPECT_EQ(ct.u, ct_with_rand.ct.u);
274   EXPECT_EQ(ct.es[0], ct_with_rand.ct.es[0]);
275 }
276 
TEST_F(CamenischShoupTest,TestEncryptFailsForNegativeMessage)277 TEST_F(CamenischShoupTest, TestEncryptFailsForNegativeMessage) {
278   auto maybe_result = private_cam_shoup_->Encrypt({-ctx_.One()});
279   EXPECT_TRUE(IsInvalidArgument(maybe_result.status()));
280   EXPECT_THAT(maybe_result.status().message(),
281               HasSubstr("Cannot encrypt negative number"));
282 }
283 
TEST_F(CamenischShoupTest,TestEncryptWithRandFailsForInvalidRandomness)284 TEST_F(CamenischShoupTest, TestEncryptWithRandFailsForInvalidRandomness) {
285   BigNum m = ctx_.CreateBigNum(2);
286 
287   // Negative randomness
288   BigNum r = -ctx_.Three();
289   auto maybe_result_1 = private_cam_shoup_->EncryptWithRand({m}, r);
290   EXPECT_TRUE(IsInvalidArgument(maybe_result_1.status()));
291   EXPECT_THAT(maybe_result_1.status().message(), HasSubstr(">=0"));
292 
293   // r not relatively prime to n.
294   r = ctx_.CreateBigNum(P);
295   auto maybe_result_2 = private_cam_shoup_->EncryptWithRand({m}, r);
296   EXPECT_TRUE(IsInvalidArgument(maybe_result_2.status()));
297   EXPECT_THAT(maybe_result_2.status().message(),
298               HasSubstr("not share prime factors"));
299 }
300 
TEST_F(CamenischShoupTest,TestEncryptWithDifferentRandoms)301 TEST_F(CamenischShoupTest, TestEncryptWithDifferentRandoms) {
302   ASSERT_OK_AND_ASSIGN(CamenischShoupCiphertext ct1,
303                        private_cam_shoup_->Encrypt({ctx_.CreateBigNum(2)}));
304   ASSERT_OK_AND_ASSIGN(CamenischShoupCiphertext ct2,
305                        private_cam_shoup_->Encrypt({ctx_.CreateBigNum(2)}));
306   EXPECT_NE(ct1.u, ct2.u);
307   EXPECT_NE(ct1.es[0], ct2.es[0]);
308 }
309 
TEST_F(CamenischShoupTest,TestDecryptFailsWithCorruptCiphertext)310 TEST_F(CamenischShoupTest, TestDecryptFailsWithCorruptCiphertext) {
311   CamenischShoupCiphertext ct =
312       CamenischShoupCiphertext{ctx_.Two(), {ctx_.Two()}};
313   auto maybe_result = private_cam_shoup_->Decrypt(ct);
314   EXPECT_TRUE(IsInvalidArgument(maybe_result.status()));
315   EXPECT_THAT(maybe_result.status().message(),
316               HasSubstr("Corrupt/invalid ciphertext"));
317 }
318 
TEST_F(CamenischShoupTest,TestEncryptAndDecryptOneToTen)319 TEST_F(CamenischShoupTest, TestEncryptAndDecryptOneToTen) {
320   private_cam_shoup_ = std::make_unique<PrivateCamenischShoup>(
321       &ctx_, ctx_.CreateBigNum(N), S, ctx_.CreateBigNum(G),
322       std::vector<BigNum>({ctx_.CreateBigNum(Y)}),
323       std::vector<BigNum>({ctx_.CreateBigNum(X)}));
324   for (int i = 0; i < 10; i++) {
325     BigNum bn_i = ctx_.CreateBigNum(i);
326     ASSERT_OK_AND_ASSIGN(CamenischShoupCiphertext ct,
327                          private_cam_shoup_->Encrypt({bn_i}));
328     ASSERT_OK_AND_ASSIGN(auto decrypted_value, private_cam_shoup_->Decrypt(ct));
329     EXPECT_EQ(bn_i, decrypted_value[0]);
330   }
331 }
332 
TEST_F(CamenischShoupTest,TestEncryptAndDecryptLargeMessage)333 TEST_F(CamenischShoupTest, TestEncryptAndDecryptLargeMessage) {
334   BigNum m = ctx_.CreateBigNum(N + 2);
335   ASSERT_OK_AND_ASSIGN(CamenischShoupCiphertext ct,
336                        private_cam_shoup_->Encrypt({m}));
337   ASSERT_OK_AND_ASSIGN(auto decrypted_value, private_cam_shoup_->Decrypt(ct));
338   EXPECT_EQ(m.Mod(ctx_.CreateBigNum(N)), decrypted_value[0]);
339 }
340 
TEST_F(CamenischShoupTest,TestPublicEncryptOneAndDecrypt)341 TEST_F(CamenischShoupTest, TestPublicEncryptOneAndDecrypt) {
342   public_cam_shoup_ = std::make_unique<PublicCamenischShoup>(
343       &ctx_, ctx_.CreateBigNum(N), S, ctx_.CreateBigNum(G),
344       std::vector<BigNum>({ctx_.CreateBigNum(Y)}));
345   private_cam_shoup_ = std::make_unique<PrivateCamenischShoup>(
346       &ctx_, ctx_.CreateBigNum(N), S, ctx_.CreateBigNum(G),
347       std::vector<BigNum>({ctx_.CreateBigNum(Y)}),
348       std::vector<BigNum>({ctx_.CreateBigNum(X)}));
349   ASSERT_OK_AND_ASSIGN(CamenischShoupCiphertext ct,
350                        public_cam_shoup_->Encrypt({ctx_.One()}));
351   ASSERT_OK_AND_ASSIGN(auto decrypted_value, private_cam_shoup_->Decrypt(ct));
352   EXPECT_EQ(ctx_.CreateBigNum(1), decrypted_value[0]);
353 }
354 
TEST_F(CamenischShoupTest,TestPublicEncryptWithRand)355 TEST_F(CamenischShoupTest, TestPublicEncryptWithRand) {
356   BigNum r = ctx_.Three();
357   ASSERT_OK_AND_ASSIGN(
358       CamenischShoupCiphertext ct,
359       public_cam_shoup_->EncryptWithRand({ctx_.CreateBigNum(2)}, r));
360   EXPECT_EQ(ctx_.CreateBigNum(293),  // (607)^(3) mod 35^2
361             ct.u);
362   EXPECT_EQ(ctx_.CreateBigNum(904),  // (949)^(3) * (1 + 70) mod 35^2
363             ct.es[0]);
364 }
365 
366 // A test fixture for CamenischShoup with a large random modulus. The tests are
367 // parameterized by (s, vector_encryption_length), so that the modulus is
368 // n^(s+1)), and there are vector_encryption_length secret keys.
369 class CamenischShoupLargeModulusTest
370     : public TestWithParam<std::pair<uint64_t, uint64_t>> {
371  protected:
SetUp()372   void SetUp() override {
373     std::tie(s_, vector_encryption_length_) = GetParam();
374     key_ = std::make_unique<CamenischShoupKey>(GenerateCamenischShoupKey(
375         &ctx_, /*n_length_bits=*/32, s_, vector_encryption_length_));
376     public_cam_shoup_ = std::make_unique<PublicCamenischShoup>(
377         &ctx_, key_->n, key_->s, key_->g, key_->ys);
378     private_cam_shoup_ = std::make_unique<PrivateCamenischShoup>(
379         &ctx_, key_->n, key_->s, key_->g, key_->ys, key_->xs);
380   }
381 
382   Context ctx_;
383   uint64_t s_;
384   uint64_t vector_encryption_length_;
385   std::unique_ptr<CamenischShoupKey> key_;
386   std::unique_ptr<PublicCamenischShoup> public_cam_shoup_;
387   std::unique_ptr<PrivateCamenischShoup> private_cam_shoup_;
388 };
389 
TEST_P(CamenischShoupLargeModulusTest,TestEncryptAndDecryptOneItemWithLargeModulus)390 TEST_P(CamenischShoupLargeModulusTest,
391        TestEncryptAndDecryptOneItemWithLargeModulus) {
392   ASSERT_OK_AND_ASSIGN(
393       auto ct, private_cam_shoup_->Encrypt({ctx_.CreateBigNum(4234234)}));
394   ASSERT_OK_AND_ASSIGN(std::vector<BigNum> decrypted,
395                        private_cam_shoup_->Decrypt(ct));
396 
397   // The first decrypted value should be as expected.
398   EXPECT_EQ(ctx_.CreateBigNum(4234234), decrypted[0]);
399   EXPECT_EQ(vector_encryption_length_, decrypted.size());
400 
401   // The rest should be padded with 0s.
402   for (uint64_t i = 1; i < vector_encryption_length_; i++) {
403     EXPECT_EQ(decrypted[i], ctx_.Zero());
404   }
405 }
406 
TEST_P(CamenischShoupLargeModulusTest,TestEncryptAndDecryptRandomNumber)407 TEST_P(CamenischShoupLargeModulusTest, TestEncryptAndDecryptRandomNumber) {
408   std::vector<BigNum> random_messages;
409   random_messages.reserve(vector_encryption_length_);
410   for (uint64_t i = 0; i < vector_encryption_length_; i++) {
411     random_messages.push_back(
412         ctx_.GenerateRandLessThan(public_cam_shoup_->message_upper_bound()));
413   }
414   ASSERT_OK_AND_ASSIGN(auto ct, private_cam_shoup_->Encrypt(random_messages));
415   EXPECT_THAT(private_cam_shoup_->Decrypt(ct),
416               IsOkAndHolds(Eq(random_messages)));
417 }
418 
TEST_P(CamenischShoupLargeModulusTest,TestAdd)419 TEST_P(CamenischShoupLargeModulusTest, TestAdd) {
420   std::vector<BigNum> random_messages_1;
421   std::vector<BigNum> random_messages_2;
422   std::vector<BigNum> sums;
423   random_messages_1.reserve(vector_encryption_length_);
424   random_messages_2.reserve(vector_encryption_length_);
425   sums.reserve(vector_encryption_length_);
426   for (uint64_t i = 0; i < vector_encryption_length_; i++) {
427     random_messages_1.push_back(
428         ctx_.GenerateRandLessThan(public_cam_shoup_->message_upper_bound()));
429     random_messages_2.push_back(
430         ctx_.GenerateRandLessThan(public_cam_shoup_->message_upper_bound()));
431     sums.push_back(random_messages_1[i].ModAdd(
432         random_messages_2[i], public_cam_shoup_->message_upper_bound()));
433   }
434 
435   ASSERT_OK_AND_ASSIGN(CamenischShoupCiphertext ct1,
436                        public_cam_shoup_->Encrypt(random_messages_1));
437   ASSERT_OK_AND_ASSIGN(CamenischShoupCiphertext ct2,
438                        public_cam_shoup_->Encrypt(random_messages_2));
439 
440   CamenischShoupCiphertext sum_ct = public_cam_shoup_->Add(ct1, ct2);
441 
442   EXPECT_THAT(private_cam_shoup_->Decrypt(sum_ct), IsOkAndHolds(Eq(sums)));
443 }
444 
TEST_P(CamenischShoupLargeModulusTest,TestMultiply)445 TEST_P(CamenischShoupLargeModulusTest, TestMultiply) {
446   std::vector<BigNum> random_messages;
447   BigNum scalar = ctx_.CreateBigNum(3);
448   std::vector<BigNum> products;
449   random_messages.reserve(vector_encryption_length_);
450   products.reserve(vector_encryption_length_);
451   for (uint64_t i = 0; i < vector_encryption_length_; i++) {
452     random_messages.push_back(
453         ctx_.GenerateRandLessThan(public_cam_shoup_->message_upper_bound()));
454     products.push_back(random_messages[i].ModMul(
455         scalar, public_cam_shoup_->message_upper_bound()));
456   }
457 
458   ASSERT_OK_AND_ASSIGN(CamenischShoupCiphertext ct,
459                        public_cam_shoup_->Encrypt(random_messages));
460 
461   CamenischShoupCiphertext prod_ct = public_cam_shoup_->Multiply(ct, scalar);
462 
463   EXPECT_THAT(private_cam_shoup_->Decrypt(prod_ct), IsOkAndHolds(Eq(products)));
464 }
465 
TEST_P(CamenischShoupLargeModulusTest,SerializeAndDeserializeCiphertext)466 TEST_P(CamenischShoupLargeModulusTest, SerializeAndDeserializeCiphertext) {
467   std::vector<BigNum> random_messages;
468   random_messages.reserve(vector_encryption_length_);
469   for (uint64_t i = 0; i < vector_encryption_length_; i++) {
470     random_messages.push_back(
471         ctx_.GenerateRandLessThan(public_cam_shoup_->message_upper_bound()));
472   }
473   ASSERT_OK_AND_ASSIGN(CamenischShoupCiphertext ct,
474                        private_cam_shoup_->Encrypt(random_messages));
475 
476   proto::CamenischShoupCiphertext serialized_ciphertext =
477       CamenischShoupCiphertextToProto(ct);
478   ASSERT_OK_AND_ASSIGN(
479       CamenischShoupCiphertext deserialized_ciphertext,
480       private_cam_shoup_->ParseCiphertextProto(serialized_ciphertext));
481 
482   EXPECT_EQ(ct.u, deserialized_ciphertext.u);
483   EXPECT_EQ(ct.es, deserialized_ciphertext.es);
484 }
485 
TEST_P(CamenischShoupLargeModulusTest,DeserializingCiphertextFailsWhenUOutOfBounds)486 TEST_P(CamenischShoupLargeModulusTest,
487        DeserializingCiphertextFailsWhenUOutOfBounds) {
488   std::vector<BigNum> random_messages;
489   random_messages.reserve(vector_encryption_length_);
490   for (uint64_t i = 0; i < vector_encryption_length_; i++) {
491     random_messages.push_back(
492         ctx_.GenerateRandLessThan(public_cam_shoup_->message_upper_bound()));
493   }
494   ASSERT_OK_AND_ASSIGN(CamenischShoupCiphertext ct,
495                        private_cam_shoup_->Encrypt(random_messages));
496 
497   proto::CamenischShoupCiphertext serialized_ciphertext =
498       CamenischShoupCiphertextToProto(ct);
499 
500   BigNum out_of_bounds = public_cam_shoup_->modulus() + ctx_.One();
501   // Out of Bounds u.
502   proto::CamenischShoupCiphertext serialized_ciphertext_u_out_of_bounds =
503       serialized_ciphertext;
504   serialized_ciphertext_u_out_of_bounds.set_u(out_of_bounds.ToBytes());
505   EXPECT_THAT(private_cam_shoup_->ParseCiphertextProto(
506                   serialized_ciphertext_u_out_of_bounds),
507               StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr(" u")));
508 }
509 
TEST_P(CamenischShoupLargeModulusTest,DeserializingCiphertextFailsWhenTooManyEs)510 TEST_P(CamenischShoupLargeModulusTest,
511        DeserializingCiphertextFailsWhenTooManyEs) {
512   std::vector<BigNum> random_messages;
513   random_messages.reserve(vector_encryption_length_);
514   for (uint64_t i = 0; i < vector_encryption_length_; i++) {
515     random_messages.push_back(
516         ctx_.GenerateRandLessThan(public_cam_shoup_->message_upper_bound()));
517   }
518   ASSERT_OK_AND_ASSIGN(CamenischShoupCiphertext ct,
519                        private_cam_shoup_->Encrypt(random_messages));
520 
521   proto::CamenischShoupCiphertext serialized_ciphertext =
522       CamenischShoupCiphertextToProto(ct);
523 
524   // Too many es.
525   proto::CamenischShoupCiphertext serialized_ciphertext_too_many_es =
526       serialized_ciphertext;
527   std::vector<BigNum> too_many_es = ct.es;
528   too_many_es.push_back(ctx_.Zero());
529   *serialized_ciphertext_too_many_es.mutable_es() =
530       BigNumVectorToProto(too_many_es);
531   EXPECT_THAT(private_cam_shoup_->ParseCiphertextProto(
532                   serialized_ciphertext_too_many_es),
533               StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr(" es")));
534 }
535 
TEST_P(CamenischShoupLargeModulusTest,DeserializingCiphertextFailsWhenEsOutOfBounds)536 TEST_P(CamenischShoupLargeModulusTest,
537        DeserializingCiphertextFailsWhenEsOutOfBounds) {
538   std::vector<BigNum> random_messages;
539   random_messages.reserve(vector_encryption_length_);
540   for (uint64_t i = 0; i < vector_encryption_length_; i++) {
541     random_messages.push_back(
542         ctx_.GenerateRandLessThan(public_cam_shoup_->message_upper_bound()));
543   }
544   ASSERT_OK_AND_ASSIGN(CamenischShoupCiphertext ct,
545                        private_cam_shoup_->Encrypt(random_messages));
546 
547   proto::CamenischShoupCiphertext serialized_ciphertext =
548       CamenischShoupCiphertextToProto(ct);
549 
550   BigNum out_of_bounds = public_cam_shoup_->modulus() + ctx_.One();
551 
552   // es out of bounds.
553   proto::CamenischShoupCiphertext serialized_ciphertext_es_out_of_bounds =
554       serialized_ciphertext;
555   std::vector<BigNum> es_out_of_bounds = ct.es;
556   es_out_of_bounds[0] = out_of_bounds;
557   *serialized_ciphertext_es_out_of_bounds.mutable_es() =
558       BigNumVectorToProto(es_out_of_bounds);
559   EXPECT_THAT(private_cam_shoup_->ParseCiphertextProto(
560                   serialized_ciphertext_es_out_of_bounds),
561               StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr(" es")));
562 }
563 
TEST_P(CamenischShoupLargeModulusTest,DeserializingEmptyCiphertextGivesCiphertextWithEmptyEs)564 TEST_P(CamenischShoupLargeModulusTest,
565        DeserializingEmptyCiphertextGivesCiphertextWithEmptyEs) {
566   proto::CamenischShoupCiphertext serialized_ciphertext;  // Default instance.
567 
568   ASSERT_OK_AND_ASSIGN(
569       CamenischShoupCiphertext deserialized,
570       private_cam_shoup_->ParseCiphertextProto(serialized_ciphertext));
571 
572   EXPECT_TRUE(deserialized.es.empty());
573 }
574 
575 INSTANTIATE_TEST_SUITE_P(CamenischShoupLargeModulusTestWithDifferentS,
576                          CamenischShoupLargeModulusTest,
577                          ::testing::Values(std::make_pair(1, 1),
578                                            std::make_pair(5, 1),
579                                            std::make_pair(1, 5),
580                                            std::make_pair(5, 5)));
581 
582 }  // namespace
583 }  // namespace private_join_and_compute
584