Browse Source

Merge pull request #26 from openfheorg/Oliveira_boolean

Oliveira boolean
Rener Oliveira 1 year ago
parent
commit
50a663a963

+ 10 - 1
CMakeLists.txt

@@ -16,8 +16,10 @@ include_directories( ${OpenFHE_INCLUDE} )
 include_directories( ${OpenFHE_INCLUDE}/third-party/include )
 include_directories( ${OpenFHE_INCLUDE}/core )
 include_directories( ${OpenFHE_INCLUDE}/pke )
+include_directories( ${OpenFHE_INCLUDE}/binfhe )
 # include_directories( ${OpenFHE_Py_SOURCES} )
 include_directories( ${OpenFHE_Py_INCLUDES}/pke )
+include_directories( ${OpenFHE_Py_INCLUDES}/binfhe )
 include_directories( ${OpenFHE_Py_INCLUDES} )
 ### add directories for other OpenFHE modules as needed for your project
 
@@ -38,7 +40,14 @@ endif()
 ### add_executable( test demo-simple-example.cpp )
 
 ### Pybind Modules
-pybind11_add_module(openfhe src/bindings.cpp src/pke/decryption.cpp src/pke/serialization.cpp src/pke/cryptocontext_wrapper.cpp)
+pybind11_add_module(openfhe 
+                    src/bindings.cpp 
+                    src/binfhe_bindings.cpp
+                    src/binfhe/binfhecontext_wrapper.cpp
+                    src/pke/decryption.cpp 
+                    src/pke/serialization.cpp 
+                    src/pke/cryptocontext_wrapper.cpp
+                    )
 ### Python installation 
 find_package(Python REQUIRED COMPONENTS Interpreter Development)
 

+ 22 - 0
include/binfhe/binfhecontext_wrapper.h

@@ -0,0 +1,22 @@
+#ifndef BINFHE_CRYPTOCONTEXT_BINDINGS_H
+#define BINFHE_CRYPTOCONTEXT_BINDINGS_H
+
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+#include "openfhe.h"
+#include "binfhecontext.h"
+
+namespace py = pybind11;
+using namespace lbcrypto;
+LWECiphertext binfhe_EncryptWrapper(BinFHEContext &self,
+                                    ConstLWEPrivateKey sk,
+                                    const LWEPlaintext &m,
+                                    BINFHE_OUTPUT output,
+                                    LWEPlaintextModulus p,
+                                    uint64_t mod);
+LWEPlaintext binfhe_DecryptWrapper(BinFHEContext &self,
+                                   ConstLWEPrivateKey sk,
+                                   ConstLWECiphertext ct,
+                                   LWEPlaintextModulus p);
+
+#endif // BINFHE_CRYPTOCONTEXT_BINDINGS_H

+ 10 - 0
include/binfhe_bindings.h

@@ -0,0 +1,10 @@
+#ifndef BINFHE_BINDINGS_H
+#define BINFHE_BINDINGS_H
+
+#include <pybind11/pybind11.h>
+
+void bind_binfhe_enums(pybind11::module &m);
+void bind_binfhe_context(pybind11::module &m);
+void bind_binfhe_keys(pybind11::module &m);
+void bind_binfhe_ciphertext(pybind11::module &m);
+#endif // BINFHE_BINDINGS_H

+ 7 - 0
src/bindings.cpp

@@ -9,6 +9,7 @@
 #include "key/key-ser.h"
 #include "bindings.h"
 #include "cryptocontext_wrapper.h"
+#include "binfhe_bindings.h"
 
 using namespace lbcrypto;
 namespace py = pybind11;
