Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ 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)
link_directories(${OpenFHE_LIBDIR})
link_libraries(${OpenFHE_LIBRARIES})

Expand All @@ -42,17 +43,19 @@ add_link_options(

# See https://github.com/emscripten-core/emscripten/blob/main/src/settings.js for more
# information
-sEXCEPTION_DEBUG=1
#-sEXCEPTION_DEBUG=1

-sALLOW_MEMORY_GROWTH=1
-sERROR_ON_UNDEFINED_SYMBOLS=0
-sMAXIMUM_MEMORY=4GB
-sALLOW_MEMORY_GROWTH=true
-sMEMORY_GROWTH_GEOMETRIC_STEP=0.50
-sMAXIMUM_MEMORY=4gb # Is the maximum value as of 3rd May
-sINITIAL_MEMORY=2gb
)
add_compile_options("-DOPENFHE_VERSION=${OpenFHE_VERSION}")

### add each of the subdirs of src
add_subdirectory(src/core)
add_subdirectory(src/pke)
add_subdirectory(src/binfhe)

#find_package(Doxygen QUIET COMPONENTS dot)
#if (DOXYGEN_FOUND)
Expand Down
35 changes: 35 additions & 0 deletions examples/js/binfhe/boolean.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// follows boolean.cpp example
async function main() {
const factory = require('../../../lib/openfhe_binfhe')
const module = await factory()
const cc = new module.BinFHEContext()
cc.GenerateBinFHEContext(module.BINFHE_PARAMSET.STD128, module.BINFHE_METHOD.GINX);
console.log('Starting to generate keys.')
const sk = cc.KeyGen()
console.log('SK Generated')
cc.BTKeyGen(sk)
console.log('Completed generating keys.')

console.log('Encrypting...')
const ct1 = cc.Encrypt(sk, 1)
const ct2 = cc.Encrypt(sk, 2)

console.log('Computing...')
const ctAND1 = cc.EvalBinGate(module.BINGATE.AND, ct1, ct2)
const ct2Not = cc.EvalNOT(ct2)
const ctAND2 = cc.EvalBinGate(module.BINGATE.AND, ct2Not, ct1)
const ctResult = cc.EvalBinGate(module.BINGATE.OR, ctAND1, ctAND2)

console.log('Decrypting...')
const result = cc.Decrypt(sk, ctResult)
console.log(
'Result of encrypted computation of ' +
'(1 AND 1) OR (1 AND (NOT 1) = ' + result)

// since javascript cannot detect variables going out of scope reliably,
// we must delete the crypto context manually
cc.delete();
return 0
}

main().then(exitCode => console.log(exitCode))
115 changes: 115 additions & 0 deletions examples/js/binfhe/boolean_serial.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// follows boolean-serial-binary.cpp example
async function main() {
const factory = require('../../../lib/openfhe_binfhe')
const module = await factory()
try {

// Generating the crypto context
const cc1 = new module.BinFHEContext()
cc1.GenerateBinFHEContext(
module.BINFHE_PARAMSET.TOY,
module.BINFHE_METHOD.GINX
)
console.log("Generating keys.")

// Generating the secret key
const sk1 = cc1.KeyGen();

// Generating the bootstrapping keys
cc1.BTKeyGen(sk1)

console.log("Done generating all keys.")

// Encryption for a ciphertext that will be serialized
const ct1 = cc1.Encrypt(sk1, 1);

// CODE FOR SERIALIZATION

// Serializing key-independent crypto context

const cryptoContextBuffer =
module.SerializeCryptoContextToBuffer(cc1, module.SerType.BINARY);
console.log("The cryptocontext has been serialized.");

// Serializing refreshing and key switching keys (needed for bootstrapping)
//
const _refreshKey = cc1.GetRefreshKey();
const refreshKeyBuffer =
module.SerializeRefreshKeyToBuffer(_refreshKey, module.SerType.BINARY);
console.log("The refreshing key has been serialized.")

const _switchKey = cc1.GetSwitchKey();
const ksKeyBuffer =
module.SerializeSwitchingKeyToBuffer(_switchKey, module.SerType.BINARY);
console.log("The key switching key has been serialized.")

// Serializing private keys

const sk1Buffer =
module.SerializePrivateKeyToBuffer(sk1, module.SerType.BINARY);
console.log("The secret key sk1 key has been serialized")

// Serializing a ciphertext

const ct1Buffer =
module.SerializeCiphertextToBuffer(ct1, module.SerType.BINARY);

// CODE FOR DESERIALIZATION

// Deserializing the cryptocontext

const cc =
module.DeserializeCryptoContextFromBuffer(cryptoContextBuffer, module.SerType.BINARY);
console.log("The cryptocontext has been deserialized");

// deserializing the refreshing and switching keys (for bootstrapping)

const refreshKey =
module.DeserializeRefreshKeyFromBuffer(refreshKeyBuffer, module.SerType.BINARY);
console.log("The refresh key has been deserialized");

const ksKey =
module.DeserializeSwitchingKeyFromBuffer(ksKeyBuffer, module.SerType.BINARY);
console.log("The key switching key has been deserialized");

// Loading the keys in the cryptocontext
cc.BTKeyLoad(refreshKey, ksKey);

// Deserializing the secret key

const sk =
module.DeserializePrivateKeyFromBuffer(sk1Buffer, module.SerType.BINARY);
console.log("The secret key has been deserialized");

// Deserializing a previously serialized ciphertext

const ct =
module.DeserializeCiphertextFromBuffer(ct1Buffer, module.SerType.BINARY);
console.log("The ciphertext has been deserialized");

// OPERATIONS WITH DESERIALIZED KEYS AND CIPHERTEXTS

const ct2 = cc.Encrypt(sk, 1);

console.log("Running the computation");

const ctResult = cc.EvalBinGate(module.BINGATE.AND, ct, ct2);

console.log("The computation has been completed");

const result = cc.Decrypt(sk, ctResult);

console.log(`result of 1 AND 1 = ${result}`)

return 0
} catch (err) {
if (typeof err === 'number')
console.log(module.getExceptionMessage(err))
else
console.log(err)
return 1;
}
}

