diff --git a/heu/algorithms/incubator/ishe/BUILD.bazel b/heu/algorithms/incubator/ishe/BUILD.bazel new file mode 100644 index 0000000..59beafb --- /dev/null +++ b/heu/algorithms/incubator/ishe/BUILD.bazel @@ -0,0 +1,81 @@ +# Copyright 2024 CyberChangAn Group, Xidian University. +# +# 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. + +load("@yacl//bazel:yacl.bzl", "yacl_cc_library", "yacl_cc_test") + +package(default_visibility = ["//visibility:public"]) + +test_suite( + name = "ishe_tests", +) + +yacl_cc_library( + name = "ishe", + srcs = ["he_kit.cc"], + hdrs = ["he_kit.h"], + deps = [ + ":base", + ":decryptor", + ":encryptor", + ":evaluator", + ], + alwayslink = 1, +) + +yacl_cc_library( + name = "base", + srcs = ["base.cc"], + hdrs = ["base.h"], + deps = [ + "//heu/spi/he/sketches/scalar/phe", + "//heu/spi/utils:formater", + "@yacl//yacl/utils:serializer", + ], +) + +yacl_cc_library( + name = "encryptor", + srcs = ["encryptor.cc"], + hdrs = ["encryptor.h"], + deps = [ + ":base", + "//heu/spi/utils:formater", + ], +) + +yacl_cc_library( + name = "decryptor", + srcs = ["decryptor.cc"], + hdrs = ["decryptor.h"], + deps = [ + ":base", + ], +) + +yacl_cc_library( + name = "evaluator", + srcs = ["evaluator.cc"], + hdrs = ["evaluator.h"], + deps = [ + ":encryptor", + ], +) + +yacl_cc_test( + name = "ishe_test", + srcs = ["ishe_test.cc"], + deps = [ + ":ishe", + ], +) diff --git a/heu/algorithms/incubator/ishe/README.md b/heu/algorithms/incubator/ishe/README.md new file mode 100644 index 0000000..558c926 --- /dev/null +++ b/heu/algorithms/incubator/ishe/README.md @@ -0,0 +1,52 @@ +# iSHE + +## 简介 + +iSHE(improved SHE),是一种对主流的对称同态加密技术的改进的对称同态加密技术(Symmetric Homomorphic Encryption,SHE)而提出的新的同态加密技术,它可以在不损害安全性的情况下提高原始SHE的性能,并在一些解决方案中作为加密原语。SHE被证明是CPA安全的,被广泛应用于可搜索的加密方案中,而iSHE是原始SHE在抵抗AGCD(Approximate Greatest Common Divisor)攻击的同时提高性能的一个新版本。 + + +## 同态性质 + +### Mul-1 + +Ciphertext mul ciphertext: + +iSHE.Dec(sk,(⟦m1⟧·⟦m_2⟧) mod N, d) = m1· m2 + +### Mul-2 + +Ciphertext mul plaintext: + +iSHE.Dec(sk,(⟦m1⟧·m2) mod N, d) = m1·m2 + +### Add-1 + +Ciphertext add ciphertext: + +iSHE.Dec(sk,(⟦m1⟧+ ⟦m2⟧) mod N, d) = m1+m2 + +### Add-2 + +Ciphertext add plaintext: + +iSHE.Dec(sk,(⟦m1⟧+ m2) mod N, d) = m1+m2 + +## 相关文献 + +### 安全性和详细证明请参考文献: + +https://ieeexplore.ieee.org/document/10517763 + +Performance Enhanced Secure Spatial Keyword Similarity Query With Arbitrary Spatial Ranges (TIFS’24) + +section Ⅴ.A on page 5280 + +### AGCD攻击相关定义和理论: + +https://eprint.iacr.org/2009/616.pdf + +Fully Homomorphic Encryption over the Integers + +https://eprint.iacr.org/2016/215.pdf + +Algorithms for the Approximate Common Divisor Problem diff --git a/heu/algorithms/incubator/ishe/base.cc b/heu/algorithms/incubator/ishe/base.cc new file mode 100644 index 0000000..6d84790 --- /dev/null +++ b/heu/algorithms/incubator/ishe/base.cc @@ -0,0 +1,104 @@ +// Copyright 2024 CyberChangAn Group, Xidian University. +// +// 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 "heu/algorithms/incubator/ishe/base.h" + +namespace heu::algos::ishe { + +Plaintext ItemTool::Clone(const Plaintext &pt) const { return pt; } + +Ciphertext ItemTool::Clone(const Ciphertext &ct) const { + return Ciphertext(ct.n_, ct.d_); +} + +size_t Ciphertext::Serialize(uint8_t *buf, size_t buf_len) const { + return yacl::SerializeVarsTo(buf, buf_len, n_, d_); +} + +yacl::Buffer Ciphertext::Serialize() const { + return yacl::SerializeVars(n_, d_); +} + +void Ciphertext::Deserialize(yacl::ByteContainerView buffer) { + DeserializeVarsTo(buffer, &n_, &d_); +} + +std::string Ciphertext::ToString() const { + return fmt::format("CT: ({},{})", n_, d_); +} + +SecretKey::SecretKey(MPInt s, MPInt p, MPInt L) { + this->s_ = std::move(s); + this->p_ = std::move(p); + this->L_ = std::move(L); +} + +yacl::Buffer SecretKey::Serialize2Buffer() const { + return yacl::SerializeVars(s_, p_, L_); +} + +yacl::Buffer PublicParameters::Serialize2Buffer() const { + return yacl::SerializeVars(k_0, k_r, k_M, N, ADDONES, ONES, NEGS); +} + +size_t SecretKey::Serialize(uint8_t *buf, size_t buf_len) const { + return yacl::SerializeVarsTo(buf, buf_len, s_, p_, L_); +} + +std::shared_ptr SecretKey::LoadFrom(yacl::ByteContainerView in) { + auto sk = std::make_shared(); + DeserializeVarsTo(in, &sk->s_, &sk->p_, &sk->L_); + return sk; +} + +PublicParameters::PublicParameters(int64_t k_0, int64_t k_r, int64_t k_M, + const MPInt &N) { + this->k_0 = k_0; + this->k_r = k_r; + this->k_M = k_M; + Init(); + this->N = N; +} + +PublicParameters::PublicParameters(int64_t k_0, int64_t k_r, int64_t k_M, + const MPInt &N, + const std::vector &ADDONES, + const std::vector &ONES, + const std::vector &NEGS) + : PublicParameters(k_0, k_r, k_M, N) { + this->ADDONES = ADDONES; + this->ONES = ONES; + this->NEGS = NEGS; +} + +size_t PublicParameters::Serialize(uint8_t *buf, size_t buf_len) const { + return yacl::SerializeVarsTo(buf, buf_len, k_0, k_r, k_M, N, ADDONES, ONES, + NEGS); +} + +void PublicParameters::Init() { + MPInt::Pow(MPInt(2), k_M - 1, &this->M[1]); + this->M[0] = -this->M[1]; +} + +std::shared_ptr PublicParameters::LoadFrom( + yacl::ByteContainerView in) { + auto pp = std::make_shared(); + DeserializeVarsTo(in, &pp->k_0, &pp->k_r, &pp->k_M, &pp->N, &pp->ADDONES, + &pp->ONES, &pp->NEGS); + pp->Init(); + return pp; +} + +} // namespace heu::algos::ishe diff --git a/heu/algorithms/incubator/ishe/base.h b/heu/algorithms/incubator/ishe/base.h new file mode 100644 index 0000000..8d61f4d --- /dev/null +++ b/heu/algorithms/incubator/ishe/base.h @@ -0,0 +1,124 @@ +// Copyright 2024 CyberChangAn Group, Xidian University. +// +// 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. + +#pragma once + +#include +#include +#include + +#include "yacl/base/byte_container_view.h" +#include "yacl/math/mpint/mp_int.h" +#include "yacl/utils/serializer.h" + +#include "heu/spi/he/sketches/common/keys.h" +#include "heu/spi/he/sketches/scalar/item_tool.h" + +namespace heu::algos::ishe { + +using yacl::math::MPInt; +using Plaintext = MPInt; + +class Ciphertext { + public: + // default constructor + Ciphertext() = default; + + explicit Ciphertext(MPInt n) : n_(std::move(n)) { d_ = MPInt(1); } + + explicit Ciphertext(MPInt n, MPInt d) : n_(std::move(n)), d_(std::move(d)) {} + + size_t Serialize(uint8_t *buf, size_t buf_len) const; + [[nodiscard]] yacl::Buffer Serialize() const; + void Deserialize(yacl::ByteContainerView buffer); + [[nodiscard]] std::string ToString() const; + + bool operator==(const Ciphertext &other) const { + return n_ == other.n_ && d_ == other.d_; + } + + MPInt n_, d_; +}; + +class SecretKey : public spi::KeySketch { + private: + MPInt s_, p_, L_; + + public: + SecretKey(MPInt s, MPInt p, MPInt L); + + SecretKey() = default; + + [[nodiscard]] yacl::Buffer Serialize2Buffer() const; + [[nodiscard]] size_t Serialize(uint8_t *buf, size_t buf_len) const; + static std::shared_ptr LoadFrom(yacl::ByteContainerView in); + + [[nodiscard]] std::map ListParams() const override { + return { + {"s_", s_.ToString()}, {"p_", p_.ToString()}, {"L_", L_.ToString()}}; + } + + [[nodiscard]] MPInt getS() const { return this->s_; } + + [[nodiscard]] MPInt getP() const { return this->p_; } + + [[nodiscard]] MPInt getL() const { return this->L_; } +}; + +class PublicParameters : public spi::KeySketch { + private: + MPInt N, M[2]; + + public: + int64_t k_M = 128; + int64_t k_r = 160; + int64_t k_0 = 4096; + std::vector ADDONES; + std::vector ONES; + std::vector NEGS; + PublicParameters() = default; + + PublicParameters(int64_t k_0, int64_t k_r, int64_t k_M, const MPInt &N); + + PublicParameters(int64_t k_0, int64_t k_r, int64_t k_M, const MPInt &N, + const std::vector &ADDONES, + const std::vector &ONES, + const std::vector &NEGS); + [[nodiscard]] yacl::Buffer Serialize2Buffer() const; + [[nodiscard]] size_t Serialize(uint8_t *buf, size_t buf_len) const; + static std::shared_ptr LoadFrom(yacl::ByteContainerView in); + + [[nodiscard]] size_t Maxsize() const { return k_M - 1; } + + [[nodiscard]] MPInt *MessageSpace() { return M; } + + [[nodiscard]] std::map ListParams() const override { + return {{"key_size", fmt::to_string(k_0)}, + {"random_number_size", fmt::to_string(k_r)}, + {"message_space_size", M[1].ToString()}}; + } + + void Init(); + + [[nodiscard]] MPInt getN() const { return N; } +}; + +class ItemTool : public spi::ItemToolScalarSketch { + public: + [[nodiscard]] Plaintext Clone(const Plaintext &pt) const override; + [[nodiscard]] Ciphertext Clone(const Ciphertext &ct) const override; +}; + +} // namespace heu::algos::ishe diff --git a/heu/algorithms/incubator/ishe/decryptor.cc b/heu/algorithms/incubator/ishe/decryptor.cc new file mode 100644 index 0000000..bb72781 --- /dev/null +++ b/heu/algorithms/incubator/ishe/decryptor.cc @@ -0,0 +1,41 @@ +// Copyright 2024 CyberChangAn Group, Xidian University. +// +// 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 "heu/algorithms/incubator/ishe/decryptor.h" + +namespace heu::algos::ishe { + +void Decryptor::Decrypt(const Ciphertext &ct, Plaintext *out) const { + *out = Decrypt(ct); +} + +Plaintext Decryptor::Decrypt(const Ciphertext &ct) const { + /** + * decrypt + * m: plaintext + * d: s's exponent + */ + MPInt tmp; + MPInt::PowMod(sk_->getS(), ct.d_, pk_->getN(), &tmp); // m = s^d + MPInt::InvertMod(tmp, pk_->getN(), &tmp); // (s^d)^-1 + MPInt::MulMod(ct.n_, tmp, pk_->getN(), &tmp); // (s^d)^-1 * m mod N + MPInt::Mod(tmp, sk_->getP(), &tmp); + MPInt::Mod(tmp, sk_->getL(), &tmp); // (((s^d)^-1 * m mod N ) mod p) mod L + if (tmp < sk_->getL() / MPInt(2)) { // case 1 : m' < L/2 + return tmp; + } + return tmp - sk_->getL(); // case 2 : else +} + +} // namespace heu::algos::ishe diff --git a/heu/algorithms/incubator/ishe/decryptor.h b/heu/algorithms/incubator/ishe/decryptor.h new file mode 100644 index 0000000..76da55d --- /dev/null +++ b/heu/algorithms/incubator/ishe/decryptor.h @@ -0,0 +1,37 @@ +// Copyright 2024 CyberChangAn Group, Xidian University. +// +// 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. + +#pragma once + +#include + +#include "heu/algorithms/incubator/ishe/base.h" +#include "heu/spi/he/sketches/scalar/decryptor.h" + +namespace heu::algos::ishe { + +class Decryptor : public spi::DecryptorScalarSketch { + public: + void Decrypt(const Ciphertext &ct, Plaintext *out) const override; + [[nodiscard]] Plaintext Decrypt(const Ciphertext &ct) const override; + + Decryptor(std::shared_ptr sk, std::shared_ptr pk) + : sk_(std::move(sk)), pk_(std::move(pk)) {} + + private: + std::shared_ptr sk_; + std::shared_ptr pk_; +}; + +} // namespace heu::algos::ishe diff --git a/heu/algorithms/incubator/ishe/encryptor.cc b/heu/algorithms/incubator/ishe/encryptor.cc new file mode 100644 index 0000000..4c41e73 --- /dev/null +++ b/heu/algorithms/incubator/ishe/encryptor.cc @@ -0,0 +1,64 @@ +// Copyright 2024 CyberChangAn Group, Xidian University. +// +// 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 "heu/algorithms/incubator/ishe/encryptor.h" + +#include + +namespace heu::algos::ishe { + +Ciphertext Encryptor::EncryptZeroT() const { + return Encrypt(MPInt(0), MPInt(1)); +} + +template +Ciphertext Encryptor::EncryptImpl(const Plaintext &m, const MPInt &d, + std::string *audit_out) const { + YACL_ENFORCE(m < pp_->MessageSpace()[1] && m >= pp_->MessageSpace()[0], + "Plaintext {} is too large, cannot encrypt.", m.ToString()); + MPInt r, r1; + MPInt::RandomExactBits(pp_->k_r, &r); // r = {0,1}^k_r + MPInt::RandomExactBits(pp_->k_0, &r1); // r' ={0,1}^k_0 + MPInt m1 = sk_->getS().PowMod(d, pp_->getN()); // m' = s^d + m1 *= (r * sk_->getL() + m); // m' = s*(rL+m) + m1 = m1.MulMod((MPInt(1) + r1 * sk_->getP()), pp_->getN()); + // m' = s*(rL+m)*(1+r'p) mod N + if constexpr (audit) { + YACL_ENFORCE(audit_out != nullptr); + *audit_out = + fmt::format("r:{}\n r':{}\n", r.ToHexString(), r1.ToHexString()); + } + return Ciphertext(m1, d); +} + +Ciphertext Encryptor::Encrypt(const Plaintext &m, const MPInt &d) const { + return EncryptImpl(m, d, nullptr); +} + +Ciphertext Encryptor::Encrypt(const Plaintext &m) const { + return Encrypt(m, MPInt(1)); +} + +void Encryptor::Encrypt(const Plaintext &m, Ciphertext *out) const { + *out = Encrypt(m); +} + +void Encryptor::EncryptWithAudit(const Plaintext &m, Ciphertext *ct_out, + std::string *audit_out) const { + *ct_out = EncryptImpl(m, 1_mp, audit_out); + audit_out->append( + fmt::format("pt:{}\n ct:{}", m.ToString(), ct_out->n_.ToString())); +} + +} // namespace heu::algos::ishe diff --git a/heu/algorithms/incubator/ishe/encryptor.h b/heu/algorithms/incubator/ishe/encryptor.h new file mode 100644 index 0000000..8f6b349 --- /dev/null +++ b/heu/algorithms/incubator/ishe/encryptor.h @@ -0,0 +1,48 @@ +// Copyright 2024 CyberChangAn Group, Xidian University. +// +// 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. + +#pragma once + +#include + +#include "heu/algorithms/incubator/ishe/base.h" +#include "heu/spi/he/sketches/scalar/phe/encryptor.h" + +namespace heu::algos::ishe { + +class Encryptor : public spi::PheEncryptorScalarSketch { + public: + explicit Encryptor(const std::shared_ptr &pk, + const std::shared_ptr &sk) + : pp_(pk), sk_(sk) {} + + [[nodiscard]] Ciphertext EncryptZeroT() const override; + + [[nodiscard]] Ciphertext Encrypt(const Plaintext &m) const override; + [[nodiscard]] Ciphertext Encrypt(const Plaintext &m, const MPInt &d) const; + + void Encrypt(const Plaintext &plaintext, Ciphertext *out) const override; + + void EncryptWithAudit(const Plaintext &plaintext, Ciphertext *ct_out, + std::string *audit_out) const override; + + private: + template + Ciphertext EncryptImpl(const Plaintext &m, const MPInt &d, + std::string *audit_str) const; + std::shared_ptr pp_; + std::shared_ptr sk_; +}; + +} // namespace heu::algos::ishe diff --git a/heu/algorithms/incubator/ishe/evaluator.cc b/heu/algorithms/incubator/ishe/evaluator.cc new file mode 100644 index 0000000..15a2fe2 --- /dev/null +++ b/heu/algorithms/incubator/ishe/evaluator.cc @@ -0,0 +1,150 @@ +// Copyright 2024 CyberChangAn Group, Xidian University. +// +// 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 "heu/algorithms/incubator/ishe/evaluator.h" + +#include + +#include "heu/spi/he/encryptor.h" + +namespace heu::algos::ishe { + +Plaintext Evaluator::Negate(const Plaintext &a) const { return -a; } + +void Evaluator::NegateInplace(Plaintext *a) const { a->NegateInplace(); } + +Ciphertext Evaluator::Negate(const Ciphertext &a) const { + // [[-1]] * a + MPInt r; + MPInt::RandomLtN(MPInt(pp_->NEGS.size()), &r); + Ciphertext neg = Ciphertext(pp_->NEGS[r.Get()], {0_mp}); + MulInplace(&neg, a); + return neg; +} + +void Evaluator::NegateInplace(Ciphertext *a) const { *a = Negate(*a); } + +Plaintext Evaluator::Add(const Plaintext &a, const Plaintext &b) const { + return a + b; +} + +Ciphertext Evaluator::Add(const Ciphertext &a, const Plaintext &b) const { + MPInt r; + Ciphertext one; + if (a.d_ == MPInt(1)) { + MPInt::RandomLtN(MPInt(pp_->ONES.size()), &r); + one = Ciphertext(pp_->ONES[r.Get()], {1_mp}); + } else { + r = a.d_ - MPInt(1); + one = Ciphertext(pp_->ADDONES[r.Get()], a.d_); + } + const auto m = Mul(one, b); + return Ciphertext(a.n_ + m.n_, a.d_); +} + +Ciphertext Evaluator::Add(const Ciphertext &a, const Ciphertext &b) const { + Ciphertext m1, m2; + // make sure d_m1 is bigger than d_m2 + if (a.d_ == b.d_) { // d_1 = d_2 + m1 = Ciphertext(a.n_ + b.n_, a.d_); + return m1; + } + if (a.d_ > b.d_) { // d_1 > d_2, + m1 = a; + m2 = b; + } else { // d_2 > d_1 + m2 = a; + m1 = b; + } + const MPInt d = m1.d_ - m2.d_; + const auto one = Ciphertext(pp_->ADDONES[d.Get() - 1], d); + m2 = this->Mul(m2, one); + return Add(m1, m2.n_); +} + +void Evaluator::AddInplace(Ciphertext *a, const Plaintext &b) const { + *a = Add(*a, b); +} + +void Evaluator::AddInplace(Ciphertext *a, const Ciphertext &b) const { + *a = Add(*a, b); +} + +Ciphertext Evaluator::Mul(const Ciphertext &a, const Ciphertext &b) const { + Ciphertext res; + MPInt::MulMod(a.n_, b.n_, pp_->getN(), &res.n_); + res.d_ = a.d_ + b.d_; + return res; +} + +Plaintext Evaluator::Mul(const Plaintext &a, const Plaintext &b) const { + Plaintext res = a * b; + return res; +} + +Ciphertext Evaluator::Mul(const Ciphertext &a, const Plaintext &b) const { + Ciphertext res; + if (b >= Plaintext(0)) { + MPInt::MulMod(a.n_, b, pp_->getN(), &res.n_); + } else { + MPInt::MulMod(Negate(a).n_, -b, pp_->getN(), &res.n_); + } + res.d_ = a.d_; + return res; +} + +void Evaluator::MulInplace(Ciphertext *a, const Plaintext &b) const { + *a = Mul(*a, b); +} + +void Evaluator::MulInplace(Ciphertext *a, const Ciphertext &b) const { + *a = Mul(*a, b); +} + +Plaintext Evaluator::Square(const Plaintext &a) const { return Mul(a, a); } + +void Evaluator::SquareInplace(Plaintext *a) const { *a = Mul(*a, *a); } + +Ciphertext Evaluator::Square(const Ciphertext &ciphertext) const { + return Ciphertext(Square(ciphertext.n_), ciphertext.d_.Mul(2)); +} + +void Evaluator::SquareInplace(Ciphertext *ciphertext) const { + *ciphertext = Square(*ciphertext); +} + +Plaintext Evaluator::Pow(const Plaintext &a, int64_t exponent) const { + return a.Pow(exponent); +} + +void Evaluator::PowInplace(Plaintext *a, int64_t exponent) const { + a->PowInplace(exponent); +} + +Ciphertext Evaluator::Pow(const Ciphertext &ciphertext, int64_t int64) const { + return Ciphertext(ciphertext.n_.Pow(int64), ciphertext.d_.Mul(int64)); +} + +void Evaluator::PowInplace(Ciphertext *ciphertext, int64_t int64) const { + *ciphertext = Pow(*ciphertext, int64); +} + +void Evaluator::Randomize(Ciphertext *ct) const { + MPInt r; + MPInt::RandomLtN(MPInt(pp_->ONES.size()), &r); + const Ciphertext one = Ciphertext(pp_->ONES[r.Get()], MPInt(1)); + MulInplace(ct, one); +} + +} // namespace heu::algos::ishe diff --git a/heu/algorithms/incubator/ishe/evaluator.h b/heu/algorithms/incubator/ishe/evaluator.h new file mode 100644 index 0000000..a15ba73 --- /dev/null +++ b/heu/algorithms/incubator/ishe/evaluator.h @@ -0,0 +1,69 @@ +// Copyright 2024 CyberChangAn Group, Xidian University. +// +// 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. + +#pragma once + +#include +#include + +#include "heu/algorithms/incubator/ishe/base.h" +#include "heu/spi/he/sketches/scalar/phe/word_evaluator.h" + +namespace heu::algos::ishe { + +class Evaluator + : public spi::PheWordEvaluatorScalarSketch { + public: + explicit Evaluator(const std::shared_ptr &pk) : pp_(pk) {} + + [[nodiscard]] Plaintext Negate(const Plaintext &a) const override; + void NegateInplace(Plaintext *a) const override; + [[nodiscard]] Ciphertext Negate(const Ciphertext &a) const override; + void NegateInplace(Ciphertext *a) const override; + + [[nodiscard]] Plaintext Add(const Plaintext &a, + const Plaintext &b) const override; + [[nodiscard]] Ciphertext Add(const Ciphertext &a, + const Plaintext &b) const override; + [[nodiscard]] Ciphertext Add(const Ciphertext &a, + const Ciphertext &b) const override; + void AddInplace(Ciphertext *a, const Plaintext &b) const override; + void AddInplace(Ciphertext *a, const Ciphertext &b) const override; + + [[nodiscard]] Plaintext Mul(const Plaintext &a, + const Plaintext &b) const override; + [[nodiscard]] Ciphertext Mul(const Ciphertext &a, + const Plaintext &b) const override; + [[nodiscard]] Ciphertext Mul(const Ciphertext &a, + const Ciphertext &b) const override; + void MulInplace(Ciphertext *a, const Plaintext &b) const override; + void MulInplace(Ciphertext *a, const Ciphertext &b) const override; + + [[nodiscard]] Plaintext Square(const Plaintext &a) const override; + void SquareInplace(Plaintext *a) const override; + [[nodiscard]] Ciphertext Square(const Ciphertext &) const override; + void SquareInplace(Ciphertext *) const override; + [[nodiscard]] Plaintext Pow(const Plaintext &a, + int64_t exponent) const override; + void PowInplace(Plaintext *a, int64_t exponent) const override; + [[nodiscard]] Ciphertext Pow(const Ciphertext &, int64_t) const override; + void PowInplace(Ciphertext *, int64_t) const override; + + void Randomize(Ciphertext *ct) const override; + + private: + std::shared_ptr pp_; +}; + +} // namespace heu::algos::ishe diff --git a/heu/algorithms/incubator/ishe/he_kit.cc b/heu/algorithms/incubator/ishe/he_kit.cc new file mode 100644 index 0000000..08628b1 --- /dev/null +++ b/heu/algorithms/incubator/ishe/he_kit.cc @@ -0,0 +1,151 @@ +// Copyright 2024 CyberChangAn Group, Xidian University. +// +// 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 "heu/algorithms/incubator/ishe/he_kit.h" + +#include + +#include +#include + +#include "yacl/utils/serializer.h" + +#include "heu/spi/he/he.h" + +DEFINE_ARG_int64(k0); +DEFINE_ARG_int64(kr); +DEFINE_ARG_int64(kM); + +namespace heu::algos::ishe { + +static const std::string kLibName = "iSHE"; + +std::string HeKit::GetLibraryName() const { return kLibName; } + +spi::Schema HeKit::GetSchema() const { return spi::Schema::iSHE; } + +std::string HeKit::ToString() const { + return fmt::format("{} schema from {} lib", GetSchema(), GetLibraryName()); +} + +void HeKit::InitOnes(int64_t k_0, int64_t k_r, int64_t k_M, const MPInt &N, + std::vector *ADDONES, std::vector *ONES, + std::vector *NEGS) { + std::shared_ptr tmp = + std::make_shared(k_0, k_r, k_M, N); + Encryptor et = Encryptor(tmp, sk_); + for (int i = 1; i <= 100; ++i) { + ADDONES->emplace_back(et.Encrypt(MPInt(1), MPInt(i)).n_); + } + for (int i = 1; i <= 50; ++i) { + ONES->emplace_back(et.Encrypt(MPInt(1), MPInt(1)).n_); + } + for (int i = 1; i <= 20; ++i) { + NEGS->emplace_back(et.Encrypt(MPInt(-1), MPInt(0)).n_); + } +} + +size_t HeKit::Serialize(uint8_t *, size_t) const { + // nothing to serialize + return 0; +} + +bool HeKit::Check(spi::Schema schema, const spi::SpiArgs &) { + return schema == spi::Schema::iSHE; +} + +size_t HeKit::Serialize(spi::HeKeyType key_type, uint8_t *buf, + const size_t buf_len) const { + switch (key_type) { + case spi::HeKeyType::SecretKey: + return sk_->Serialize(buf, buf_len); + case spi::HeKeyType::PublicKey: + return pk_->Serialize(buf, buf_len); + default: + YACL_THROW("Unknown key type {}", key_type); + } +} + +std::unique_ptr HeKit::CreateParams(spi::Schema schema, int64_t k_0, + int64_t k_r, int64_t k_M) { + YACL_ENFORCE(schema == spi::Schema::iSHE, "Schema {} not supported by {}", + schema, kLibName); + YACL_ENFORCE(k_0 > k_r && k_r > k_M && k_M > 0, + "do not obey the rule of params"); + auto kit = std::make_unique(); + kit->GenPkSk(k_0, k_r, k_M); + kit->InitOperators(); + return kit; +} + +std::unique_ptr HeKit::Create(const spi::Schema schema, + const spi::SpiArgs &args) { + YACL_ENFORCE(schema == spi::Schema::iSHE, "Schema {} not supported by {}", + schema, kLibName); + YACL_ENFORCE( + args.Exist(spi::ArgGenNewPkSk) || args.Exist(spi::ArgPkFrom), + "Neither ArgGenNewPkSk nor ArgPkFrom is set, you must set one of them"); + + auto kit = std::make_unique(); + if (args.GetOptional(spi::ArgGenNewPkSk) == true) { + // choose random prime p&q, k_0 bits + const auto k_0 = args.GetOrDefault(Argk0, 4096); + const auto k_r = args.GetOrDefault(Argkr, 160); + const auto k_M = args.GetOrDefault(ArgkM, 128); + kit->GenPkSk(k_0, k_r, k_M); + + } else { + kit->pk_ = PublicParameters::LoadFrom(args.GetRequired(spi::ArgPkFrom)); + if (args.Exist(spi::ArgSkFrom)) { + kit->sk_ = SecretKey::LoadFrom(args.GetRequired(spi::ArgSkFrom)); + } + } + kit->InitOperators(); + return kit; +} + +void HeKit::GenPkSk(int64_t k_0, int64_t k_r, int64_t k_M) { + MPInt p, q, s, L; + // choose random prime p&q, k_0 bits + std::vector ADDONES, ONES, NEGS; + MPInt::RandPrimeOver(k_0, &p); + MPInt::RandPrimeOver(k_0, &q); + // N = p * q + MPInt N = p * q; + // choose s mod N < N + MPInt::RandomLtN(N, &s); + // choose random L , k_r bits + MPInt::RandomExactBits(k_r, &L); + // init key pairs + sk_ = std::make_shared(s, p, L); + InitOnes(k_0, k_r, k_M, N, &ADDONES, &ONES, &NEGS); + pk_ = + std::make_shared(k_0, k_r, k_M, N, ADDONES, ONES, NEGS); +} + +void HeKit::InitOperators() { + item_tool_ = std::make_shared(); + + if (pk_) { + word_evaluator_ = std::make_shared(pk_); + if (sk_) { + encryptor_ = std::make_shared(pk_, sk_); + decryptor_ = std::make_shared(sk_, pk_); + } + } +} + +REGISTER_HE_LIBRARY(kLibName, 1, HeKit::Check, HeKit::Create); + +} // namespace heu::algos::ishe diff --git a/heu/algorithms/incubator/ishe/he_kit.h b/heu/algorithms/incubator/ishe/he_kit.h new file mode 100644 index 0000000..c5dce8d --- /dev/null +++ b/heu/algorithms/incubator/ishe/he_kit.h @@ -0,0 +1,67 @@ +// Copyright 2024 CyberChangAn Group, Xidian University. +// +// 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. + +#pragma once + +#include + +#include "heu/algorithms/incubator/ishe/base.h" +#include "heu/algorithms/incubator/ishe/decryptor.h" +#include "heu/algorithms/incubator/ishe/encryptor.h" +#include "heu/algorithms/incubator/ishe/evaluator.h" +#include "heu/spi/he/sketches/common/he_kit.h" +#include "heu/spi/he/sketches/scalar/phe/he_kit.h" + +DECLARE_ARG_int64(k0); +DECLARE_ARG_int64(kr); +DECLARE_ARG_int64(kM); + +namespace heu::algos::ishe { +class HeKit + : public spi::PheHeKitSketch { + public: + HeKit() = default; + [[nodiscard]] std::string GetLibraryName() const override; + [[nodiscard]] spi::Schema GetSchema() const override; + + [[nodiscard]] std::string ToString() const override; + + [[nodiscard]] size_t MaxPlaintextBits() const override { + return pk_->Maxsize(); + } + + size_t Serialize(uint8_t *buf, size_t buf_len) const override; + size_t Serialize(spi::HeKeyType key_type, uint8_t *buf, + size_t buf_len) const override; + + void GenPkSk(int64_t k_0, int64_t k_r, int64_t k_M); + static std::unique_ptr CreateParams(spi::Schema schema, int64_t k_0, + int64_t k_r, int64_t k_M); + static std::unique_ptr Create(spi::Schema schema, + const spi::SpiArgs &args); + + static bool Check(spi::Schema schema, const spi::SpiArgs &); + + std::shared_ptr getSk() { return this->sk_; } + + std::shared_ptr getPk() { return this->pk_; } + + private: + void InitOperators(); + void InitOnes(int64_t k_0, int64_t k_r, int64_t k_M, const MPInt &N, + std::vector *ADDONES, std::vector *ONES, + std::vector *NEGS); +}; + +} // namespace heu::algos::ishe diff --git a/heu/algorithms/incubator/ishe/ishe_test.cc b/heu/algorithms/incubator/ishe/ishe_test.cc new file mode 100644 index 0000000..ead9d2b --- /dev/null +++ b/heu/algorithms/incubator/ishe/ishe_test.cc @@ -0,0 +1,243 @@ +// Copyright 2024 CyberChangAn Group, Xidian University. +// +// 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 "gtest/gtest.h" + +#include "heu/algorithms/incubator/ishe/he_kit.h" + +namespace heu::algos::ishe::test { +class iSHETest : public testing::Test { + protected: + std::unique_ptr hekit_; + std::shared_ptr secretkey_; + std::shared_ptr publickey_; + std::shared_ptr encryptor_; + std::shared_ptr decryptor_; + std::shared_ptr evaluator_; + std::shared_ptr itemTool_ = std::make_shared(); + + void SetUp() override { + hekit_ = HeKit::CreateParams(spi::Schema::iSHE, 4096, 160, 128); + secretkey_ = hekit_->getSk(); + publickey_ = hekit_->getPk(); + encryptor_ = std::make_shared(publickey_, secretkey_); + decryptor_ = std::make_shared(secretkey_, publickey_); + evaluator_ = std::make_shared(publickey_); + } +}; + +TEST_F(iSHETest, ItomToolEvaluator) { + uint8_t buff[1024], buff2[4096]; + Plaintext pt = Plaintext(1000); + Ciphertext ct = encryptor_->Encrypt(pt); + auto pt_serialization = itemTool_->Serialize(pt, buff, size_t(1024)); + auto ct_serialization = itemTool_->Serialize(ct, buff2, size_t(4096)); + Plaintext p1; + yacl::ByteContainerView bc1 = yacl::ByteContainerView(buff, pt_serialization); + p1 = itemTool_->DeserializePT(bc1); + Ciphertext c1; + yacl::ByteContainerView bc2 = + yacl::ByteContainerView(buff2, ct_serialization); + c1 = itemTool_->DeserializeCT(bc2); + EXPECT_EQ(p1, pt); + EXPECT_EQ(c1.n_, ct.n_); + EXPECT_EQ(c1.d_, ct.d_); + + Plaintext pt1 = itemTool_->Clone(pt); + EXPECT_EQ(pt, pt1); + Ciphertext ct2 = itemTool_->Clone(ct); + EXPECT_EQ(ct, ct2); +} + +TEST_F(iSHETest, serializeEvaluate) { + // Serialize publicparam + yacl::Buffer pk_buf = publickey_->Serialize2Buffer(); + // Serialize secretKey + yacl::Buffer sk_buf = secretkey_->Serialize2Buffer(); + // operation ct + Ciphertext ct_pos = encryptor_->Encrypt(MPInt(100000)); + Ciphertext ct_zero = encryptor_->Encrypt(MPInt(0)); + Ciphertext ct_neg = encryptor_->Encrypt(MPInt(-123456)); + yacl::Buffer pos_buffer = ct_pos.Serialize(); + yacl::Buffer zero_buffer = ct_zero.Serialize(); + yacl::Buffer neg_buffer = ct_neg.Serialize(); + // Deserialize and compare + std::shared_ptr pp = PublicParameters::LoadFrom(pk_buf); + EXPECT_EQ(pp->getN(), publickey_->getN()); + EXPECT_EQ(pp->k_0, publickey_->k_0); + EXPECT_EQ(pp->k_r, publickey_->k_r); + EXPECT_EQ(pp->k_M, publickey_->k_M); + EXPECT_EQ(pp->ONES, publickey_->ONES); + EXPECT_EQ(pp->ADDONES, publickey_->ADDONES); + EXPECT_EQ(pp->NEGS, publickey_->NEGS); + // deserialze cts + Ciphertext pos_from_buf, zero_from_buf, neg_from_buf; + pos_from_buf.Deserialize(pos_buffer); + zero_from_buf.Deserialize(zero_buffer); + neg_from_buf.Deserialize(neg_buffer); + // operations + Ciphertext o1, o2, o3, o4, o5; + o1 = evaluator_->Add(pos_from_buf, zero_from_buf); + o2 = evaluator_->Add(neg_from_buf, zero_from_buf); + o3 = evaluator_->Add(pos_from_buf, neg_from_buf); + o4 = evaluator_->Mul(pos_from_buf, zero_from_buf); + o5 = evaluator_->Mul(pos_from_buf, neg_from_buf); + // Serialize results + yacl::Buffer bo1 = o1.Serialize(); + yacl::Buffer bo2 = o2.Serialize(); + yacl::Buffer bo3 = o3.Serialize(); + yacl::Buffer bo4 = o4.Serialize(); + yacl::Buffer bo5 = o5.Serialize(); + // Deserialize sk + std::shared_ptr sk = SecretKey::LoadFrom(sk_buf); + EXPECT_EQ(sk->getS(), secretkey_->getS()); + EXPECT_EQ(sk->getP(), secretkey_->getP()); + EXPECT_EQ(sk->getL(), secretkey_->getL()); + // Deserialize results + o1.Deserialize(bo1); + o2.Deserialize(bo2); + o3.Deserialize(bo3); + o4.Deserialize(bo4); + o5.Deserialize(bo5); + EXPECT_EQ(decryptor_->Decrypt(o1), MPInt(100000)); + EXPECT_EQ(decryptor_->Decrypt(o2), MPInt(-123456)); + EXPECT_EQ(decryptor_->Decrypt(o3), MPInt(-23456)); + EXPECT_EQ(decryptor_->Decrypt(o4), MPInt(0)); + EXPECT_EQ(decryptor_->Decrypt(o5), MPInt(-123456) * MPInt(100000)); +} + +TEST_F(iSHETest, OperationEvaluate) { + Plaintext m0 = Plaintext(12345); + Plaintext m1 = Plaintext(-20000); + Plaintext m3 = Plaintext(0); + Ciphertext c0 = encryptor_->Encrypt(m0); + Ciphertext c1 = encryptor_->Encrypt(m1); + Ciphertext c2 = encryptor_->Encrypt(-m0); + Ciphertext c3 = encryptor_->Encrypt(m3); + EXPECT_EQ(m0, Plaintext(12345)); + + Plaintext plain; + Ciphertext res; + + // evaluate add + res = evaluator_->Add(c0, c0); + decryptor_->Decrypt(res, &plain); + EXPECT_EQ(plain, Plaintext(12345 * 2)); + res = evaluator_->Add(c1, c1); + decryptor_->Decrypt(res, &plain); + EXPECT_EQ(plain, Plaintext(-20000 * 2)); + res = evaluator_->Add(c0, c1); + decryptor_->Decrypt(res, &plain); + EXPECT_EQ(plain, Plaintext(12345 - 20000)); + res = evaluator_->Add(c1, m3); + decryptor_->Decrypt(res, &plain); + EXPECT_EQ(plain, Plaintext(-20000)); + res = evaluator_->Add(c0, m1); + decryptor_->Decrypt(res, &plain); + EXPECT_EQ(plain, Plaintext(12345 - 20000)); + res = evaluator_->Add(c1, m0); + decryptor_->Decrypt(res, &plain); + EXPECT_EQ(plain, Plaintext(12345 - 20000)); + res = evaluator_->Add(c2, c0); + decryptor_->Decrypt(res, &plain); + EXPECT_EQ(plain, Plaintext(0)); + + Plaintext m2 = Plaintext(123); + Ciphertext c4 = encryptor_->Encrypt(m2); + Ciphertext c5 = encryptor_->Encrypt(-m2); + res = evaluator_->Mul(c0, c0); + decryptor_->Decrypt(res, &plain); + EXPECT_EQ(plain, Plaintext(12345 * 12345)); + res = evaluator_->Mul(c1, c1); + decryptor_->Decrypt(res, &plain); + EXPECT_EQ(plain, Plaintext(20000 * 20000)); + res = evaluator_->Mul(c0, m0); + decryptor_->Decrypt(res, &plain); + EXPECT_EQ(plain, Plaintext(12345 * 12345)); + res = evaluator_->Mul(c4, c4); + res = evaluator_->Mul(res, c4); + decryptor_->Decrypt(res, &plain); + EXPECT_EQ(plain, Plaintext(123 * 123 * 123)); + res = evaluator_->Mul(c1, m0); + decryptor_->Decrypt(res, &plain); + EXPECT_EQ(plain, Plaintext(-20000 * 12345)); + res = evaluator_->Mul(c1, m1); + decryptor_->Decrypt(res, &plain); + EXPECT_EQ(plain, Plaintext(20000 * 20000)); + + Ciphertext Zero = encryptor_->EncryptZeroT(); + decryptor_->Decrypt(Zero, &plain); + EXPECT_EQ(plain, MPInt(0)); + evaluator_->Randomize(&c1); + decryptor_->Decrypt(c1, &plain); + EXPECT_EQ(plain, MPInt(-20000)); + + evaluator_->MulInplace(&c0, m1); + decryptor_->Decrypt(c0, &plain); + EXPECT_EQ(plain, MPInt(-20000 * 12345)); + + evaluator_->MulInplace(&c1, c1); + decryptor_->Decrypt(c1, &plain); + EXPECT_EQ(plain, MPInt(20000 * 20000)); + + Plaintext pt0 = Plaintext(12345); + Plaintext pt1 = Plaintext(20000); + Ciphertext ct0 = encryptor_->Encrypt(pt0); + Ciphertext ct1 = encryptor_->Encrypt(pt1); + evaluator_->AddInplace(&ct0, pt1); // call add, test Inplace function + decryptor_->Decrypt(ct0, &plain); + EXPECT_EQ(plain, MPInt(20000 + 12345)); + evaluator_->AddInplace(&ct0, ct1); + decryptor_->Decrypt(ct0, &plain); + EXPECT_EQ(plain, MPInt(20000 + 12345 + 20000)); + // m < pp_->MessageSpace()[1] && m >= pp_->MessageSpace()[0] + Plaintext pt_min = Plaintext(publickey_->MessageSpace()[0]); + Plaintext pt_max = Plaintext(publickey_->MessageSpace()[1] - 1_mp); + Ciphertext ct_max = encryptor_->Encrypt(pt_max); + Ciphertext ct_min = encryptor_->Encrypt(pt_min); + Plaintext tmp = decryptor_->Decrypt(ct_min); + EXPECT_EQ(tmp, pt_min); + tmp = decryptor_->Decrypt(ct_max); + EXPECT_EQ(tmp, pt_max); +} + +TEST_F(iSHETest, NegateEvalutate) { + Plaintext p1 = Plaintext(123456); + evaluator_->NegateInplace(&p1); + EXPECT_EQ(p1, MPInt(-123456)); // p1 = -123456 + Plaintext p2 = Plaintext(123456); + p2 = evaluator_->Negate(p2); + EXPECT_EQ(p2, MPInt(-123456)); // p2 = -123456 + + Plaintext plain; + evaluator_->NegateInplace(&p1); // p1 = -123456 + Ciphertext c1 = encryptor_->Encrypt(p2); + evaluator_->NegateInplace(&c1); + decryptor_->Decrypt(c1, &plain); + EXPECT_EQ(plain, MPInt(123456)); +} + +TEST_F(iSHETest, PlaintextEvaluate) { + Plaintext p1 = Plaintext(2000); + Plaintext p2 = evaluator_->Square(p1); + evaluator_->SquareInplace(&p1); + EXPECT_EQ(p1, MPInt(2000 * 2000)); + EXPECT_EQ(p1, p2); + + Plaintext p3 = Plaintext(200); + Plaintext p4 = evaluator_->Pow(p3, 5); + evaluator_->PowInplace(&p3, 5); + EXPECT_EQ(p3, p4); +} +} // namespace heu::algos::ishe::test diff --git a/heu/spi/he/schema.h b/heu/spi/he/schema.h index b408b10..fcb733d 100644 --- a/heu/spi/he/schema.h +++ b/heu/spi/he/schema.h @@ -34,6 +34,7 @@ enum class Schema { MockBfv, // mock of FeatureSet::WordFHE MockCkks, // mock of FeatureSet::ApproxFHE + iSHE, Paillier, OU, ElGamal, @@ -51,6 +52,7 @@ inline const std::unordered_map kSchema2String = { {Schema::MockBfv, "mock_bfv"}, {Schema::MockCkks, "mock_ckks"}, + {Schema::iSHE, "iSHE"}, {Schema::Paillier, "paillier"}, {Schema::OU, "okamoto–uchiyama"}, {Schema::ElGamal, "elgamal"},