@@ -304,6 +305,7 @@ void bind_schemes(py::module &m){
 PYBIND11_MODULE(openfhe, m)
 {
     m.doc() = "Open-Source Fully Homomorphic Encryption Library";
+    // pke library
     bind_parameters(m);
     bind_enums_and_constants(m);
     bind_crypto_context(m);
@@ -313,4 +315,9 @@ PYBIND11_MODULE(openfhe, m)
     bind_decryption(m);
     bind_serialization(m);
     bind_schemes(m);
+    // binfhe library
+    bind_binfhe_enums(m);
+    bind_binfhe_context(m);
+    bind_binfhe_keys(m);
+    bind_binfhe_ciphertext(m);
 }

+ 25 - 0
src/binfhe/binfhecontext_wrapper.cpp

@@ -0,0 +1,25 @@
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+#include <openfhe.h>
+#include "binfhecontext_wrapper.h"
+
+using namespace lbcrypto;
+namespace py = pybind11;
+
+LWECiphertext binfhe_EncryptWrapper(BinFHEContext &self, ConstLWEPrivateKey sk, const LWEPlaintext &m, BINFHE_OUTPUT output,
+                                    LWEPlaintextModulus p, uint64_t mod)
+{
+    NativeInteger mod_native_int = NativeInteger(mod);
+    return self.Encrypt(sk, m, output, p, mod_native_int);
+}
+
+LWEPlaintext binfhe_DecryptWrapper(BinFHEContext &self,
+                                   ConstLWEPrivateKey sk,
+                                   ConstLWECiphertext ct,
+                                   LWEPlaintextModulus p)
+{
+
+    LWEPlaintext result;
+    self.Decrypt(sk, ct, &result, p);
+    return result;
+}

+ 58 - 0
src/binfhe/examples/boolean-ap.py

@@ -0,0 +1,58 @@
+from openfhe import *
+
+## Sample Program: Step 1: Set CryptoContext
+
+cc = BinFHEContext()
+
+"""
+STD128 is the security level of 128 bits of security based on LWE Estimator
+and HE standard. Other common options are TOY, MEDIUM, STD192, and STD256.
+MEDIUM corresponds to the level of more than 100 bits for both quantum and
+classical computer attacks. The second argument is the bootstrapping method
+(AP or GINX). The default method is GINX. Here we explicitly set AP. GINX
+typically provides better performance: the bootstrapping key is much
+smaller in GINX (by 20x) while the runtime is roughly the same.
+"""
+cc.GenerateBinFHEContext(STD128,AP)
+
+## Sample Program: Step 2: Key Generation
+
+# Generate the secret key
+sk = cc.KeyGen()
+
+print("Generating the bootstrapping keys...\n")
+
+# Generate the bootstrapping keys (refresh and switching keys)
+cc.BTKeyGen(sk)
+
+print("Completed the key generation.\n")
+# Sample Program: Step 3: Encryption
+"""
+Encrypt two ciphertexts representing Boolean True (1).
+By default, freshly encrypted ciphertexts are bootstrapped.
+If you wish to get a fresh encryption without bootstrapping, write
+ct1 = cc.Encrypt(sk, 1, FRESH)
+"""
+ct1 = cc.Encrypt(sk, 1)
+ct2 = cc.Encrypt(sk, 1)
+
+# Sample Program: Step 4: Evaluation
+
+# Compute (1 AND 1) = 1; Other binary gate options are OR, NAND, and NOR
+ctAND1 = cc.EvalBinGate(AND, ct1, ct2)
+
+# Compute (NOT 1) = 0
+ct2Not = cc.EvalNOT(ct2)
+
+# Compute (1 AND (NOT 1)) = 0
+ctAND2 = cc.EvalBinGate(AND, ct2Not, ct1)
+
+# Compute OR of the result in ctAND1 and ctAND2
+ctResult = cc.EvalBinGate(OR, ctAND1, ctAND2)
+
+# Sample Program: Step 5: Decryption
+
+result = cc.Decrypt(sk, ctResult)
+
+print(f"Result of encrypted computation of (1 AND 1) OR (1 AND (NOT 1)) = {result}")
+

+ 197 - 0
src/binfhe/examples/boolean-truth-tables.py

@@ -0,0 +1,197 @@
+from openfhe import *
+
+# Sample Program: Step 1: Set CryptoContext
+cc = BinFHEContext()
+
+print("Generate cryptocontext\n")
+
+"""
+STD128 is the security level of 128 bits of security based on LWE Estimator
+and HE standard. Other common options are TOY, MEDIUM, STD192, and STD256. MEDIUM 
+corresponds to the level of more than 100 bits for both quantum and
+classical computer attacks
+"""
+
+cc.GenerateBinFHEContext(STD128)
+print("Finished generating cryptocontext\n")
+
+# Sample Program: Step 2: Key Generation
+
+# Generate the secret key
+sk = cc.KeyGen()
+
+print("Generating the bootstrapping keys...\n")
+
+# Generate the bootstrapping keys (refresh and switching keys)
+cc.BTKeyGen(sk)
+
+print("Completed the key generation.\n\n")
+
+# Sample Program: Step 3: Encryption
+
+# Encrypt two ciphertexts representing Boolean True (1).
+ct10 = cc.Encrypt(sk, 1)
+ct11 = cc.Encrypt(sk, 1)
+# Encrypt two ciphertexts representing Boolean False (0).
+ct00 = cc.Encrypt(sk, 0)
+ct01 = cc.Encrypt(sk, 0)
+
+# Sample Program: Step 4: Evaluation of NAND gates
+
+ctNAND1 = cc.EvalBinGate(NAND, ct10, ct11)
+ctNAND2 = cc.EvalBinGate(NAND, ct10, ct01)
+ctNAND3 = cc.EvalBinGate(NAND, ct00, ct01)
+ctNAND4 = cc.EvalBinGate(NAND, ct00, ct11)
+
+result = cc.Decrypt(sk, ctNAND1)
+print(f"1 NAND 1 = {result}")
+
+result = cc.Decrypt(sk, ctNAND2)
+print(f"1 NAND 0 = {result}")
+
+result = cc.Decrypt(sk, ctNAND3)
+print(f"0 NAND 0 = {result}")
+
+result = cc.Decrypt(sk, ctNAND4)
+print(f"0 NAND 1 = {result}")
+
+# Sample Program: Step 5: Evaluation of AND gates
+
+ctAND1 = cc.EvalBinGate(AND, ct10, ct11)
+ctAND2 = cc.EvalBinGate(AND, ct10, ct01)
+ctAND3 = cc.EvalBinGate(AND, ct00, ct01)
+ctAND4 = cc.EvalBinGate(AND, ct00, ct11)
+
+result = cc.Decrypt(sk, ctAND1)
+print(f"1 AND 1 = {result}")
+
+result = cc.Decrypt(sk, ctAND2)
+print(f"1 AND 0 = {result}")
+
+result = cc.Decrypt(sk, ctAND3)
+print(f"0 AND 0 = {result}")
+
+result = cc.Decrypt(sk, ctAND4)
+print(f"0 AND 1 = {result}")
+
+# Sample Program: Step 6: Evaluation of OR gates
+
+ctOR1 = cc.EvalBinGate(OR, ct10, ct11)
+ctOR2 = cc.EvalBinGate(OR, ct10, ct01)
+ctOR3 = cc.EvalBinGate(OR, ct00, ct01)
+ctOR4 = cc.EvalBinGate(OR, ct00, ct11)
+
+result = cc.Decrypt(sk, ctOR1)
+print(f"1 OR 1 = {result}")
+
+result = cc.Decrypt(sk, ctOR2)
+print(f"1 OR 0 = {result}")
+
+result = cc.Decrypt(sk, ctOR3)
+print(f"0 OR 0 = {result}")
+
+result = cc.Decrypt(sk, ctOR4)
+print(f"0 OR 1 = {result}")
+
+# Sample Program: Step 7: Evaluation of NOR gates
+
+ctNOR1 = cc.EvalBinGate(NOR, ct10, ct11)
+ctNOR2 = cc.EvalBinGate(NOR, ct10, ct01)
+ctNOR3 = cc.EvalBinGate(NOR, ct00, ct01)
+ctNOR4 = cc.EvalBinGate(NOR, ct00, ct11)
+
+result = cc.Decrypt(sk, ctNOR1)
+print(f"1 NOR 1 = {result}")
+
+result = cc.Decrypt(sk, ctNOR2)
+print(f"1 NOR 0 = {result}")
+
+result = cc.Decrypt(sk, ctNOR3)
+print(f"0 NOR 0 = {result}")
+
+result = cc.Decrypt(sk, ctNOR4)
+print(f"0 NOR 1 = {result}")
+
+# Sample Program: Step 8: Evaluation of XOR gates
+
+ctXOR1 = cc.EvalBinGate(XOR, ct10, ct11)
+ctXOR2 = cc.EvalBinGate(XOR, ct10, ct01)
+ctXOR3 = cc.EvalBinGate(XOR, ct00, ct01)
+ctXOR4 = cc.EvalBinGate(XOR, ct00, ct11)
+
+result = cc.Decrypt(sk, ctXOR1)
+print(f"1 XOR 1 = {result}")
+
+result = cc.Decrypt(sk, ctXOR2)
+print(f"1 XOR 0 = {result}")
+
+result = cc.Decrypt(sk, ctXOR3)
+print(f"0 XOR 0 = {result}")
+
+result = cc.Decrypt(sk, ctXOR4)
+print(f"0 XOR 1 = {result}")
+
+# Sample Program: Step 9: Evaluation of XNOR gates
+
+ctXNOR1 = cc.EvalBinGate(XNOR, ct10, ct11)
+ctXNOR2 = cc.EvalBinGate(XNOR, ct10, ct01)
+ctXNOR3 = cc.EvalBinGate(XNOR, ct00, ct01)
+ctXNOR4 = cc.EvalBinGate(XNOR, ct00, ct11)
+
+result = cc.Decrypt(sk, ctXNOR1)
+print(f"1 XNOR 1 = {result}")
+
+result = cc.Decrypt(sk, ctXNOR2)
+print(f"1 XNOR 0 = {result}")
+
+result = cc.Decrypt(sk, ctXNOR3)
+print(f"0 XNOR 0 = {result}")
+
+result = cc.Decrypt(sk, ctXNOR4)
+print(f"0 XNOR 1 = {result}")
+
+# Sample Program: Step 90: Evaluation of NOR gates
+# using XOR_FAT (1 boostrap but the probability of failure is higher)
+
+ctNOR1_FAST = cc.EvalBinGate(XOR_FAST, ct10, ct11)
+ctNOR2_FAST = cc.EvalBinGate(XOR_FAST, ct10, ct01)
+ctNOR3_FAST = cc.EvalBinGate(XOR_FAST, ct00, ct01)
+ctNOR4_FAST = cc.EvalBinGate(XOR_FAST, ct00, ct11)
+
+result = cc.Decrypt(sk, ctNOR1_FAST)
+print(f"1 XOR_FAST 1 = {result}")
+
+result = cc.Decrypt(sk, ctNOR2_FAST)
+print(f"1 XOR_FAST 0 = {result}")
+
+result = cc.Decrypt(sk, ctNOR3_FAST)
+print(f"0 XOR_FAST 0 = {result}")
+
+result = cc.Decrypt(sk, ctNOR4_FAST)
+print(f"0 XOR_FAST 1 = {result}")
+
+# Sample Program: Step 10: Evaluation of XNOR gates
+# using XNOR_FAT (1 boostrap but the probability of failure is higher)
+
+ctXNOR1_FAST = cc.EvalBinGate(XNOR_FAST, ct10, ct11)
+ctXNOR2_FAST = cc.EvalBinGate(XNOR_FAST, ct10, ct01)
+ctXNOR3_FAST = cc.EvalBinGate(XNOR_FAST, ct00, ct01)
+ctXNOR4_FAST = cc.EvalBinGate(XNOR_FAST, ct00, ct11)
+
+result = cc.Decrypt(sk, ctXNOR1_FAST)
+print(f"1 XNOR_FAST 1 = {result}")
+
+result = cc.Decrypt(sk, ctXNOR2_FAST)
+print(f"1 XNOR_FAST 0 = {result}")
+
+result = cc.Decrypt(sk, ctXNOR3_FAST)
+print(f"0 XNOR_FAST 0 = {result}")
+
+result = cc.Decrypt(sk, ctXNOR4_FAST)
+print(f"0 XNOR_FAST 1 = {result}")
+
+
+
+
+
+

+ 54 - 0
src/binfhe/examples/boolean.py

@@ -0,0 +1,54 @@
+from openfhe import *
+
+## Sample Program: Step 1: Set CryptoContext
+
+cc = BinFHEContext()
+
+"""
+STD128 is the security level of 128 bits of security based on LWE Estimator
+and HE standard. Other common options are TOY, MEDIUM, STD192, and STD256.
+MEDIUM corresponds to the level of more than 100 bits for both quantum and
+classical computer attacks
+"""
+cc.GenerateBinFHEContext(STD128,GINX)
+
+## Sample Program: Step 2: Key Generation
+
+# Generate the secret key
+sk = cc.KeyGen()
+
+print("Generating the bootstrapping keys...\n")
+
+# Generate the bootstrapping keys (refresh and switching keys)
+cc.BTKeyGen(sk)
+
+# Sample Program: Step 3: Encryption
+"""
+Encrypt two ciphertexts representing Boolean True (1).
+By default, freshly encrypted ciphertexts are bootstrapped.
+If you wish to get a fresh encryption without bootstrapping, write
+ct1 = cc.Encrypt(sk, 1, FRESH)
+"""
+ct1 = cc.Encrypt(sk, 1)
+ct2 = cc.Encrypt(sk, 1)
+
+# Sample Program: Step 4: Evaluation
+
+# Compute (1 AND 1) = 1; Other binary gate options are OR, NAND, and NOR
+ctAND1 = cc.EvalBinGate(AND, ct1, ct2)
+
+# Compute (NOT 1) = 0
+ct2Not = cc.EvalNOT(ct2)
+
+# Compute (1 AND (NOT 1)) = 0
+ctAND2 = cc.EvalBinGate(AND, ct2Not, ct1)
+
+# Compute OR of the result in ctAND1 and ctAND2
+ctResult = cc.EvalBinGate(OR, ctAND1, ctAND2)
+
+# Sample Program: Step 5: Decryption
+
+result = cc.Decrypt(sk, ctResult)
+
+print(f"Result of encrypted computation of (1 AND 1) OR (1 AND (NOT 1)) = {result}")
+

+ 129 - 0
src/binfhe_bindings.cpp

@@ -0,0 +1,129 @@
+#include <pybind11/pybind11.h>
+#include <pybind11/operators.h>
+#include <iostream>
+#include "openfhe.h"
+#include "binfhe_bindings.h"
+#include "binfhecontext.h"
+#include "binfhecontext_wrapper.h"
+
+using namespace lbcrypto;
+namespace py = pybind11;
+
+void bind_binfhe_enums(py::module &m)
+{
+    py::enum_<BINFHE_PARAMSET>(m, "BINFHE_PARAMSET")
+        .value("TOY", BINFHE_PARAMSET::TOY)
+        .value("MEDIUM", BINFHE_PARAMSET::MEDIUM)
+        .value("STD128_AP", BINFHE_PARAMSET::STD128_AP)
+        .value("STD128_APOPT", BINFHE_PARAMSET::STD128_APOPT)
+        .value("STD128", BINFHE_PARAMSET::STD128)
+        .value("STD128_OPT", BINFHE_PARAMSET::STD128_OPT)
+        .value("STD192", BINFHE_PARAMSET::STD192)
+        .value("STD192_OPT", BINFHE_PARAMSET::STD192_OPT)
+        .value("STD256", BINFHE_PARAMSET::STD256)
+        .value("STD256_OPT", BINFHE_PARAMSET::STD256_OPT)
+        .value("STD128Q", BINFHE_PARAMSET::STD128Q)
+        .value("STD128Q_OPT", BINFHE_PARAMSET::STD128Q_OPT)
+        .value("STD192Q", BINFHE_PARAMSET::STD192Q)
+        .value("STD192Q_OPT", BINFHE_PARAMSET::STD192Q_OPT)
+        .value("STD256Q", BINFHE_PARAMSET::STD256Q)
+        .value("STD256Q_OPT", BINFHE_PARAMSET::STD256Q_OPT)
+        .value("SIGNED_MOD_TEST", BINFHE_PARAMSET::SIGNED_MOD_TEST);
+    m.attr("TOY") = py::cast(BINFHE_PARAMSET::TOY);
+    m.attr("MEDIUM") = py::cast(BINFHE_PARAMSET::MEDIUM);
+    m.attr("STD128_AP") = py::cast(BINFHE_PARAMSET::STD128_AP);
+    m.attr("STD128_APOPT") = py::cast(BINFHE_PARAMSET::STD128_APOPT);
+    m.attr("STD128") = py::cast(BINFHE_PARAMSET::STD128);
+    m.attr("STD128_OPT") = py::cast(BINFHE_PARAMSET::STD128_OPT);
+    m.attr("STD192") = py::cast(BINFHE_PARAMSET::STD192);
+    m.attr("STD192_OPT") = py::cast(BINFHE_PARAMSET::STD192_OPT);
+    m.attr("STD256") = py::cast(BINFHE_PARAMSET::STD256);
+    m.attr("STD256_OPT") = py::cast(BINFHE_PARAMSET::STD256_OPT);
+    m.attr("STD128Q") = py::cast(BINFHE_PARAMSET::STD128Q);
+    m.attr("STD128Q_OPT") = py::cast(BINFHE_PARAMSET::STD128Q_OPT);
+    m.attr("STD192Q") = py::cast(BINFHE_PARAMSET::STD192Q);
+    m.attr("STD192Q_OPT") = py::cast(BINFHE_PARAMSET::STD192Q_OPT);
+    m.attr("STD256Q") = py::cast(BINFHE_PARAMSET::STD256Q);
+    m.attr("STD256Q_OPT") = py::cast(BINFHE_PARAMSET::STD256Q_OPT);
+    m.attr("SIGNED_MOD_TEST") = py::cast(BINFHE_PARAMSET::SIGNED_MOD_TEST);
+
+    py::enum_<BINFHE_METHOD>(m, "BINFHE_METHOD")
+        .value("INVALID_METHOD", BINFHE_METHOD::INVALID_METHOD)
+        .value("AP", BINFHE_METHOD::AP)
+        .value("GINX", BINFHE_METHOD::GINX);
+    m.attr("INVALID_METHOD") = py::cast(BINFHE_METHOD::INVALID_METHOD);
+    m.attr("GINX") = py::cast(BINFHE_METHOD::GINX);
+    m.attr("AP") = py::cast(BINFHE_METHOD::AP);
+
+    py::enum_<BINFHE_OUTPUT>(m, "BINFHE_OUTPUT")
+        .value("INVALID_OUTPUT", BINFHE_OUTPUT::INVALID_OUTPUT)
+        .value("FRESH", BINFHE_OUTPUT::FRESH)
+        .value("BOOTSTRAPPED", BINFHE_OUTPUT::BOOTSTRAPPED);
+    m.attr("INVALID_OUTPUT") = py::cast(BINFHE_OUTPUT::INVALID_OUTPUT);
+    m.attr("FRESH") = py::cast(BINFHE_OUTPUT::FRESH);
+    m.attr("BOOTSTRAPPED") = py::cast(BINFHE_OUTPUT::BOOTSTRAPPED);
+
+    py::enum_<BINGATE>(m, "BINGATE")
+        .value("OR", BINGATE::OR)
+        .value("AND", BINGATE::AND)
+        .value("NOR", BINGATE::NOR)
+        .value("NAND", BINGATE::NAND)
+        .value("XOR_FAST", BINGATE::XOR_FAST)
+        .value("XNOR_FAST", BINGATE::XNOR_FAST)
+        .value("XOR", BINGATE::XOR)
+        .value("XNOR", BINGATE::XNOR);
+    m.attr("OR") = py::cast(BINGATE::OR);
+    m.attr("AND") = py::cast(BINGATE::AND);
+    m.attr("NOR") = py::cast(BINGATE::NOR);
+    m.attr("NAND") = py::cast(BINGATE::NAND);
+    m.attr("XOR_FAST") = py::cast(BINGATE::XOR_FAST);
+    m.attr("XNOR_FAST") = py::cast(BINGATE::XNOR_FAST);
+    m.attr("XOR") = py::cast(BINGATE::XOR);
+    m.attr("XNOR") = py::cast(BINGATE::XNOR);
+
+}
+
+void bind_binfhe_keys(py::module &m)
+{
+    py::class_<LWEPrivateKeyImpl, std::shared_ptr<LWEPrivateKeyImpl>>(m, "LWEPrivateKey")
+        .def(py::init<>())
+        .def("GetLength", &LWEPrivateKeyImpl::GetLength)
+        .def(py::self == py::self)
+        .def(py::self != py::self);
+}
+void bind_binfhe_ciphertext(py::module &m)
+{
+    py::class_<LWECiphertextImpl, std::shared_ptr<LWECiphertextImpl>>(m, "LWECiphertext")
+        .def(py::init<>())
+        .def("GetLength", &LWECiphertextImpl::GetLength)
+        .def(py::self == py::self)
+        .def(py::self != py::self);
+}
+
+void bind_binfhe_context(py::module &m)
+{
+    py::class_<BinFHEContext>(m, "BinFHEContext")
+        .def(py::init<>())
+        .def("GenerateBinFHEContext", static_cast<void (BinFHEContext::*)(BINFHE_PARAMSET, BINFHE_METHOD)>(&BinFHEContext::GenerateBinFHEContext),
+             py::arg("set"), 
+             py::arg("method") = GINX)
+        .def("KeyGen", &BinFHEContext::KeyGen)
+        .def("BTKeyGen", &BinFHEContext::BTKeyGen)
+        .def("Encrypt", &binfhe_EncryptWrapper,
+             py::arg("sk"),
+             py::arg("m"),
+             py::arg("output") = BOOTSTRAPPED,
+             py::arg("p") = 4, 
+             py::arg("mod") = 0)
+        .def("Decrypt",&binfhe_DecryptWrapper,
+             py::arg("sk"),
+             py::arg("ct"),
+             py::arg("p") = 4)
+        .def("EvalBinGate",&BinFHEContext::EvalBinGate,
+             py::arg("gate"),
+             py::arg("ct1"),
+             py::arg("ct2"))
+        .def("EvalNOT",&BinFHEContext::EvalNOT,
+             py::arg("ct"));
+            
+}