123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- /*
- * 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.
- */
- // Implementation of compressed ciphertexts.
- //
- // In the RLWE encryption scheme, the second component of the ciphertext, a, is
- // drawn uniformly at random (that is, each coefficient is drawn uniformly at
- // random). If we the second components of a series of ciphertexts are
- // constructed using the pseudorandom outputs of a PRNG, the second components
- // can be encoded using the PRNG's seed, which is the functionality provided
- // here.
- //
- // An important note is that the order of encrypting the ciphertexts is
- // important. When decompressing, the order of the ciphertexts must be given in
- // the exact same order that the ciphertexts were encrypted to ensure the same
- // random polynomials are constructed for the correct ciphertext. Since a party
- // without the private key will be decompressing, it is impossible to check if
- // the decompressions were performed properly.
- #ifndef RLWE_SYMMETRIC_ENCRYPTION_WITH_PRNG_H_
- #define RLWE_SYMMETRIC_ENCRYPTION_WITH_PRNG_H_
- #include <vector>
- #include "polynomial.h"
- #include "prng/integral_prng_types.h"
- #include "prng/prng.h"
- #include "status_macros.h"
- #include "statusor.h"
- #include "symmetric_encryption.h"
- namespace rlwe {
- // Encrypts a set of plaintexts using randomness-of-encryption sampled using the
- // specified PRNG.
- //
- // When encrypting a plaintext, the c0 component of a ciphertext incorporates a
- // polynomial "a" where each coefficient is drawn uniformly and independently at
- // random. The c1 component of the ciphertext is exactly "-a" to ensure
- // homomorphic operations and decryption may occur. Instead of sending "a"
- // explicitly, we may construct "a" using the seed of a pseudorandom number
- // generator. Then, we may simply send the seed used to generate all "a"s
- // together with only the c0 components of each ciphertext. This would allow the
- // server to replay the PRNG and recover all "a"s and thereby reconstruct the
- // c1 components of the ciphertexts. As a result, the required communication
- // would be cut almost in half.
- //
- // Note, the c0 components of the ciphertext have an additional error vector
- // added to them. This error vector is drawn separately from the PRNG used to
- // compute all "a"s. The error vector remaining hidden is important for
- // security.
- //
- // Importantly, the order of the compressed ciphertexts must remain static
- // before decompression. Otherwise, the decompression will be incorrect.
- //
- // Two PRNGs are being passed: one is used to sample random polynomials that
- // is required to be used for decryption. The other PRNG is used to sample error
- // that does not need to be used for decryption.
- template <typename ModularInt>
- rlwe::StatusOr<std::vector<Polynomial<ModularInt>>> EncryptWithPrng(
- const SymmetricRlweKey<ModularInt>& key,
- const std::vector<Polynomial<ModularInt>>& plaintexts, SecurePrng* prng,
- SecurePrng* prng_encryption) {
- std::vector<Polynomial<ModularInt>> c0s(plaintexts.size());
- for (int i = 0; i < c0s.size(); ++i) {
- RLWE_ASSIGN_OR_RETURN(auto a, SamplePolynomialFromPrng<ModularInt>(
- key.Len(), prng, key.ModulusParams()));
- RLWE_ASSIGN_OR_RETURN(
- c0s[i], internal::Encrypt(key, plaintexts[i], a, prng_encryption));
- }
- return c0s;
- }
- // Given a list of compressed encryption and the seed of the PRNG used for
- // compression, this function will decompress the encryptions so the ciphertexts
- // can now be used in homomorphic operations.
- //
- // The compressed ciphertexts must be given in the same order as they were given
- // to be encrypted.
- template <typename ModularInt>
- rlwe::StatusOr<std::vector<SymmetricRlweCiphertext<ModularInt>>> ExpandFromPrng(
- std::vector<Polynomial<ModularInt>> c0,
- const typename ModularInt::Params* modulus_params,
- const NttParameters<ModularInt>* ntt_params,
- const ErrorParams<ModularInt>* error_params, SecurePrng* prng) {
- std::vector<SymmetricRlweCiphertext<ModularInt>> ciphertexts;
- for (int i = 0; i < c0.size(); ++i) {
- RLWE_ASSIGN_OR_RETURN(auto a, SamplePolynomialFromPrng<ModularInt>(
- c0[i].Len(), prng, modulus_params));
- // Ciphertexts that can be expanded from PRNG must be fresh encryptions.
- ciphertexts.emplace_back(
- std::vector<Polynomial<ModularInt>>(
- {std::move(c0[i]), std::move(a.NegateInPlace(modulus_params))}),
- 1, error_params->B_encryption(), modulus_params, error_params);
- }
- return ciphertexts;
- }
- } // namespace rlwe
- #endif // RLWE_SYMMETRIC_ENCRYPTION_WITH_PRNG_H_
|