main().then(exitCode => console.log(exitCode))

214 changes: 214 additions & 0 deletions src/binfhe/BinFHEContext_em.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
// Palisade Includes
#include "binfhe/binfhecontext.h"
#include "binfhe/binfhecontext-ser.h"
using namespace lbcrypto;

// Emscripten includes.
#include <emscripten.h>
#include <emscripten/bind.h>
using namespace emscripten;

// Local emscripten binding includes.
#include "binfhe_serial_em.h"
#include "binfhe_types.h"
#include "core/exception_em.h"

/**
*
Creates a crypto context using custom parameters. Should be used with care (only for advanced users familiar with LWE parameter selection).

@param n – lattice parameter for additive LWE scheme
@param N – ring dimension for RingGSW/RLWE used in bootstrapping
@param &q – modulus for additive LWE
@param &Q – modulus for RingGSW/RLWE used in bootstrapping
@param std – standard deviation
@param baseKS – the base used for key switching
@param baseG – the gadget base used in bootstrapping
@param baseR – the base used for refreshing
@param method – the bootstrapping method (DM or CGGI)
*/
void GenerateBinFHEContext1(
BinFHEContext *cryptoCtx,
uint32_t n,
uint32_t N,
const NativeInteger &q,
const NativeInteger &Q,
double std,
uint32_t baseKS,
uint32_t baseG,
uint32_t baseR,
BINFHE_METHOD method = GINX
) {
cryptoCtx->GenerateBinFHEContext(
n,
N,
(const NativeInteger) q,
(const NativeInteger) Q,
std,
baseKS,
baseG,
baseR,
method = GINX
);
}

/**
* Creates a crypto context using custom parameters. Should be used with care (only for advanced users familiar with LWE parameter selection).
@param set – the parameter set: TOY, MEDIUM, STD128, STD192, STD256
@param arbFunc – whether need to evaluate an arbitrary function using functional bootstrapping
@param logQ – log(input ciphertext modulus)
@param N – ring dimension for RingGSW/RLWE used in bootstrapping
@param method – the bootstrapping method (DM or CGGI)
@param timeOptimization – whether to use dynamic bootstrapping technique
*/

void GenerateBinFHEContext2(
BinFHEContext *cryptoCtx,
BINFHE_PARAMSET set,
bool arbFunc,
uint32_t logQ = 11,
int64_t N = 0 ,
BINFHE_METHOD method = GINX,
bool timeOptimization = false
) {
cryptoCtx->GenerateBinFHEContext(set, arbFunc, logQ, N, method, timeOptimization);
}
/**
* Creates a crypto context using predefined parameters sets. Recommended for most users.
@param set – the parameter set: TOY, MEDIUM, STD128, STD192, STD256
@param method – the bootstrapping method (DM or CGGI)
*/
void GenerateBinFHEContext3(
BinFHEContext *cryptoCtx,
BINFHE_PARAMSET set,
BINFHE_METHOD method = GINX
) {
cryptoCtx->GenerateBinFHEContext(set, method);
}

/**
* @brief Encrypts a bit using a secret key (symmetric key encryption)
*
* @param cryptoCtx - Reference to CryptoContext from JS.
* @param sk - the secret key
* @param &m - the plaintext
* @param output - FRESH to generate fresh ciphertext, BOOTSTRAPPED to
* generate a refreshed ciphertext (default)
* @return a shared pointer to the ciphertext
*/
LWECiphertext Encrypt(BinFHEContext *cryptoCtx, LWEPrivateKey pk, uint32_t m) {
return cryptoCtx->Encrypt(pk, (LWEPlaintext) m);
}

