Skip to content

Commit

Permalink
fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
xbw886 committed Feb 11, 2025
1 parent 5b1ecae commit e16b85d
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 121 deletions.
40 changes: 40 additions & 0 deletions yacl/examples/sse/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Introduction

This folder contains the implementation of searchable symmetric encryption.

## Reference paper

https://eprint.iacr.org/2013/169.pdf

### Description

This paper proposes a highly scalable searchable symmetric encryption (SSE) scheme that aims to solve the search problem in large-scale encrypted datasets, especially to support Boolean queries (e.g., logical operations such as AND, OR, NOT, etc.). While traditional SSE schemes usually support only simple keyword searches, this scheme is able to handle more complex Boolean queries by improving the index structure and query processing, allowing users to combine multiple keywords for searching.

## Implemention

1. **T-Set Instantiation**
- `tset.h`
- `tset.cc`
- `tset_test.cc`
2. **OXT: Oblivious Cross-Tags Protocol**
- `sse.h`
- `sse.cc`
- Test:`sse_test.cc`

## Test

1. To test tset:`bazel test //yacl/examples/sse/tset_test`
2. To test sse:`bazel test //yacl/examples/sse/sse_test`

## Data Set

Census Income Dataset
https://tianchi.aliyun.com/dataset/111479







###
50 changes: 25 additions & 25 deletions yacl/examples/sse/sse.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,45 +17,33 @@
namespace examples::sse {

Sse::Sse(int bucket_size, int slot_size, int lambda, int n_lambda)
: iv_(yacl::crypto::RandU32()),
tset_(bucket_size, slot_size, lambda, n_lambda) {
: tset_(bucket_size, slot_size, lambda, n_lambda) {
Initialize();
}

// EDBSetup
std::pair<std::vector<std::vector<TSet::Record>>, std::string> Sse::EDBSetup() {
ProcessAndUpdateTAndXSet();
auto [TSet, Kt] = tset_.TSetSetup(T_, keywords_);
auto Kt = tset_.TSetSetup(T_, keywords_);
auto TSet = tset_.GetTSet();
TSet_ = TSet;
k_map_["Kt"] = Kt;
return {TSet, Kt};
}

// SaveEDB
std::tuple<std::map<std::string, std::string>,
std::vector<std::vector<TSet::Record>>,
std::vector<yacl::crypto::EcPoint>>
Sse::SaveEDB(const std::string& k_map_file, const std::string& tset_file,
const std::string& xset_file) {
void Sse::SaveEDB(const std::string& k_map_file, const std::string& tset_file,
const std::string& xset_file) {
SaveKeys(k_map_, k_map_file);
SaveTSet(TSet_, tset_file);
SaveXSet(XSet_, xset_file, ec_group_);
return {k_map_, TSet_, XSet_};
}

// LoadEDB
std::tuple<std::map<std::string, std::string>,
std::vector<std::vector<TSet::Record>>,
std::vector<yacl::crypto::EcPoint>>
Sse::LoadEDB(const std::string& k_map_file, const std::string& tset_file,
const std::string& xset_file) {
void Sse::LoadEDB(const std::string& k_map_file, const std::string& tset_file,
const std::string& xset_file) {
k_map_ = LoadKeys(k_map_file);
TSet_ = LoadTSet(tset_file);
XSet_ = LoadXSet(xset_file, ec_group_);
return {k_map_, TSet_, XSet_};
}

// SearchProtocol
std::vector<std::string> Sse::SearchProtocol(
const std::vector<std::string>& keywords_Search) {
if (keywords_Search.empty()) {
Expand Down Expand Up @@ -133,19 +121,28 @@ std::vector<std::string> Sse::SearchProtocol(
auto Ke_mac = hmac_F_SSE_Search_Ks.CumulativeMac();
uint128_t Ke = ConvertToUint128(Ke_mac);
for (const auto& e : E) {
std::vector<uint8_t> ind = AesCtrDecrypt(e, Ke, iv_);
__uint128_t iv = GetIVForE(e);
std::vector<uint8_t> ind = AesCtrDecrypt(e, Ke, iv);
std::string ind_string(ind.begin(), ind.end());
std::cout << "Found match: " << ind_string << std::endl;
results.push_back(ind_string);
}

return results;
}

Sse::~Sse() { ec_group_.reset(); }

// ! private functions

__uint128_t Sse::GetIVForE(const std::vector<uint8_t>& e) const {
for (const auto& pair : IV_) {
if (pair.first == e) {
return pair.second;
}
}
throw std::runtime_error("IV not found for the given e");
}

bool Sse::IsInXSet(const std::unique_ptr<yacl::crypto::EcGroup>& ec_group,
const yacl::crypto::EcPoint& xtag,
const std::vector<yacl::crypto::EcPoint>& XSet) {
Expand Down Expand Up @@ -219,7 +216,10 @@ void Sse::ProcessAndUpdateTAndXSet() {

// append (e, y) to t.
std::vector<uint8_t> ind_vector(ind.begin(), ind.end());
std::vector<uint8_t> e = AesCtrEncrypt(ind_vector, Ke, iv_);

__uint128_t iv = yacl::crypto::RandU128();
std::vector<uint8_t> e = AesCtrEncrypt(ind_vector, Ke, iv);
IV_.push_back(std::make_pair(e, iv));
t.push_back(std::make_pair(e, y.ToString()));

// add xtag to XSet.
Expand All @@ -229,7 +229,7 @@ void Sse::ProcessAndUpdateTAndXSet() {

c++;
}
T_[keyword] = t;
T_.emplace(keyword, std::move(t));
}
}

Expand Down Expand Up @@ -440,10 +440,10 @@ std::map<std::string, std::string> Sse::LoadKeys(const std::string& file_path) {
std::string value(value_size, '\0');
K_file_read.read(&value[0], value_size);

K_map_read[key] = value;
K_map_read.emplace(key, std::move(value));
}
K_file_read.close();
std::cout << "The key has been successfully read from the file."
std::cout << "The keys have been successfully read from the file."
<< std::endl;
} else {
std::cerr << "Unable to open file: " << file_path << std::endl;
Expand Down
43 changes: 23 additions & 20 deletions yacl/examples/sse/sse.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,46 +40,48 @@ class Sse {
Sse(int bucket_size = 8, int slot_size = 8, int lambda = 128,
int n_lambda = 256);

// Setup the Encrypted Database (EDB)
std::pair<std::vector<std::vector<TSet::Record>>, std::string> EDBSetup();

std::tuple<std::map<std::string, std::string>,
std::vector<std::vector<TSet::Record>>,
std::vector<yacl::crypto::EcPoint>>
SaveEDB(const std::string& k_map_file = "/tmp/sse_test_data/K_map.bin",
const std::string& tset_file = "/tmp/sse_test_data/TSet.bin",
const std::string& xset_file = "/tmp/sse_test_data/XSet.bin");
std::tuple<std::map<std::string, std::string>,
std::vector<std::vector<TSet::Record>>,
std::vector<yacl::crypto::EcPoint>>
LoadEDB(const std::string& k_map_file = "/tmp/sse_test_data/K_map.bin",
const std::string& tset_file = "/tmp/sse_test_data/TSet.bin",
const std::string& xset_file = "/tmp/sse_test_data/XSet.bin");
// Save the Encrypted Database (EDB) to files
void SaveEDB(const std::string& k_map_file, const std::string& tset_file,
const std::string& xset_file);
// Load the Encrypted Database (EDB) from files
void LoadEDB(const std::string& k_map_file, const std::string& tset_file,
const std::string& xset_file);

// Perform the Search Protocol (OXT: Oblivious Cross-Tags Protocol)
std::vector<std::string> SearchProtocol(
const std::vector<std::string>& keywords);

~Sse();

private:
// Get the IV for a given encrypted value
__uint128_t GetIVForE(const std::vector<uint8_t>& e) const;

// Check if a given xtag is in the XSet
bool IsInXSet(const std::unique_ptr<yacl::crypto::EcGroup>& ec_group,
const yacl::crypto::EcPoint& xtag,
const std::vector<yacl::crypto::EcPoint>& XSet);
void Initialize();
void ProcessAndUpdateTAndXSet();

std::tuple<std::vector<std::string>,
std::vector<std::pair<std::string, std::string>>,
std::unordered_map<std::string, std::vector<std::string>>>
static std::tuple<std::vector<std::string>,
std::vector<std::pair<std::string, std::string>>,
std::unordered_map<std::string, std::vector<std::string>>>
ProcessAndSaveCSV(const std::string& file_path);
uint128_t ConvertToUint128(const std::vector<uint8_t>& mac);
std::string VectorToString(const std::vector<uint8_t>& vec);
std::vector<std::string> FetchKeysByValue(
static uint128_t ConvertToUint128(const std::vector<uint8_t>& mac);
static std::string VectorToString(const std::vector<uint8_t>& vec);
// Fetch keys by value from the reverse index
static std::vector<std::string> FetchKeysByValue(
const std::unordered_map<std::string, std::vector<std::string>>&
reverseIndex,
const std::string& value);

// Encrypt plaintext using AES-CTR
std::vector<uint8_t> AesCtrEncrypt(const std::vector<uint8_t>& plaintext,
const uint128_t& key, const uint128_t& iv);
// Decrypt ciphertext using AES-CTR
std::vector<uint8_t> AesCtrDecrypt(const std::vector<uint8_t>& ciphertext,
const uint128_t& key, const uint128_t& iv);

Expand All @@ -90,13 +92,13 @@ class Sse {
void SaveXSet(const std::vector<yacl::crypto::EcPoint>& XSet,
const std::string& file_path,
const std::unique_ptr<yacl::crypto::EcGroup>& ec_group);

std::map<std::string, std::string> LoadKeys(const std::string& file_path);
std::vector<std::vector<TSet::Record>> LoadTSet(const std::string& file_path);
std::vector<yacl::crypto::EcPoint> LoadXSet(
const std::string& file_path,
const std::unique_ptr<yacl::crypto::EcGroup>& ec_group);

uint128_t iv_;
std::vector<std::string> keywords_;
std::vector<std::pair<std::string, std::string>> keyValuePairs_;
std::unordered_map<std::string, std::vector<std::string>> reverseIndex_;
Expand All @@ -107,6 +109,7 @@ class Sse {
T_;
std::vector<yacl::crypto::EcPoint> XSet_;
std::vector<std::vector<TSet::Record>> TSet_;
std::vector<std::pair<std::vector<uint8_t>, __uint128_t>> IV_;

TSet tset_;
};
Expand Down
9 changes: 5 additions & 4 deletions yacl/examples/sse/sse_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,13 @@ TEST_F(SseTest, SaveAndLoadEDB) {
FAIL() << "Failed to create directory: " << test_dir;
}

auto [k_map, tset, xset] = sse_->SaveEDB(
test_dir + "K_map.bin", test_dir + "TSet.bin", test_dir + "XSet.bin");
sse_->SaveEDB(test_dir + "K_map.bin", test_dir + "TSet.bin",
test_dir + "XSet.bin");

auto new_sse = std::make_unique<Sse>();
auto [loaded_k_map, loaded_tset, loaded_xset] = new_sse->LoadEDB(
test_dir + "K_map.bin", test_dir + "TSet.bin", test_dir + "XSet.bin");

new_sse->LoadEDB(test_dir + "K_map.bin", test_dir + "TSet.bin",
test_dir + "XSet.bin");

auto results_after = new_sse->SearchProtocol(keyword);

Expand Down
Loading

0 comments on commit e16b85d

Please sign in to comment.