Skip to content

Commit

Permalink
Merge pull request sharathvemula#6 from sharathvemula/newWaffle
Browse files Browse the repository at this point in the history
Added randomness while pushing data and added PRF, non-uniform encryp…
  • Loading branch information
sharathvemula authored Feb 17, 2023
2 parents 9c83d58 + 60b6f4a commit 16d079d
Show file tree
Hide file tree
Showing 35 changed files with 167 additions and 27 deletions.
Binary file modified waffleClient/bin/proxy_benchmark
Binary file not shown.
Binary file modified waffleClient/bin/proxy_server
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
77 changes: 76 additions & 1 deletion waffleClient/proxy/src/encryption_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ encryption_engine::encryption_engine() {
};

encryption_engine::encryption_engine(const encryption_engine& enc_engine) {
encryption_string_ = enc_engine.encryption_string_;
encryption_key_ = (unsigned char *)enc_engine.encryption_string_.c_str();
iv_ = (unsigned char *)enc_engine.iv_string_.c_str();
skey_ = NULL;
Expand Down Expand Up @@ -518,4 +519,78 @@ std::string encryption_engine::hmac(const std::string &key) {
int res = hmac_it((byte *)key.c_str(), key.size(), &val, &val_len, skey_);
std::string str = std::string((const char *)val, val_len);
return str;
};
};

std::string encryption_engine::encryptNonDeterministicHelper(const std::string& plaintext, const std::string& key) {
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();

// Initialize the encryption context
EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, (const unsigned char*)key.c_str(), nullptr);

// Generate a random IV
unsigned char iv[EVP_MAX_IV_LENGTH];
RAND_bytes(iv, EVP_MAX_IV_LENGTH);

// Set the IV in the encryption context
EVP_EncryptInit_ex(ctx, nullptr, nullptr, nullptr, iv);

// Allocate memory for the ciphertext
std::string ciphertext(EVP_MAX_BLOCK_LENGTH + plaintext.length(), '\0');

// Perform the encryption
int len;
EVP_EncryptUpdate(ctx, (unsigned char*)ciphertext.data(), &len, (const unsigned char*)plaintext.c_str(), plaintext.length());
ciphertext.resize(len);

// Finalize the encryption and append the padding
EVP_EncryptFinal_ex(ctx, (unsigned char*)ciphertext.data() + len, &len);
ciphertext.resize(len + ciphertext.length());

// Concatenate the IV to the ciphertext
ciphertext.insert(0, (char*)iv, EVP_MAX_IV_LENGTH);

EVP_CIPHER_CTX_free(ctx);

return ciphertext;
};

std::string encryption_engine::decryptNonDeterministicHelper(const std::string& ciphertext, const std::string& key) {
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();

// Extract the IV from the ciphertext
unsigned char iv[EVP_MAX_IV_LENGTH];
std::string ciphertextWithoutIV = ciphertext.substr(EVP_MAX_IV_LENGTH, std::string::npos);
ciphertextWithoutIV.substr(0, EVP_MAX_IV_LENGTH).copy((char*)iv, EVP_MAX_IV_LENGTH, 0);

// Initialize the decryption context
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, (const unsigned char*)key.c_str(), nullptr);

// Set the IV in the decryption context
EVP_DecryptInit_ex(ctx, nullptr, nullptr, nullptr, iv);

// Allocate memory for the plaintext
std::string plaintext(ciphertextWithoutIV.length(), '\0');

// Perform the decryption
int len1 = 0, len2 = 0;
EVP_DecryptUpdate(ctx, (unsigned char*)plaintext.data(), &len1, (const unsigned char*)ciphertextWithoutIV.c_str(), ciphertextWithoutIV.length());
EVP_DecryptFinal_ex(ctx, (unsigned char*)plaintext.data() + len1, &len2);
plaintext.resize(len1 + len2);

EVP_CIPHER_CTX_free(ctx);

return plaintext;
}


std::string encryption_engine::encryptNonDeterministic(const std::string &plain_text) {
return encryptNonDeterministicHelper(plain_text, encryption_string_);
};

