diff --git a/README.md b/README.md index a9f527c85..bf50e1802 100644 --- a/README.md +++ b/README.md @@ -17,17 +17,12 @@ Source code adapted from [C++ source code published here](https://www.sanfoundry 1) Install the OpenFHE library on your machine by following the [official documentation](https://openfhe-development.readthedocs.io/en/latest/sphinx_rsts/intro/installation/installation.html). Do note that the following example has not been tested on windows or macOS. -2) Clone this repo to your local system and `cd` into it - -``` -git clone git@github.com:openfheorg/openfhe-integer-examples.git -cd openfhe-integer-examples -``` +2) Clone this repo to your local system 3) Build this code ``` -mkdir build +mkdr build cd build cmake .. make diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4bfa92a53..1ec9767f4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,2 +1,2 @@ add_executable( strsearch_enc_1 strsearch_enc_1.cpp) -add_executable( strsearch_enc_2 strsearch_enc_2.cpp ) +add_executable( strsearch_enc_2 strsearch_enc_2.cpp) diff --git a/src/strsearch_enc_1.cpp b/src/strsearch_enc_1.cpp index 5fc4233fa..0a2d38e7e 100644 --- a/src/strsearch_enc_1.cpp +++ b/src/strsearch_enc_1.cpp @@ -1,4 +1,4 @@ -/* OpenFHE C++ program implements the Rabin-Karp method for string +/* PALISADE C++ program implements the Rabin-Karp method for string * matching using encrypted computation and no SIMD batching * plaintext version of this code comes from * https://www.sanfoundry.com/cpp-program-implement-rabin-karp-method-for-string-matching @@ -6,18 +6,17 @@ */ -#include +#include +#include #include +#include #include #include "openfhe.h" -#include "scheme/bfvrns/cryptocontext-bfvrns.h" -#include "gen-cryptocontext.h" -#include "utils/debug.h" using namespace std; //data types we will need -using CT = lbcrypto::Ciphertext ; //ciphertext -using PT = lbcrypto::Plaintext ; //plaintext +using CT = lbcrypto::Ciphertext; //ciphertext +using PT = lbcrypto::Plaintext; //plaintext using vecCT = vector; //vector of ciphertexts using vecPT = vector; //vector of plaintexts using vecInt = vector; // vector of ints @@ -31,33 +30,33 @@ const int d = 256; // p -> A prime number // function to get string input from terminal and return as vector of char -void get_input_from_term(vecChar& a) { +void get_input_from_term(vecChar &a) { string cstr; - cin.ignore(numeric_limits::max(),'\n'); //flushes buffer + cin.ignore(numeric_limits::max(), '\n'); //flushes buffer std::getline(std::cin, cstr); - cout <<"Pattern is `"<> c) { - a.push_back(c); + a.push_back(c); } - cout <<"Read "< &cc, lbcrypto::PublicKey &pk, int64_t in, size_t n){ +CT encrypt_repeated_integer(lbcrypto::CryptoContext &cc, lbcrypto::PublicKey &pk, int64_t in, size_t n) { vecInt v_in(n, in); - PT pt= cc->MakePackedPlaintext(v_in); + PT pt = cc->MakePackedPlaintext(v_in); CT ct = cc->Encrypt(pk, pt); return ct; } // helper function to multiply by constant 256 using binary tree addition -CT encMultD(lbcrypto::CryptoContext &cc, CT in){ - if (d !=256){ - cout <<"error d not 256"< &cc, CT in) { + if (d != 256) { + cout << "error d not 256" << endl; exit(-1); } auto tmp(in); - for (auto i = 0; i< 8; i++ ){ - tmp = cc->EvalAdd(tmp, tmp); + for (auto i = 0; i < 8; i++) { + tmp = cc->EvalAdd(tmp, tmp); } - return(tmp); + return (tmp); } //Single value encrypted search -vecCT encrypted_search(lbcrypto::CryptoContext &cc, lbcrypto::PublicKey &pk, vecCT &epat, vecCT &etxt, int ps) { +vecCT encrypted_search(lbcrypto::CryptoContext &cc, lbcrypto::PublicKey &pk, vecCT &epat, vecCT &etxt, int ps) { int64_t p(ps); OPENFHE_DEBUG_FLAG(false); @@ -174,12 +173,12 @@ vecCT encrypted_search(lbcrypto::CryptoContext &cc, lbcrypt OPENFHE_DEBUG("encrypting hct"); // The value of h would be "pow(d, M-1)%p" int64_t h = 1; - for (i = 0; i < M-1; i++) { - h = (h*d)%p; + for (i = 0; i < M - 1; i++) { + h = (h * d) % p; } CT hct = encrypt_repeated_integer(cc, pk, h, nrep); // encrypted h - OPENFHE_DEBUG("encrypting first hashes" ); + OPENFHE_DEBUG("encrypting first hashes"); // Calculate the hash value of pattern and first window of text for (i = 0; i < M; i++) { auto tmp = encMultD(cc, phct); @@ -191,37 +190,36 @@ vecCT encrypted_search(lbcrypto::CryptoContext &cc, lbcrypt vecCT eres(0); // Slide the pattern over text one by one - OPENFHE_DEBUG("sliding" ); + OPENFHE_DEBUG("sliding"); for (i = 0; i <= N - M; i++) { - cout<EvalSub(phct, thct)); + // Check the hash values of current window of text and pattern + // If the hash values match then only check for characters on by one + // subtract the two hashes, zero is equality + OPENFHE_DEBUG("sub"); + eres.push_back(cc->EvalSub(phct, thct)); - // Calculate hash value for next window of text: Remove leading digit, - // add trailing digit - if ( i < N - M ) { - OPENFHE_DEBUG("rehash" ); - //th = (d * (th - txt[i] * h) + txt[i + M]) % p; + // Calculate hash value for next window of text: Remove leading digit, + // add trailing digit + if (i < N - M) { + OPENFHE_DEBUG("rehash"); + //th = (d * (th - txt[i] * h) + txt[i + M]) % p; - auto tmp = encMultD(cc, - cc->EvalSub(thct, - cc->EvalMult(etxt[i], hct) - ) - ); - thct = cc->EvalAdd(tmp, etxt[i+M] ); + auto tmp = encMultD(cc, + cc->EvalSub(thct, + cc->EvalMult(etxt[i], hct) + ) + ); + thct = cc->EvalAdd(tmp, etxt[i + M]); - } + } } //end for return eres; } -int main() -{ +int main() { vecChar bigtxt; vecChar pat; @@ -238,11 +236,11 @@ int main() //cin>> textSize; textSize = 32; uint32_t offset(16); - cout << "Limiting search to "<::genCryptoContextBFVrns( - plaintextModulus, securityLevel, sigma, 0, multDepth, 0, OPTIMIZED); - */ - lbcrypto::CCParams parameters; - parameters.SetPlaintextModulus(plaintextModulus); - parameters.SetSecurityLevel(securityLevel); - parameters.SetStandardDeviation(sigma); - parameters.SetMultiplicativeDepth(multDepth); - - lbcrypto::CryptoContext cc = lbcrypto::GenCryptoContext(parameters); - - // Instantiate the crypto context + lbcrypto::CCParams params; + params.SetPlaintextModulus(plaintextModulus); + params.SetSecurityLevel(securityLevel); + params.SetMultiplicativeDepth(multDepth); + params.SetSecretKeyDist(UNIFORM_TERNARY); + auto cc = GenCryptoContext(params); // Enable features that you wish to use - cc->Enable(PKE); - cc->Enable(KEYSWITCH); - cc->Enable(LEVELEDSHE); + cc->Enable(PKE); + cc->Enable(LEVELEDSHE); - cout<<"Step 2 - Key Generation"<EvalMultKeyGen(keyPair.secretKey); - cout<<"Step 3 - Encryption"<MakePackedPlaintext(vin); + PT pt = cc->MakePackedPlaintext(vin); vin.clear(); CT ct = cc->Encrypt(keyPair.publicKey, pt); epat.push_back(ct); @@ -317,35 +305,35 @@ int main() //encrypt the text auto ringsize = cc->GetRingDimension(); - cout << "ringsize = "<MakePackedPlaintext(vin); + lbcrypto::Plaintext pt = cc->MakePackedPlaintext(vin); pt_len = pt->GetLength(); vin.clear(); CT ct = cc->Encrypt(keyPair.publicKey, pt); etxt.push_back(ct); } - cout<<"Step 4 - Encrypted string search"<Decrypt(keyPair.secretKey, e_itr, &ptresult); ptresult->SetLength(pt_len); @@ -354,15 +342,15 @@ int main() int i(0); int nfound(0); - for (auto val: vecResult) { + for (auto val : vecResult) { auto unpackedVal = val->GetPackedValue(); if (unpackedVal[0] == 0) { - cout<<"Pattern found at index "<< i << endl; + cout << "Pattern found at index " << i << endl; nfound++; } i++; } - cout<<"total occurances "< +#include +#include #include +#include #include #include - #include "openfhe.h" -#include "utils/debug.h" -#include "scheme/bfvrns/cryptocontext-bfvrns.h" -#include "gen-cryptocontext.h" using namespace std; -using namespace lbcrypto; //data types we will need -using CT = Ciphertext ; //ciphertext -using PT = Plaintext ; //plaintext +using CT = lbcrypto::Ciphertext; //ciphertext +using PT = lbcrypto::Plaintext; //plaintext using vecCT = vector; //vector of ciphertexts using vecPT = vector; //vector of plaintexts using vecInt = vector; // vector of ints using vecChar = vector; // vector of characters // d is the number of characters in input alphabet -const int32_t d = 256; - +const int32_t d = 256; + /* pat -> pattern txt -> text p -> A prime number @@ -37,39 +33,39 @@ const int32_t d = 256; // function to get string input from terminal and return as vector of char -void get_input_from_term(vecChar& a) { +void get_input_from_term(vecChar &a) { string cstr; - cin.ignore(numeric_limits::max(),'\n'); //flushes buffer + cin.ignore(numeric_limits::max(), '\n'); //flushes buffer cin >> ws; //discards white space std::getline(std::cin, cstr); - cout <<"Pattern is `"<> c) { - a.push_back(c); + a.push_back(c); } - cout <<"Read "< &cc, PublicKey &pk, int64_t in, size_t n){ - +CT encrypt_repeated_integer(lbcrypto::CryptoContext &cc, lbcrypto::PublicKey &pk, int64_t in, size_t n) { + vecInt v_in(n, in); - PT pt= cc->MakePackedPlaintext(v_in); + PT pt = cc->MakePackedPlaintext(v_in); CT ct = cc->Encrypt(pk, pt); return ct; } // helper function to multiply by constant 256 using binary tree addition -CT encMultD(CryptoContext &cc, CT in){ - if (d !=256){ - cout <<"error d not 256"< &cc, CT in) { + if (d != 256) { + cout << "error d not 256" << endl; + exit(-1); } auto tmp(in); - for (size_t i = 0; i< 8; i++ ){ - tmp = cc->EvalAdd(tmp, tmp); + for (size_t i = 0; i < 8; i++) { + tmp = cc->EvalAdd(tmp, tmp); } - - return(tmp); + + return (tmp); } //SIMD encrypted search -vecCT encrypted_search(CryptoContext &cc, PublicKey &pk, vecCT &epat, vecCT &etxt, int ps) { +vecCT encrypted_search(lbcrypto::CryptoContext &cc, lbcrypto::PublicKey &pk, vecCT &epat, vecCT &etxt, int ps) { int64_t p(ps); OPENFHE_DEBUG_FLAG(false); @@ -173,26 +169,26 @@ vecCT encrypted_search(CryptoContext &cc, PublicKey &pk, v size_t i; PT dummy; - + size_t nrep(cc->GetRingDimension()); - OPENFHE_DEBUG("encrypting small ct"); + OPENFHE_DEBUG("encrypting small ct"); CT phct = encrypt_repeated_integer(cc, pk, 0, nrep); // hash value for pattern CT thct = encrypt_repeated_integer(cc, pk, 0, nrep); // hash value for txt CT dhct = encrypt_repeated_integer(cc, pk, d, nrep); // d - OPENFHE_DEBUG("encrypting hct"); + OPENFHE_DEBUG("encrypting hct"); // The value of h would be "pow(d, M-1)%p" long h = 1; - for (i = 0; i < M-1; i++) { - h = (h*d)%p; + for (i = 0; i < M - 1; i++) { + h = (h * d) % p; } CT hct = encrypt_repeated_integer(cc, pk, h, nrep); // encrypted h - OPENFHE_DEBUG("encrypting first hashes" ); + OPENFHE_DEBUG("encrypting first hashes"); // Calculate the hash value of pattern and first window of text for (i = 0; i < M; i++) { - auto tmp = encMultD(cc, phct); + auto tmp = encMultD(cc, phct); phct = cc->EvalAdd(tmp, epat[i]); tmp = encMultD(cc, thct); @@ -201,36 +197,35 @@ vecCT encrypted_search(CryptoContext &cc, PublicKey &pk, v vecCT eres(0); // Slide the pattern over text one by one - OPENFHE_DEBUG("sliding" ); + OPENFHE_DEBUG("sliding"); for (i = 0; i <= N - M; i++) { - cout<EvalSub(phct, thct)); - + // Calculate hash value for next window of text: Remove leading digit, // add trailing digit - if ( i < N - M ) { - OPENFHE_DEBUG("rehash" ); + if (i < N - M) { + OPENFHE_DEBUG("rehash"); //th = (d * (th - txt[i] * h) + txt[i + M]) % p; auto tmp = encMultD(cc, - cc->EvalSub(thct, - cc->EvalMult(etxt[i], hct) - ) - ); + cc->EvalSub(thct, + cc->EvalMult(etxt[i], hct) + ) + ); - thct = cc->EvalAdd(tmp, etxt[i+M] ); + thct = cc->EvalAdd(tmp, etxt[i + M]); } } //end for return eres; } - -int main() -{ + +int main() { vecChar txt; vecChar pat; string infilename; @@ -246,200 +241,198 @@ int main() //cin>> maxNBatches; maxNBatches = 32; minNBatches = 10; - cout << "batching to "< parameters; - parameters.SetPlaintextModulus(plaintextModulus); - parameters.SetSecurityLevel(securityLevel); - parameters.SetStandardDeviation(sigma); - parameters.SetMultiplicativeDepth(multDepth); - lbcrypto::CryptoContext cc = lbcrypto::GenCryptoContext(parameters); + lbcrypto::CCParams params; + params.SetPlaintextModulus(plaintextModulus); + params.SetSecurityLevel(securityLevel); + params.SetMultiplicativeDepth(multDepth); + params.SetSecretKeyDist(UNIFORM_TERNARY); + auto cc = GenCryptoContext(params); - cc->Enable(PKE); - cc->Enable(KEYSWITCH); - cc->Enable(LEVELEDSHE); + cc->Enable(PKE); + cc->Enable(LEVELEDSHE); + cout << "Step 2 - Key Generation" << endl; - cout<<"Step 2 - Key Generation"<KeyGen(); - + // Generate the relinearization key cc->EvalMultKeyGen(keyPair.secretKey); // note we do not use rotation in this example so we don't need rotation keys - // but make them anyway + // but make them anyway // Generate the rotation evaluation keys - //cc->EvalAtIndexKeyGen(keyPair.secretKey, {1, 2, -1, -2}); + //cc->EvalAtIndexKeyGen(keyPair.secretKey, {1, 2, -1, -2}); - cout<<"Step 3 - Encryption"<GetRingDimension(); - cout << "Given ringsize = "<= txt.size()){ + if (largestIx >= txt.size()) { done = true; } else { nbatch++; - cout<<"increasing batch size to "< maxNBatches) { - cout<<"have to limit number of batches to "<= txt.size()) { + cout << i << '\r' << flush; + //build a vector out of the batches + for (size_t bat = 0; bat < ringsize; bat++) { + if (i + (unsigned) offset[bat] >= txt.size()) { vin.push_back('\0'); //null terminate } else { - vin.push_back(txt[i+offset[bat]]); + vin.push_back(txt[i + offset[bat]]); } } - Plaintext pt= cc->MakePackedPlaintext(vin); + lbcrypto::Plaintext pt = cc->MakePackedPlaintext(vin); pt_len = pt->GetLength(); vin.clear(); CT ct = cc->Encrypt(keyPair.publicKey, pt); etxt.push_back(ct); } - cout<<"encrypted "<MakePackedPlaintext(vin); - vin.clear(); - CT ct = cc->Encrypt(keyPair.publicKey, pt); - epat.push_back(ct); - } - - cout<<"Step 4 - Encrypted string search"<MakePackedPlaintext(vin); + vin.clear(); + CT ct = cc->Encrypt(keyPair.publicKey, pt); + epat.push_back(ct); + } + + cout << "Step 4 - Encrypted string search" << endl; + + TIC(auto + t2); vecCT eresult = encrypted_search(cc, keyPair.publicKey, epat, etxt, p); auto encrypted_time_ms = TOC_MS(t2); - cout<< "Encrypted execution time "<Decrypt(keyPair.secretKey, e_itr, &ptresult); - ptresult->SetLength(pt_len); - vecResult.push_back(ptresult); + for (auto e_itr : eresult) { + PT ptresult; + cc->Decrypt(keyPair.secretKey, e_itr, &ptresult); + ptresult->SetLength(pt_len); + vecResult.push_back(ptresult); } vecInt foundloc(0); for (size_t i = 0; i < vecResult.size(); i++) { auto unpackedVal = vecResult[i]->GetPackedValue(); - for (size_t jj = 0; jj< ringsize; jj++) { - if (unpackedVal[jj] == 0) { - auto loc = i + offset[jj]; - foundloc.push_back(loc); + for (size_t j = 0; j < ringsize; j++) { + if (unpackedVal[j] == 0) { + auto loc = i + offset[j]; + foundloc.push_back(loc); } } } sort(foundloc.begin(), foundloc.end()); - cout<<"total occurences "<