Boolean Cipher Circuits Using Fully Homomorphic Encryption and OpenFHE

Prof Bill Buchanan OBE FRSE
4 min readJul 30, 2024

DM (FHEW) [1] uses a LWE (Learning With Error) method that provides fully homomorphic encryption (FHE). It is able to evaluate cipher data applied onto Boolean circuits and uses bootstrapping after each gate evaluation. This allows the evaluation to be conducted in less than 0.1 seconds. The gates implemented are AND, OR, NAND, NOR, and NOT. In homomorphic encryption, the noise in the computation increases as we perform operations. This is typically when we perform a large number of additions. and multiplications will often reduce the amount of noise. A bootstrapping process allows for us to reset the noise and will introduce a delay in the computation. In this case, we will use the Gama-Izabachene-Nguyen-Xie (GINX) [2] bootstrapping method.

In this case, we will use the Boolean circuit:

This gives us a Truth Table of:

b1  b2  (b1.b2)  (b1.NOT(b2)  Z
--------------------------------
0 0 0 0 0
0 1 0 0 0
1 0 0 1 1
1 1 1 0 1

For this, we initially create a secret key (sk) and a cipher context:

auto cc = BinFHEContext();
// We can use TOY, MEDIUM, STD192, and STD256.
cc.GenerateBinFHEContext(TOY);
auto sk = cc.KeyGen();
std::cout << "Creating bootstrapping keys..." << std::endl;
cc.BTKeyGen(sk);
std::cout << "Completed key generation." << std::endl;

We use a TOY example as it is faster but less secure. Other modes are MEDIUM, STD192, and STD25, and which give increased security levels. Next, we can encrypt the input bits and define our circuit using the EvalBinGate() method and AND, OR, NAND, NOR, XOR, and XNOR operations:

auto bit1 = cc.Encrypt(sk, b1);
auto bit2 = cc.Encrypt(sk, b2);

auto ctAND1 = cc.EvalBinGate(AND, bit1, bit2);
auto bit2Not = cc.EvalNOT(bit2);
auto ctAND2 = cc.EvalBinGate(AND, bit2Not, bit1);
auto ctResult = cc.EvalBinGate(OR, ctAND1, ctAND2);

Finally, we can decrypt with the private key (sk) to reveal the result:

LWEPlaintext result;
cc.Decrypt(sk, ctResult, &result);

We initially need to compile the OpenFHE code into a library. The Windows build is [here]. Then we create our cpp file, and build with:

g++.exe *.cpp lib.a -o openfhe_01  -I../../openfhe_main/src/pke/include -I../../openfhe_main/src/binfhe/include -I../../openfhe_main/src/core/include -I../../openfhe_main/src/core -I../../openfhe_main/build/src/core -I../../openfhe_main/src/binfhe -I../../openfhe_main/third-party/cereal/include

Coding

The code is [here]:

#include <openfhe.h>

using namespace lbcrypto;
using namespace std;
#include <iostream>
#include <sstream>
#include <cstdint>
int main(int argc, char *argv[]) {

int64_t b1=0, b2=0;

if (argc>1) {
std::istringstream iss(argv[1]);
iss >> b1;
}
if (argc>2) {
std::istringstream iss(argv[2]);
iss >>b2;
}
auto cc = BinFHEContext();
// We can use TOY, MEDIUM, STD192, and STD256.
cc.GenerateBinFHEContext(TOY);
auto sk = cc.KeyGen();
std::cout << "Creating bootstrapping keys..." << std::endl;
cc.BTKeyGen(sk);
std::cout << "Completed key generation." << std::endl;

auto bit1 = cc.Encrypt(sk, b1);
auto bit2 = cc.Encrypt(sk, b2);
auto ctAND1 = cc.EvalBinGate(AND, bit1, bit2);
auto bit2Not = cc.EvalNOT(bit2);
auto ctAND2 = cc.EvalBinGate(AND, bit2Not, bit1);
auto ctResult = cc.EvalBinGate(OR, ctAND1, ctAND2);

LWEPlaintext result;
cc.Decrypt(sk, ctResult, &result);
printf("b1=%d\n",b1);
printf("b2=%d\n",b2);
printf("(b1 AND b2) OR ( b1 AND NOT(b2))\n");
printf("(%d AND %d) OR ( %d AND NOT(%d))=%d\n",b1,b2,b1,b2,result);
return 0;

}

A sample run shows the correct output [here]:

Creating bootstrapping keys...
Completed key generation.
b1=0
b2=1
(b1 AND b2) OR ( b1 AND NOT(b2))
(0 AND 1) OR ( 0 AND NOT(1))=0

References

[1] Ducas, L., & Micciancio, D. (2015, April). FHEW: bootstrapping homomorphic encryption in less than a second. In Annual international conference on the theory and applications of cryptographic techniques (pp. 617–640). Berlin, Heidelberg: Springer Berlin Heidelberg.

[2] Gama, N., Izabachène, M., Nguyen, P. Q., & Xie, X. (2016). Structural lattice reduction: generalized worst-case to average-case reductions and homomorphic cryptosystems. In Advances in Cryptology–EUROCRYPT 2016: 35th Annual International Conference on the Theory and Applications of Cryptographic Techniques, Vienna, Austria, May 8–12, 2016, Proceedings, Part II 35 (pp. 528–558). Springer Berlin Heidelberg.

Conclusions

Isn’t that magic? We can create a cipher circuit with Boolean logic, and then apply ciphered bits onto it. This would mean we could build any electronic system but where the bits we used would be encrypted.

If you want to find out more about homomorphic encryption using SEAL and OpenFHE, try here:

https://asecuritysite.com/seal/index

References

[1] Ducas, L., & Micciancio, D. (2015, April). FHEW: bootstrapping homomorphic encryption in less than a second. In Annual international conference on the theory and applications of cryptographic techniques (pp. 617–640). Berlin, Heidelberg: Springer Berlin Heidelberg.

[2] Gama, N., Izabachène, M., Nguyen, P. Q., & Xie, X. (2016). Structural lattice reduction: generalized worst-case to average-case reductions and homomorphic cryptosystems. In Advances in Cryptology–EUROCRYPT 2016: 35th Annual International Conference on the Theory and Applications of Cryptographic Techniques, Vienna, Austria, May 8–12, 2016, Proceedings, Part II 35 (pp. 528–558). Springer Berlin Heidelberg.

--

--

Prof Bill Buchanan OBE FRSE

Professor of Cryptography. Serial innovator. Believer in fairness, justice & freedom. Based in Edinburgh. Old World Breaker. New World Creator. Building trust.