std::string encryption_engine::decryptNonDeterministic(const std::string &cipher_text){
return decryptNonDeterministicHelper(cipher_text, encryption_string_);
};

std::string encryption_engine::getencryption_string_(){
return encryption_string_;
}
6 changes: 6 additions & 0 deletions waffleClient/proxy/src/encryption_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ class encryption_engine {
std::string encrypt(const std::string &plain_text);
std::string decrypt(const std::string &cipher_text);
std::string hmac(const std::string &key);
std::string encryptNonDeterministic(const std::string &plain_text);
std::string decryptNonDeterministic(const std::string &cipher_text);
std::string getencryption_string_();


private:
void handle_errors();
Expand All @@ -43,6 +47,8 @@ class encryption_engine {
void print_it(const char* label, const byte* buff, size_t len);
int make_keys(EVP_PKEY** skey, EVP_PKEY** vkey);
int hmac_it(const byte* msg, size_t mlen, byte** val, size_t* vlen, EVP_PKEY* pkey);
std::string encryptNonDeterministicHelper(const std::string& plaintext, const std::string& key);
std::string decryptNonDeterministicHelper(const std::string& ciphertext, const std::string& key);

std::string encryption_string_;
std::string iv_string_;
Expand Down
110 changes: 84 additions & 26 deletions waffleClient/proxy/src/waffle_proxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@

#include "waffle_proxy.h"

void randomize_map(const std::unordered_map<std::string, std::string>& input_map, std::vector<std::string>& keys, std::vector<std::string>& values) {
for (const auto& it : input_map) {
keys.push_back(it.first);
values.push_back(it.second);
}
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(keys.begin(), keys.end(), g);
std::shuffle(values.begin(), values.end(), g);
}

#define rdtscllProxy(val) do { \
unsigned int __a,__d; \
__asm__ __volatile__("rdtsc" : "=a" (__a), "=d" (__d)); \
Expand Down Expand Up @@ -80,13 +91,11 @@ void waffle_proxy::init(const std::vector<std::string> &keys, const std::vector<
std::vector<std::string> keysCacheUnencrypted;

if (server_type_ == "redis") {
std::cout << "Storage interface is starting with Redis DB " << std::endl;
storage_interface_ = std::make_shared<redis>(server_host_name_, server_port_);
cpp_redis::network::set_default_nb_workers(std::min(10, p_threads_));
std::cout << "Storage interface is initialized with Redis DB " << std::endl;
}


for (int i = 1; i < server_count_; i++) {
storage_interface_->add_server(server_host_name_, server_port_+i);
}
Expand All @@ -108,7 +117,7 @@ void waffle_proxy::init(const std::vector<std::string> &keys, const std::vector<
std::cout << "Keys size in init() is " << keys.size() << std::endl;
std::unordered_map<std::string, std::string> keyValueMap;
for(int i=0;i<keys.size();++i) {
keyValueMap[keys[i]] = values[i];
keyValueMap[encryption_engine_.hmac(keys[i])] = encryption_engine_.encryptNonDeterministic(values[i]);
realBst.insert(keys[i]);
}

Expand All @@ -123,41 +132,83 @@ void waffle_proxy::init(const std::vector<std::string> &keys, const std::vector<
temp.insert(keys[index]);
keysCacheUnencrypted.push_back(keys[index]);
valuesCache.push_back(values[index]);
keyValueMap.erase(keys[index]);
keyValueMap.erase(encryption_engine_.hmac(keys[index]));
}
}

cache = Cache(keysCacheUnencrypted, valuesCache, cacheCapacity+R);

std::vector<std::string> fakeValues;
std::vector<std::string> fakeKeys;
for(int i=0; i < m; ) {
auto fakeKey = gen_random(rand()%15);
auto fakeKey = gen_random(rand()%10);
if(allKeys.find(fakeKey) == allKeys.end() && tempFakeKeys.find(fakeKey)==tempFakeKeys.end()) {
++i;
fakeBst.insert(fakeKey);
tempFakeKeys.insert(fakeKey);
auto tempFakeKey = fakeKey + '#' + std::to_string(fakeBst.getFrequency(fakeKey));
auto fakeKeyValue = encryption_engine_.encrypt(gen_random(rand()%15));
fakeKeys.push_back(tempFakeKey);
fakeValues.push_back(fakeKeyValue);
auto tempFakeKey = encryption_engine_.hmac(fakeKey + "#" + std::to_string(fakeBst.getFrequency(fakeKey)));
auto fakeKeyValue = encryption_engine_.encryptNonDeterministic(gen_random(rand()%10));
keyValueMap[tempFakeKey] = fakeKeyValue;
}
}

for(auto& it: keyValueMap) {
storage_interface_->put(it.first + "#" + std::to_string(realBst.getFrequency(it.first)), encryption_engine_.encrypt(it.second));
std::vector<std::string> redisKeys;
std::vector<std::string> redisValues;
randomize_map(keyValueMap, redisKeys, redisValues);

// for(auto& it: keyValueMap) {
// storage_interface_->put(it.first + "#" + std::to_string(realBst.getFrequency(it.first)), encryption_engine_.encryptNonDeterministic(it.second));
// }
std::vector<std::string> finalKeysRedis;
std::vector<std::string> finalValuesRedis;
for(int i=0;i<redisKeys.size();++i) {
finalKeysRedis.push_back(redisKeys[i]);
finalValuesRedis.push_back(redisValues[i]);
if(finalValuesRedis.size() == redisBulkLength) {
storage_interface_->put_batch(finalKeysRedis, finalValuesRedis);
finalValuesRedis.clear();
finalKeysRedis.clear();
}
}
if(finalValuesRedis.size() > 0) {
storage_interface_->put_batch(finalKeysRedis, finalValuesRedis);
}
storage_interface_->put_batch(fakeKeys, fakeValues);
threads_.push_back(std::thread(&waffle_proxy::clearThread, this));

auto test1 = encryption_engine_.encrypt("mynameissharath");
auto test2 = encryption_engine_.encrypt("mynameissharath");
//Tests for the encryption
auto test1 = encryption_engine_.hmac("mynameissharath");
auto test2 = encryption_engine_.hmac("mynameissharath");

if(test1 == test2) {
std::cout << "Encryption is same" << std::endl;
} else {
std::cout << "Encryption is not same" << std::endl;
}


auto test3 = encryption_engine_.encryptNonDeterministic("mynameissharath");
auto test4 = encryption_engine_.encryptNonDeterministic("mynameissharath");
if(test3 == test4) {
std::cout << "Non Deterministic Encryption is same" << std::endl;
} else {
std::cout << "Non Deterministic Encryption is not same and test3 is " << test3 << std::endl;
std::cout << "Non Deterministic Encryption is not same and test4 is " << test4 << std::endl;
}

std::cout << "Encryption string is " << encryption_engine_.getencryption_string_() << std::endl;

auto test5 = encryption_engine_.decryptNonDeterministic(test3);
auto test6 = encryption_engine_.decryptNonDeterministic(test4);
if(test5 == test6) {
std::cout << "Decryption is same and the value is " << std::endl;
for (char c : test5) {
std::cout << std::hex << (int)c;
}
std::cout << std::endl;
} else {
std::cout << "Decryption is not same and the value is " << test5 << std::endl;
std::cout << "Decryption is not same and the value is " << test6 << std::endl;
}
//Tests for the encryption ended

std::time_t end_time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
date_string = std::string(std::ctime(&end_time));
date_string = date_string.substr(0, date_string.rfind(":"));
Expand Down Expand Up @@ -213,14 +264,17 @@ void waffle_proxy::execute_batch(const std::vector<operation> &operations, std::
std::vector<std::string> storage_keys;
std::vector<std::string> writeBatchKeys;
std::vector<std::string> writeBatchValues;
std::unordered_map<std::string, std::string> readBatchMap;
uint64_t start, end;

if(latency) {
rdtscllProxy(start);
}
for(int i = 0; i < operations.size(); i++){
std::string key = operations[i].key;
storage_keys.push_back(key + "#" + std::to_string(realBst.getFrequency(key)));
auto stKey = enc_engine->hmac(key + "#" + std::to_string(realBst.getFrequency(key)));
readBatchMap[stKey] = key;
storage_keys.push_back(stKey);
realBst.incrementFrequency(key);
}

Expand All @@ -237,13 +291,17 @@ void waffle_proxy::execute_batch(const std::vector<operation> &operations, std::
// std::cout << "realKeysNotInCache size is " << realKeysNotInCache.size() << std::endl;

for(auto& iter: realKeysNotInCache) {
storage_keys.push_back(iter + "#" + std::to_string(realBst.getFrequency(iter)));
auto stKey = enc_engine->hmac(iter + "#" + std::to_string(realBst.getFrequency(iter)));
readBatchMap[stKey] = iter;
storage_keys.push_back(stKey);
realBst.incrementFrequency(iter);
}

for(int i=0;i<(D-operations.size());++i) {
auto fakeMinKey = fakeBst.getKeyWithMinFrequency();
storage_keys.push_back(fakeMinKey + "#" + std::to_string(fakeBst.getFrequency(fakeMinKey)));
auto stKey = enc_engine->hmac(fakeMinKey + "#" + std::to_string(fakeBst.getFrequency(fakeMinKey)));
readBatchMap[stKey] = fakeMinKey;
storage_keys.push_back(stKey);
fakeBst.incrementFrequency(fakeMinKey);
}

Expand All @@ -265,12 +323,12 @@ void waffle_proxy::execute_batch(const std::vector<operation> &operations, std::
if(i < (operations.size() + realKeysNotInCache.size())) {
// This means ith request is for real key
auto kv_pair = cache.evictLRElementFromCache();
writeBatchKeys.push_back(kv_pair[0] + "#" + std::to_string(realBst.getFrequency(kv_pair[0])));
writeBatchValues.push_back(enc_engine->encrypt(kv_pair[1]));
writeBatchKeys.push_back(enc_engine->hmac(kv_pair[0] + "#" + std::to_string(realBst.getFrequency(kv_pair[0]))));
writeBatchValues.push_back(enc_engine->encryptNonDeterministic(kv_pair[1]));

auto keyAboutToGoToCache = extractKey(storage_keys[i]);
auto keyAboutToGoToCache = readBatchMap[storage_keys[i]];
// std::cout << "Extracted key which is about to go to Cache is " << keyAboutToGoToCache << std::endl;
std::string valueAboutToGoToCache = enc_engine->decrypt(responses[i]);
std::string valueAboutToGoToCache = enc_engine->decryptNonDeterministic(responses[i]);
if(keyToPromiseMap.find(keyAboutToGoToCache) != keyToPromiseMap.end()) {
for(auto& it: keyToPromiseMap[keyAboutToGoToCache]) {
it->set_value(valueAboutToGoToCache);
Expand All @@ -282,9 +340,9 @@ void waffle_proxy::execute_batch(const std::vector<operation> &operations, std::
cache.insertIntoCache(keyAboutToGoToCache, valueAboutToGoToCache);
} else {
// Writing fake key values to DB
auto fakeWriteKey = extractKey(storage_keys[i]);
writeBatchKeys.push_back(fakeWriteKey + "#" + std::to_string(fakeBst.getFrequency(fakeWriteKey)));
writeBatchValues.push_back(enc_engine->encrypt("fakeValue"));
auto fakeWriteKey = readBatchMap[storage_keys[i]];
writeBatchKeys.push_back(enc_engine->hmac(fakeWriteKey + "#" + std::to_string(fakeBst.getFrequency(fakeWriteKey))));
writeBatchValues.push_back(enc_engine->encryptNonDeterministic(gen_random(rand()%10)));

}
}
Expand Down
1 change: 1 addition & 0 deletions waffleClient/proxy/src/waffle_proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class waffle_proxy : public proxy {
int D = 50;
int s = 25;
int m = 50;
int redisBulkLength = 524287;

private:
void create_security_batch(std::shared_ptr<queue <std::pair<operation, std::shared_ptr<std::promise<std::string>>>>> &op_queue,
Expand Down

0 comments on commit 16d079d

Please sign in to comment.