Skip to content

Commit b71ee1e

Browse files
authored
Add multi-party homomorphic encryption scheme (#21)
* Add multi-party homomorphic encryption scheme Also includes various improvements and updated dependencies. * Fix copyright year for new files
1 parent b381c4e commit b71ee1e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+5617
-3552
lines changed

.bazelversion

Lines changed: 0 additions & 1 deletion
This file was deleted.

MODULE.bazel

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ module(
33
)
44

55
bazel_dep(name = "tink_cc", version = "2.1.3", repo_name = "com_github_tink_crypto_tink_cc")
6-
bazel_dep(name = "rules_cc", version = "0.1.0")
6+
bazel_dep(name = "rules_cc", version = "0.1.1")
77
bazel_dep(name = "rules_proto", version = "7.0.2")
8-
bazel_dep(name = "protobuf", version = "27.3", repo_name = "com_google_protobuf")
8+
bazel_dep(name = "protobuf", version = "30.0-rc2", repo_name = "com_google_protobuf")
99
bazel_dep(name = "googletest", version = "1.15.2", repo_name = "com_github_google_googletest")
10-
bazel_dep(name = "abseil-cpp", version = "20240116.2", repo_name = "com_google_absl")
10+
bazel_dep(name = "abseil-cpp", version = "20250127.0", repo_name = "com_google_absl")
1111
bazel_dep(name = "boringssl", version = "0.20241209.0")
1212
bazel_dep(name = "glog", version = "0.5.0", repo_name = "com_github_google_glog")
1313
bazel_dep(name = "rules_license", version = "1.0.0")

MODULE.bazel.lock

Lines changed: 130 additions & 3443 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

shell_encryption/BUILD

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ cc_test(
243243

244244
cc_library(
245245
name = "dft_transformations",
246+
srcs = ["dft_transformations.cc"],
246247
hdrs = ["dft_transformations.h"],
247248
deps = [
248249
":ntt_parameters",
@@ -259,16 +260,54 @@ cc_test(
259260
],
260261
deps = [
261262
":context",
263+
":dft_transformations",
264+
":statusor_fork",
265+
"//shell_encryption/testing:parameters",
266+
"//shell_encryption/testing:status_is_fork",
267+
"//shell_encryption/testing:status_testing",
268+
"//shell_encryption/testing:testing_prng",
269+
"@com_github_google_googletest//:gtest_main",
270+
"@com_google_absl//absl/status",
271+
"@com_google_absl//absl/strings",
272+
],
273+
)
274+
275+
cc_library(
276+
name = "dft_transformations_hwy",
277+
srcs = ["dft_transformations_hwy.cc"],
278+
hdrs = [
279+
"dft_transformations_hwy.h",
280+
],
281+
deps = [
262282
":dft_transformations",
263283
":montgomery",
264284
":ntt_parameters",
265285
":statusor_fork",
286+
"@com_github_google_highway//:hwy",
287+
"@com_google_absl//absl/numeric:int128",
288+
"@com_google_absl//absl/status",
289+
],
290+
)
291+
292+
cc_test(
293+
name = "dft_transformations_hwy_test",
294+
size = "small",
295+
srcs = [
296+
"dft_transformations_hwy_test.cc",
297+
],
298+
deps = [
299+
":context",
300+
":dft_transformations",
301+
":dft_transformations_hwy",
302+
":statusor_fork",
266303
"//shell_encryption/testing:parameters",
267304
"//shell_encryption/testing:status_is_fork",
268305
"//shell_encryption/testing:status_testing",
269306
"//shell_encryption/testing:testing_prng",
270307
"@com_github_google_googletest//:gtest_main",
271-
"@com_google_absl//absl/numeric:int128",
308+
"@com_github_google_highway//:hwy",
309+
"@com_google_absl//absl/status",
310+
"@com_google_absl//absl/strings",
272311
],
273312
)
274313

@@ -280,6 +319,7 @@ cc_library(
280319
deps = [
281320
":constants",
282321
":dft_transformations",
322+
":dft_transformations_hwy",
283323
":ntt_parameters",
284324
":serialization_cc_proto",
285325
":statusor_fork",

shell_encryption/constants.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ constexpr Uint64 kNewhopeModulus = 12289;
3434
constexpr Uint64 kNewhopeLogDegreeBound = 10;
3535
constexpr Uint64 kNewhopeDegreeBound = 1 << kNewhopeLogDegreeBound;
3636

37+
// RLWE parameters for a 62 bit modulus.
38+
constexpr Uint64 kModulus62 = 4611686018427322369;
39+
constexpr Uint64 kLogDegreeBound62 = 11;
40+
constexpr Uint64 kDegreeBound62 = 1L << kLogDegreeBound62;
41+
3742
// Montgomery parameters for a 59-bit modulus.
3843
constexpr Uint64 kModulus59 = 332366567264636929;
3944
constexpr Uint64 kInvModulus59 = 7124357790306815999;
@@ -55,6 +60,11 @@ constexpr Uint64 kModulus25 = 33538049;
5560
constexpr Uint64 kLogDegreeBound25 = 10;
5661
constexpr Uint64 kDegreeBound25 = 1L << kLogDegreeBound25;
5762

63+
// RLWE parameters for a 30 bit modulus.
64+
constexpr Uint64 kModulus30 = 1073707009;
65+
constexpr Uint64 kLogDegreeBound30 = 10;
66+
constexpr Uint64 kDegreeBound30 = 1L << kLogDegreeBound30;
67+
5868
// RLWE parameters for an 80-bit modulus.
5969
// The modulus represented in decimal is 646119422561999443726337.
6070
constexpr absl::uint128 kModulus80 =
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright 2025 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+
#include "shell_encryption/dft_transformations.h"
17+
18+
#include <cmath>
19+
#include <complex>
20+
#include <cstddef>
21+
#include <vector>
22+
23+
#include "absl/status/status.h"
24+
25+
namespace rlwe {
26+
27+
namespace {
28+
29+
// Returns true if n is a power of two.
30+
inline bool IsPowerOfTwo(size_t n) { return (n & (n - 1)) == 0; }
31+
32+
} // namespace
33+
34+
absl::Status IterativeHalfCooleyTukey(
35+
std::vector<std::complex<double>>& coeffs,
36+
const std::vector<std::complex<double>>& psis_bitrev) {
37+
if (!IsPowerOfTwo(coeffs.size())) {
38+
return absl::InvalidArgumentError(
39+
"The size of `coeffs` must be a power of two.");
40+
}
41+
int len = coeffs.size();
42+
if (psis_bitrev.size() < len) {
43+
return absl::InvalidArgumentError(
44+
"Not enough primitive roots in `psis_bitrev`.");
45+
}
46+
int log_len = log2(len);
47+
for (int i = log_len - 1; i >= 0; i--) {
48+
// Layer i.
49+
const int half_m = 1 << i;
50+
const int m = half_m << 1;
51+
for (int k = 0, index_psi = 1 << (log_len - i); k < coeffs.size();
52+
k += m, ++index_psi) {
53+
const std::complex<double> psi = psis_bitrev[index_psi];
54+
for (int j = 0; j < half_m; j++) {
55+
// The Cooley-Tukey butterfly operation.
56+
std::complex<double> t = coeffs[k + j + half_m] * psi;
57+
std::complex<double> u = coeffs[k + j];
58+
coeffs[k + j] += t;
59+
coeffs[k + j + half_m] = u - t;
60+
}
61+
}
62+
}
63+
return absl::OkStatus();
64+
}
65+
66+
absl::Status IterativeHalfGentlemanSande(
67+
std::vector<std::complex<double>>& coeffs,
68+
const std::vector<std::complex<double>>& psis_bitrev_inv) {
69+
if (!IsPowerOfTwo(coeffs.size())) {
70+
return absl::InvalidArgumentError(
71+
"The size of `coeffs` must be a power of two.");
72+
}
73+
int len = coeffs.size();
74+
if (psis_bitrev_inv.size() < len * 2) {
75+
return absl::InvalidArgumentError(
76+
"Not enough primitive roots in `psis_bitrev_inv`.");
77+
}
78+
int log_len = log2(len);
79+
int index_psi_base = 0;
80+
for (int i = 0; i < log_len; i++) {
81+
const int half_m = 1 << i;
82+
const int m = half_m << 1;
83+
for (int k = 0, index_psi_inv = index_psi_base; k < coeffs.size();
84+
k += m, ++index_psi_inv) {
85+
for (int j = 0; j < half_m; j++) {
86+
// The Gentleman-Sande butterfly operation.
87+
std::complex<double> t = coeffs[k + j + half_m];
88+
std::complex<double> u = coeffs[k + j];
89+
coeffs[k + j] += t;
90+
coeffs[k + j + half_m] = (u - t) * psis_bitrev_inv[index_psi_inv];
91+
}
92+
}
93+
index_psi_base += 1 << (log_len - i);
94+
}
95+
return absl::OkStatus();
96+
}
97+
98+
} // namespace rlwe

shell_encryption/dft_transformations.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616
#ifndef RLWE_DFT_TRANSFORMATIONS_H_
1717
#define RLWE_DFT_TRANSFORMATIONS_H_
1818

19+
#include <complex>
1920
#include <utility>
2021
#include <vector>
2122

2223
#include "absl/status/status.h"
2324
#include "shell_encryption/ntt_parameters.h"
2425
#include "shell_encryption/status_macros.h"
2526

26-
// This file implements various discrete Fourier transformtions to be used by
27+
// This file implements various discrete Fourier transformations to be used by
2728
// arithmetic in polynomial rings.
2829

2930
namespace rlwe {
@@ -199,6 +200,24 @@ absl::Status InverseNumberTheoreticTransform(
199200
return absl::OkStatus();
200201
}
201202

203+
// Performs the special log_len iterations of the Cooley-Tukey butterfly on
204+
// `coeffs` in-place, which has length 2^log_len.
205+
// This computes the DFT transform phi: coeffs -> {coeffs(psi^(4k+1))}_j
206+
// where coeffs are coefficients of a polynomial of degree 2^log_len - 1, and
207+
// {psi_j}_j are primitive 2N'th roots of unity for N = 2^(log_len + 1), i.e.
208+
// psi = exp(PI * I / (2N)).
209+
absl::Status IterativeHalfCooleyTukey(
210+
std::vector<std::complex<double>>& coeffs,
211+
const std::vector<std::complex<double>>& psis_bitrev);
212+
213+
// Performs the special log_len iterations of the Gentleman-Sande butterfly on
214+
// `coeffs` in-place, which has length 2^log_len.
215+
// This computes the inverse of the transform phi, where phi is the DFT
216+
// phi: coeffs -> {coeffs(psi_j)}_{j = 4*k+1}.
217+
absl::Status IterativeHalfGentlemanSande(
218+
std::vector<std::complex<double>>& coeffs,
219+
const std::vector<std::complex<double>>& psis_bitrev_inv);
220+
202221
} // namespace rlwe
203222

204223
#endif // RLWE_DFT_TRANSFORMATIONS_H_

0 commit comments

Comments
 (0)