/**
* @brief Decrypts a ciphertext using a secret key
*
* @param cryptoCtx - Reference to CryptoContext from JS.
* @param sk the secret key
* @param ct the ciphertext
* @param *result plaintext as unsigned int.
*/
uint32_t Decrypt(BinFHEContext *cryptoCtx, LWEPrivateKey sk, LWECiphertext ct) {
LWEPlaintext result;
cryptoCtx->Decrypt(sk, ct, &result);
return result;
}

/**
* @brief Generates boostrapping keys
*
* @param cryptoCtx - Reference to CryptoContext from JS.
* @param sk secret key
*/
void BTKeyGen(BinFHEContext *cryptoCtx, LWEPrivateKey sk) { cryptoCtx->BTKeyGen(sk); }

/**
* @brief Generates a switching key to go from a secret key with (Q,N) to a secret
* key with (q,n)
*
* @param cryptoCtx - Reference to CryptoContext from JS.
* @param sk new secret key
* @param skN old secret key
* @return a shared pointer to the switching key
*/
LWESwitchingKey KeySwitchGen(
BinFHEContext *cryptoCtx,
ConstLWEPrivateKey sk,
ConstLWEPrivateKey skN) {
return cryptoCtx->KeySwitchGen(sk, skN);
}

/**
* @brief Loads bootstrapping keys in the context (typically after deserializing)
*
* @param cryptoCtx - Reference to CryptoContext from JS.
* @param BSkey - first element of struct with the bootstrapping keys.
* @param KSkey - second element of strct with the bootstrapping keys.
*/
void BTKeyLoad(BinFHEContext &cryptoCtx,
const RingGSWBTKey BSkey
) {
cryptoCtx.BTKeyLoad(BSkey);
}

/**
* @brief Evaluates a binary gate (calls bootstrapping as a subroutine)
*
* @param cryptoCtx - Reference to CryptoContext from JS.
* @param gate the gate; can be AND, OR, NAND, NOR, XOR, or XNOR
* @param ct1 first ciphertext
* @param ct2 second ciphertext
* @return a shared pointer to the resulting ciphertext
*/
LWECiphertext EvalBinGate(BinFHEContext *cryptoCtx, BINGATE gate, LWECiphertext ct1, LWECiphertext ct2) {
return cryptoCtx->EvalBinGate(gate, ct1, ct2);
}

/**
* @brief Bootstraps a ciphertext (without performing any operation)
*
* @param cryptoCtx - Reference to CryptoContext from JS.
* @param ct1 ciphertext to be bootstrapped
* @return a shared pointer to the resulting ciphertext
*/
LWECiphertext Bootstrap(BinFHEContext *cryptoCtx, LWECiphertext ct1) { return cryptoCtx->Bootstrap(ct1); }

/**
* @brief Evaluates NOT gate
*
* @param cryptoCtx - Reference to CryptoContext from JS.
* @param ct1 the input ciphertext
* @return a shared pointer to the resulting ciphertext
*/
LWECiphertext EvalNOT(BinFHEContext *cryptoCtx, LWECiphertext ct1) { return cryptoCtx->EvalNOT(ct1); }

EMSCRIPTEN_BINDINGS(binfhe) {
class_<BinFHEContext>("BinFHEContext")
.constructor<>()

.function("GenerateBinFHEContext", &GenerateBinFHEContext1, allow_raw_pointers())
.function("GenerateBinFHEContext", &GenerateBinFHEContext2, allow_raw_pointers())
.function("GenerateBinFHEContext", &GenerateBinFHEContext3, allow_raw_pointers())

.function("Encrypt", &Encrypt, allow_raw_pointers())

.function("Decrypt", &Decrypt, allow_raw_pointers())
.function("BTKeyGen", &BTKeyGen, allow_raw_pointers())
.function("BTKeyLoad", &BTKeyLoad)
.function("KeySwitchGen", &KeySwitchGen, allow_raw_pointers())

.function("EvalBinGate", &EvalBinGate, allow_raw_pointers())
.function("Bootstrap", &Bootstrap, allow_raw_pointers())
.function("EvalNOT", &EvalNOT, allow_raw_pointers())
.function("KeyGen", &BinFHEContext::KeyGen)
.function("KeyGenN", &BinFHEContext::KeyGenN)

.function("ClearBTKeys", &BinFHEContext::ClearBTKeys)
.function("GetRefreshKey", &BinFHEContext::GetRefreshKey, allow_raw_pointers())
.function("GetSwitchKey", &BinFHEContext::GetSwitchKey)
.function("GetParams", &BinFHEContext::GetParams)
.function("GetLWEScheme", &BinFHEContext::GetLWEScheme)
.function("SerializedObjectName", &BinFHEContext::SerializedObjectName)

.class_function("SerializedVersion", &BinFHEContext::SerializedVersion);
}
Loading