binfhe_bindings.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. //==================================================================================
  2. // BSD 2-Clause License
  3. //
  4. // Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
  5. //
  6. // All rights reserved.
  7. //
  8. // Author TPOC: contact@openfhe.org
  9. //
  10. // Redistribution and use in source and binary forms, with or without
  11. // modification, are permitted provided that the following conditions are met:
  12. //
  13. // 1. Redistributions of source code must retain the above copyright notice, this
  14. // list of conditions and the following disclaimer.
  15. //
  16. // 2. Redistributions in binary form must reproduce the above copyright notice,
  17. // this list of conditions and the following disclaimer in the documentation
  18. // and/or other materials provided with the distribution.
  19. //
  20. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  23. // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  24. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  26. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  27. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. //==================================================================================
  31. #include "binfhe_bindings.h"
  32. #include <pybind11/operators.h>
  33. #include "openfhe.h"
  34. #include "binfhecontext.h"
  35. #include "binfhecontext_docs.h"
  36. #include "binfhecontext_wrapper.h"
  37. #include "cereal/archives/binary.hpp"
  38. // #include "cereal/archives/portable_binary.hpp"
  39. // #include "core/utils/serial.h"
  40. using namespace lbcrypto;
  41. namespace py = pybind11;
  42. void bind_binfhe_enums(py::module &m) {
  43. py::enum_<BINFHE_PARAMSET>(m, "BINFHE_PARAMSET")
  44. .value("TOY", BINFHE_PARAMSET::TOY)
  45. .value("MEDIUM", BINFHE_PARAMSET::MEDIUM)
  46. .value("STD128_LMKCDEY", BINFHE_PARAMSET::STD128_LMKCDEY)
  47. .value("STD128_AP", BINFHE_PARAMSET::STD128_AP)
  48. .value("STD128", BINFHE_PARAMSET::STD128)
  49. .value("STD192", BINFHE_PARAMSET::STD192)
  50. .value("STD256", BINFHE_PARAMSET::STD256)
  51. .value("STD128Q", BINFHE_PARAMSET::STD128Q)
  52. .value("STD128Q_LMKCDEY", BINFHE_PARAMSET::STD128Q_LMKCDEY)
  53. .value("STD192Q", BINFHE_PARAMSET::STD192Q)
  54. .value("STD256Q", BINFHE_PARAMSET::STD256Q)
  55. .value("STD128_3", BINFHE_PARAMSET::STD128_3)
  56. .value("STD128_3_LMKCDEY", BINFHE_PARAMSET::STD128_3_LMKCDEY)
  57. .value("STD128Q_3", BINFHE_PARAMSET::STD128Q_3)
  58. .value("STD128Q_3_LMKCDEY", BINFHE_PARAMSET::STD128Q_3_LMKCDEY)
  59. .value("STD192Q_3", BINFHE_PARAMSET::STD192Q_3)
  60. .value("STD256Q_3", BINFHE_PARAMSET::STD256Q_3)
  61. .value("STD128_4", BINFHE_PARAMSET::STD128_4)
  62. .value("STD128_4_LMKCDEY", BINFHE_PARAMSET::STD128_4_LMKCDEY)
  63. .value("STD128Q_4", BINFHE_PARAMSET::STD128Q_4)
  64. .value("STD128Q_4_LMKCDEY", BINFHE_PARAMSET::STD128Q_4_LMKCDEY)
  65. .value("STD192Q_4", BINFHE_PARAMSET::STD192Q_4)
  66. .value("STD256Q_4", BINFHE_PARAMSET::STD256Q_4)
  67. .value("SIGNED_MOD_TEST", BINFHE_PARAMSET::SIGNED_MOD_TEST);
  68. m.attr("TOY") = py::cast(BINFHE_PARAMSET::TOY);
  69. m.attr("MEDIUM") = py::cast(BINFHE_PARAMSET::MEDIUM);
  70. m.attr("STD128_LMKCDEY") = py::cast(BINFHE_PARAMSET::STD128_LMKCDEY);
  71. m.attr("STD128_AP") = py::cast(BINFHE_PARAMSET::STD128_AP);
  72. m.attr("STD128") = py::cast(BINFHE_PARAMSET::STD128);
  73. m.attr("STD192") = py::cast(BINFHE_PARAMSET::STD192);
  74. m.attr("STD256") = py::cast(BINFHE_PARAMSET::STD256);
  75. m.attr("STD128Q") = py::cast(BINFHE_PARAMSET::STD128Q);
  76. m.attr("STD128Q_LMKCDEY") = py::cast(BINFHE_PARAMSET::STD128Q_LMKCDEY);
  77. m.attr("STD192Q") = py::cast(BINFHE_PARAMSET::STD192Q);
  78. m.attr("STD256Q") = py::cast(BINFHE_PARAMSET::STD256Q);
  79. m.attr("STD128_3") = py::cast(BINFHE_PARAMSET::STD128_3);
  80. m.attr("STD128_3_LMKCDEY") = py::cast(BINFHE_PARAMSET::STD128_3_LMKCDEY);
  81. m.attr("STD128Q_3") = py::cast(BINFHE_PARAMSET::STD128Q_3);
  82. m.attr("STD128Q_3_LMKCDEY") = py::cast(BINFHE_PARAMSET::STD128Q_3_LMKCDEY);
  83. m.attr("STD192Q_3") = py::cast(BINFHE_PARAMSET::STD192Q_3);
  84. m.attr("STD256Q_3") = py::cast(BINFHE_PARAMSET::STD256Q_3);
  85. m.attr("STD128_4") = py::cast(BINFHE_PARAMSET::STD128_4);
  86. m.attr("STD128_4_LMKCDEY") = py::cast(BINFHE_PARAMSET::STD128_4_LMKCDEY);
  87. m.attr("STD128Q_4") = py::cast(BINFHE_PARAMSET::STD128Q_4);
  88. m.attr("STD128Q_4_LMKCDEY") = py::cast(BINFHE_PARAMSET::STD128Q_4_LMKCDEY);
  89. m.attr("STD192Q_4") = py::cast(BINFHE_PARAMSET::STD192Q_4);
  90. m.attr("STD256Q_4") = py::cast(BINFHE_PARAMSET::STD256Q_4);
  91. m.attr("SIGNED_MOD_TEST") = py::cast(BINFHE_PARAMSET::SIGNED_MOD_TEST);
  92. py::enum_<BINFHE_METHOD>(m, "BINFHE_METHOD")
  93. .value("INVALID_METHOD", BINFHE_METHOD::INVALID_METHOD)
  94. .value("AP", BINFHE_METHOD::AP)
  95. .value("GINX", BINFHE_METHOD::GINX)
  96. .value("LMKCDEY", BINFHE_METHOD::LMKCDEY);
  97. m.attr("INVALID_METHOD") = py::cast(BINFHE_METHOD::INVALID_METHOD);
  98. m.attr("GINX") = py::cast(BINFHE_METHOD::GINX);
  99. m.attr("AP") = py::cast(BINFHE_METHOD::AP);
  100. m.attr("LMKCDEY") = py::cast(BINFHE_METHOD::LMKCDEY);
  101. py::enum_<KEYGEN_MODE>(m, "KEYGEN_MODE")
  102. .value("SYM_ENCRYPT", KEYGEN_MODE::SYM_ENCRYPT)
  103. .value("PUB_ENCRYPT", KEYGEN_MODE::PUB_ENCRYPT);
  104. m.attr("SYM_ENCRYPT") = py::cast(KEYGEN_MODE::SYM_ENCRYPT);
  105. m.attr("PUB_ENCRYPT") = py::cast(KEYGEN_MODE::PUB_ENCRYPT);
  106. py::enum_<BINFHE_OUTPUT>(m, "BINFHE_OUTPUT")
  107. .value("INVALID_OUTPUT", BINFHE_OUTPUT::INVALID_OUTPUT)
  108. .value("FRESH", BINFHE_OUTPUT::FRESH)
  109. .value("BOOTSTRAPPED", BINFHE_OUTPUT::BOOTSTRAPPED);
  110. m.attr("INVALID_OUTPUT") = py::cast(BINFHE_OUTPUT::INVALID_OUTPUT);
  111. m.attr("FRESH") = py::cast(BINFHE_OUTPUT::FRESH);
  112. m.attr("BOOTSTRAPPED") = py::cast(BINFHE_OUTPUT::BOOTSTRAPPED);
  113. py::enum_<BINGATE>(m, "BINGATE")
  114. .value("OR", BINGATE::OR)
  115. .value("AND", BINGATE::AND)
  116. .value("NOR", BINGATE::NOR)
  117. .value("NAND", BINGATE::NAND)
  118. .value("XOR_FAST", BINGATE::XOR_FAST)
  119. .value("XNOR_FAST", BINGATE::XNOR_FAST)
  120. .value("XOR", BINGATE::XOR)
  121. .value("XNOR", BINGATE::XNOR);
  122. m.attr("OR") = py::cast(BINGATE::OR);
  123. m.attr("AND") = py::cast(BINGATE::AND);
  124. m.attr("NOR") = py::cast(BINGATE::NOR);
  125. m.attr("NAND") = py::cast(BINGATE::NAND);
  126. m.attr("XOR_FAST") = py::cast(BINGATE::XOR_FAST);
  127. m.attr("XNOR_FAST") = py::cast(BINGATE::XNOR_FAST);
  128. m.attr("XOR") = py::cast(BINGATE::XOR);
  129. m.attr("XNOR") = py::cast(BINGATE::XNOR);
  130. }
  131. void bind_binfhe_keys(py::module &m) {
  132. py::class_<LWEPrivateKeyImpl, std::shared_ptr<LWEPrivateKeyImpl>>(
  133. m, "LWEPrivateKey")
  134. .def(py::init<>())
  135. .def("GetLength", &LWEPrivateKeyImpl::GetLength)
  136. .def(py::self == py::self)
  137. .def(py::self != py::self);
  138. }
  139. void bind_binfhe_ciphertext(py::module &m) {
  140. py::class_<LWECiphertextImpl, std::shared_ptr<LWECiphertextImpl>>(
  141. m, "LWECiphertext")
  142. .def(py::init<>())
  143. .def("GetLength", &LWECiphertextImpl::GetLength)
  144. .def("GetModulus", &GetLWECiphertextModulusWrapper)
  145. .def(py::self == py::self)
  146. .def(py::self != py::self);
  147. }
  148. void bind_binfhe_context(py::module &m) {
  149. py::class_<BinFHEContext, std::shared_ptr<BinFHEContext>>(m, "BinFHEContext")
  150. .def(py::init<>())
  151. .def("GenerateBinFHEContext",
  152. static_cast<void (BinFHEContext::*)(BINFHE_PARAMSET, BINFHE_METHOD)>(
  153. &BinFHEContext::GenerateBinFHEContext),
  154. binfhe_GenerateBinFHEContext_parset_docs, py::arg("set"),
  155. py::arg("method") = GINX)
  156. // void GenerateBinFHEContext(BINFHE_PARAMSET set, bool arbFunc, uint32_t
  157. // logQ = 11, int64_t N = 0, BINFHE_METHOD method = GINX, bool
  158. // timeOptimization = false)
  159. .def("GenerateBinFHEContext",
  160. static_cast<void (BinFHEContext::*)(BINFHE_PARAMSET, bool, uint32_t,
  161. uint32_t, BINFHE_METHOD, bool)>(
  162. &BinFHEContext::GenerateBinFHEContext),
  163. binfhe_GenerateBinFHEContext_docs, py::arg("set"),
  164. py::arg("arbFunc"), py::arg("logQ") = 11, py::arg("N") = 0,
  165. py::arg("method") = GINX, py::arg("timeOptimization") = false)
  166. .def("KeyGen", &BinFHEContext::KeyGen, binfhe_KeyGen_docs)
  167. .def("KeyGenN", &BinFHEContext::KeyGenN)
  168. .def("KeyGenPair", &BinFHEContext::KeyGenPair)
  169. .def("BTKeyGen", &BinFHEContext::BTKeyGen, binfhe_BTKeyGen_docs,
  170. py::arg("sk"), py::arg("keygenMode") = SYM_ENCRYPT)
  171. .def("Encrypt", &binfhe_EncryptWrapper, binfhe_Encrypt_docs,
  172. py::arg("sk"), py::arg("m"), py::arg("output") = BOOTSTRAPPED,
  173. py::arg("p") = 4, py::arg("mod") = 0)
  174. .def("Decrypt", &binfhe_DecryptWrapper, binfhe_Decrypt_docs,
  175. py::arg("sk"), py::arg("ct"), py::arg("p") = 4)
  176. .def("EvalBinGate",
  177. static_cast<LWECiphertext (BinFHEContext::*)(
  178. BINGATE, ConstLWECiphertext &, ConstLWECiphertext &, bool) const>(
  179. &BinFHEContext::EvalBinGate),
  180. binfhe_EvalBinGate_docs, py::arg("gate"), py::arg("ct1"),
  181. py::arg("ct2"), py::arg("extended") = false)
  182. .def("EvalBinGate",
  183. static_cast<LWECiphertext (BinFHEContext::*)(
  184. BINGATE, const std::vector<LWECiphertext> &, bool) const>(
  185. &BinFHEContext::EvalBinGate),
  186. py::arg("gate"), py::arg("ctvector"), py::arg("extended") = false)
  187. .def("EvalNOT", &BinFHEContext::EvalNOT, binfhe_EvalNOT_docs,
  188. py::arg("ct"))
  189. .def("Getn", &GetnWrapper)
  190. .def("Getq", &GetqWrapper)
  191. .def("GetMaxPlaintextSpace", &GetMaxPlaintextSpaceWrapper)
  192. .def("GetBeta", &GetBetaWrapper)
  193. .def("EvalDecomp", &BinFHEContext::EvalDecomp, binfhe_EvalDecomp_docs,
  194. py::arg("ct"))
  195. .def("EvalFloor", &BinFHEContext::EvalFloor, binfhe_EvalFloor_docs,
  196. py::arg("ct"), py::arg("roundbits") = 0)
  197. .def("GenerateLUTviaFunction", &GenerateLUTviaFunctionWrapper,
  198. binfhe_GenerateLUTviaFunction_docs, py::arg("f"), py::arg("p"))
  199. .def("EvalFunc", &EvalFuncWrapper, binfhe_EvalFunc_docs, py::arg("ct"),
  200. py::arg("LUT"))
  201. .def("EvalSign", &BinFHEContext::EvalSign, binfhe_EvalSign_docs,
  202. py::arg("ct"), py::arg("schemeSwitch") = false)
  203. .def("EvalNOT", &BinFHEContext::EvalNOT)
  204. .def("EvalConstant", &BinFHEContext::EvalConstant)
  205. .def("ClearBTKeys", &BinFHEContext::ClearBTKeys)
  206. .def("Bootstrap", &BinFHEContext::Bootstrap, py::arg("ct"), py::arg("extended") = false)
  207. .def("SerializedVersion", &BinFHEContext::SerializedVersion,
  208. binfhe_SerializedVersion_docs)
  209. .def("SerializedObjectName", &BinFHEContext::SerializedObjectName,
  210. binfhe_SerializedObjectName_docs)
  211. .def("SaveJSON", &BinFHEContext::save<cereal::JSONOutputArchive>)
  212. .def("LoadJSON", &BinFHEContext::load<cereal::JSONInputArchive>)
  213. .def("SaveBinary", &BinFHEContext::save<cereal::BinaryOutputArchive>)
  214. .def("LoadBinary", &BinFHEContext::load<cereal::BinaryInputArchive>)
  215. .def("SavePortableBinary",
  216. &BinFHEContext::save<cereal::PortableBinaryOutputArchive>)
  217. .def("LoadPortableBinary",
  218. &BinFHEContext::load<cereal::PortableBinaryInputArchive>)
  219. .def("GetPublicKey", &BinFHEContext::GetPublicKey)
  220. .def("GetSwitchKey", &BinFHEContext::GetSwitchKey)
  221. .def("GetRefreshKey", &BinFHEContext::GetRefreshKey)
  222. .def("GetBinFHEScheme", &BinFHEContext::GetBinFHEScheme)
  223. .def("GetLWEScheme", &BinFHEContext::GetLWEScheme)
  224. .def("GetParams", &BinFHEContext::GetParams);
  225. }