This repository was archived by the owner on Jan 12, 2026. It is now read-only.
forked from google/shell-encryption
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrelinearization_key.h
More file actions
197 lines (167 loc) · 8.63 KB
/
relinearization_key.h
File metadata and controls
197 lines (167 loc) · 8.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/*
* Copyright 2018 Google LLC.
* 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
*
* https://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 RLWE_RELINEARIZATION_KEY_H_
#define RLWE_RELINEARIZATION_KEY_H_
#include <cstdint>
#include <vector>
#include "sample_error.h"
#include "statusor.h"
#include "symmetric_encryption.h"
namespace rlwe {
// Represents a RelinearizationKey constructed from a symmetric-key. Applying a
// RelinearizationKey of order k to a ciphertext {m1}_s encrypting m1 with
// k components produces a ciphertext {m1}_s with 2 components encrypted with
// the same secret key s. This is one of two ways key-switching is used, the
// other being GaloisKeys.
//
// RelinearizationKeys are constructed based on the secret key. Two
// RelinearizationKeys that correspond to the same secret key, number of parts,
// and use the same decomposition modulus will not necessarily be equal. This is
// due to randomness that is sampled when the key is created. However, both will
// relinearize a ciphertext. This randomness is generated from a PRNG with a
// given prng_seed.
//
// This variant of key-switching is based on a decomposition modulo a general
// modulus T. We restrict this decomposition modulus T to be a power of 2, and
// log_2(T) generally ranges form 1 to log_2(q)/2. We treat T as a parameter to
// be optimized for. The matrix W is the sum of two matrices: (1) the first is
// the matrix A = [PowersofT(( s, ..., s^{k-1})) + t * e, 0], and (2) a matrix
// R which is perpendicular to (1, s). Note that A consists of "encryptions" of
// the PowersOfT (setting a = 0 in {as + et + m, -a}), and R basically consists
// of encryptions of 0 under (1,s). The sum of these two matrices yields
// essentially "encryptions" of the non-trivial powers of the length k secret
// key (s, s^2, ..., s^{k-1}) under the length 2 secret key (1,s).
//
// Details can be found in Appendix D.2 of https://eprint.iacr.org/2011/566.pdf
//
// Only MontgomeryInt types (Uint16, Uint32, Uint64, absl::uint128) are
// supported.
// The RelinearizationKey, which holds a vector of RelinearizationKeyParts of
// length (k - 1), where k is the number of parts of the ciphertext it applies
// to.
template <typename ModularInt>
class RelinearizationKey {
using ModularIntParams = typename ModularInt::Params;
public:
// Initializes a RelinearizationKey based on a SymmetricRlweKey key that can
// relinearize ciphertexts with at most num_parts components.
// A positive log_decomposition_modulus corresponds to the decomposition
// modulus T. The prng_seed is used to generate and encode the random entries
// that form the bottom row of the matrix. For most RelinearizationKeys, the
// substitution_power is 1. This corresponds to the power of x in the secret
// key polynomial s(x^substitution_power) that the ciphertext is encrypted
// with. This power changes when substitutions of the form x->x^k (Galois
// automorphisms) have been applied to ciphertexts, yielding an encryption
// with (1, s^k). In that case, we would use a relinearization key with
// substition_power = k to return the ciphertext to be encrypted with (1,s).
// See GaloisKey for an explicit wrapper around RelinearizationKey.
static rlwe::StatusOr<RelinearizationKey> Create(
const SymmetricRlweKey<ModularInt>& key, absl::string_view prng_seed,
ssize_t num_parts, Uint64 log_decomposition_modulus,
Uint64 substitution_power = 1);
// Takes a SymmetricRlweCiphertext with at most num_parts components and
// returns a 2 component SymmetricRlweCiphertext encoding the same message.
// Returns an error when the number of components of ciphertext is larger than
// the number of parts of the RelineraizationKey.
rlwe::StatusOr<SymmetricRlweCiphertext<ModularInt>> ApplyTo(
const SymmetricRlweCiphertext<ModularInt>& ciphertext) const;
// Returns a SerializedRelinearizationKey containing a flattened
// representation of the SerializedNttPolynomials in the key, the
// log_decomposition_modulus, and the number of parts the key is comprised of.
rlwe::StatusOr<SerializedRelinearizationKey> Serialize() const;
// Requires that the number of NTT Polynomials in serialized is (num_parts) *
// (2 * dimension) where dimension is the number of digits needed to represent
// the modulus in base 2^{log_decomposition_modulus}. Crashes for non-valid
// input parameters.
static rlwe::StatusOr<RelinearizationKey> Deserialize(
const SerializedRelinearizationKey& serialized,
const ModularIntParams* modulus_params,
const NttParameters<ModularInt>* ntt_params);
// Substitution Power accessor.
int SubstitutionPower() const { return substitution_power_; }
private:
// Represents part of the RelinearizationKey corresponding to a single
// component of the secret key.
class RelinearizationKeyPart {
public:
static rlwe::StatusOr<RelinearizationKeyPart> Create(
const Polynomial<ModularInt>& key_power,
const SymmetricRlweKey<ModularInt>& key,
const Uint64 log_decomposition_modulus,
const ModularInt& decomposition_modulus, int dimension,
SecurePrng* prng, SecurePrng* prng_encryption);
// For RelinearizationKeyPart i, this method takes the ith component of the
// ciphertext and params, and applies the RelinearizationKeyPart matrix to
// an expanded ciphertext component vector to produce a 2-component vector
// of polynomials.
rlwe::StatusOr<std::vector<Polynomial<ModularInt>>> ApplyPartTo(
const Polynomial<ModularInt>& ciphertext_part,
const ModularIntParams* modulus_params,
const NttParameters<ModularInt>* ntt_params) const;
// Creates a RelinearizationKeyPart out of a vector of Polynomials.
static rlwe::StatusOr<RelinearizationKeyPart> Deserialize(
const std::vector<SerializedNttPolynomial>& polynomials,
Uint64 log_decomposition_modulus, SecurePrng* prng,
const ModularIntParams* modulus_params,
const NttParameters<ModularInt>* ntt_params);
std::vector<Polynomial<ModularInt>> Matrix() const { return matrix_[0]; }
private:
RelinearizationKeyPart(
std::vector<std::vector<Polynomial<ModularInt>>> matrix,
Uint64 log_decomposition_modulus)
: matrix_(std::move(matrix)),
log_decomposition_modulus_(log_decomposition_modulus) {}
std::vector<std::vector<Polynomial<ModularInt>>> matrix_;
const Uint64 log_decomposition_modulus_;
};
// Creates an empty RelinearizationKey.
RelinearizationKey(Uint64 log_decomposition_modulus,
const ModularInt& decomposition_modulus,
const ModularIntParams* params,
const NttParameters<ModularInt>* ntt_params)
: log_decomposition_modulus_(log_decomposition_modulus),
decomposition_modulus_(decomposition_modulus),
substitution_power_(1),
modulus_params_(params),
ntt_params_(ntt_params) {}
RelinearizationKey(const SymmetricRlweKey<ModularInt>& key,
absl::string_view prng_seed, ssize_t num_parts,
Uint64 log_decomposition_modulus,
Uint64 substitution_power,
ModularInt decomposition_modulus,
std::vector<RelinearizationKeyPart> relinearization_key);
// Dimension of the relinearization key matrix.
int dimension_;
// Number of parts the key corresponds to.
int num_parts_;
const Uint64 log_decomposition_modulus_;
ModularInt decomposition_modulus_;
// Substitution power.
int substitution_power_;
// Modulus parameters. Does not take ownership.
const ModularIntParams* modulus_params_;
// NTT parameters. Does not take ownership.
const NttParameters<ModularInt>* ntt_params_;
// The key-switching matrix. Each component in the vector is a
// RelinearizationKeyPart: a 2 by dimension_ matrix corresponding to a single
// power of the key. In this way, a RelinearizationKey for a length k
// ciphertext can be used to transform ciphertext with any number of parts up
// to k by only using items 0 to k-1 of the relinearization_key_.
std::vector<RelinearizationKeyPart> relinearization_key_;
// Prng seed
std::string prng_seed_;
};
} // namespace rlwe
#endif // RLWE_RELINEARIZATION_KEY_H_