#include "assert.hpp" #include "../include/odhtdb/Log.hpp" #include "../include/odhtdb/Database.hpp" #include "../include/odhtdb/Group.hpp" #include "../include/odhtdb/LocalUser.hpp" #include "../include/odhtdb/Encryption.hpp" #include "../include/odhtdb/Hash.hpp" #include "../include/odhtdb/hex2bin.hpp" #include "../include/odhtdb/bin2hex.hpp" #include "../include/odhtdb/DataView.hpp" #include #include #include #include using namespace std; using namespace chrono_literals; using namespace odhtdb; void testBinHexConvert() { DataView input { (void*)"hello", 5 }; string inputHex = bin2hex((const char*)input.data, input.size); assertEquals("68656c6c6f", inputHex); string inputBin = hex2bin(inputHex.c_str(), inputHex.size()); if(inputBin.size() != input.size) { string errMsg = "Expected input converted to hex and then back to binary size to be 5, was: "; errMsg += to_string(inputBin.size()); fail(errMsg); } if(memcmp(input.data, inputBin.data(), input.size) != 0) { string errMsg = "Expected input converted to hex and then back to binary to be same as original input ('hello'), was: "; errMsg += string(inputBin.c_str(), inputBin.size()); fail(errMsg); } } void testHash() { Hash hash("odhtdb", 6); string hashHex = hash.toString(); assertEquals("a7b30ec8ab92de60e551b26bb8f78d315697f84dd7f5549a143477e095ec934f", hashHex); Log::debug("hash of 'odhtdb' is: a7b30ec8ab92de60e551b26bb8f78d315697f84dd7f5549a143477e095ec934f"); } void testSignData(LocalUser *localUser) { std::string publicKeyStr = localUser->getPublicKey().toString(); Log::debug("Local user public key: %s", publicKeyStr.c_str()); std::string privateKeyStr = localUser->getPrivateKey().toString(); Log::debug("Local user private key: %s", privateKeyStr.c_str()); string expectedUnsignedData = "hello, world!"; string signedData = localUser->getPrivateKey().sign(DataView((void*)expectedUnsignedData.data(), expectedUnsignedData.size())); assertEquals(SIGNED_HASH_SIZE + expectedUnsignedData.size(), signedData.size()); string unsignedData = localUser->getPublicKey().unsign(DataView((void*)signedData.data(), signedData.size())); assertEquals(expectedUnsignedData, unsignedData); try { Signature::KeyPair anotherKeyPair; anotherKeyPair.getPublicKey().unsign(DataView((void*)signedData.data(), signedData.size())); fail("Expected unsign to fail since the data was not signed with the private key matching given public key"); } catch (UnsignWrongKeyException &e) { } catch (exception &e) { string errMsg = "Expected unsign to fail with UnsignWrongKeyException, fail reason: "; errMsg += e.what(); fail(errMsg); } try { Signature::KeyPair anotherKeyPair; anotherKeyPair.getPublicKey().unsign(DataView((void*)signedData.data(), 3)); fail("Expected unsign to fail since the (signed) data is too small to have been signed (signed hash is 64 bytes)"); } catch (UnsignInvalidSizeException &e) { } catch (exception &e) { string errMsg = "Expected unsign to fail with UnsignInvalidSizeException, fail reason: "; errMsg += e.what(); fail(errMsg); } } void testEncryption() { const char *message = "hello, world!"; const unsigned long long messageLength = 13; Encryption encryption(DataView((void*)message, messageLength)); Decryption decryption(encryption.getCipherText(), encryption.getNonce(), encryption.getKey()); assertEquals(messageLength, decryption.getDecryptedText().size); assertEquals(0, strncmp(message, (const char*)decryption.getDecryptedText().data, messageLength)); } void testCachedIdentity() { pair, shared_ptr> identity = dht::crypto::generateIdentity(); dht::Blob privateKeyData = identity.first->serialize(); printf("Private key size: %d, serialized data: %s\n", privateKeyData.size(), Hash(privateKeyData.data(), privateKeyData.size()).toString().c_str()); dht::crypto::PrivateKey privateKeyDeserialized(privateKeyData); privateKeyData = identity.first->serialize(); printf("Private key size: %d, serialized data: %s\n", privateKeyData.size(), Hash(privateKeyData.data(), privateKeyData.size()).toString().c_str()); dht::Blob certificateData; identity.second->pack(certificateData); printf("Certificate data size: %d, serialized data: %s\n", certificateData.size(), Hash(certificateData.data(), certificateData.size()).toString().c_str()); dht::crypto::Certificate certificateDeserialized(certificateData); certificateData.clear(); identity.second->pack(certificateData); printf("Certificate data size: %d, serialized data: %s\n", certificateData.size(), Hash(certificateData.data(), certificateData.size()).toString().c_str()); } int main() { Log::debug("Starting tests..."); testCachedIdentity(); testBinHexConvert(); testHash(); testEncryption(); LocalUser *localUser = LocalUser::create(Signature::KeyPair(), "dec05eba", nullptr); testSignData(localUser); // TODO: Setup local bootstrap node for tests Database database("bootstrap.ring.cx", 4222, "storage"); database.setOnCreateNodeCallback([](const DatabaseCreateNodeRequest &request) { Log::debug("Create node callback"); }); database.setOnAddNodeCallback([](const DatabaseAddNodeRequest &request) { Log::debug("Add node callback"); }); database.setOnAddUserCallback([](const DatabaseAddUserRequest &request) { Log::debug("Add user callback"); }); auto databaseCreateResponse = database.create("adminUserName", "latenight"); DatabaseNode databaseNode(databaseCreateResponse->getNodeEncryptionKey(), databaseCreateResponse->getRequestHash()); auto adminUser = (LocalUser*)databaseCreateResponse->getNodeAdminUser(); database.addData(databaseNode, adminUser, DataView{ (void*)"hello, world!", 13 }); database.addUser(databaseNode, adminUser, localUser->getName(), localUser->getPublicKey(), adminUser->getGroups()[0]); localUser->addToGroup(adminUser->getGroups()[0]); database.addData(databaseNode, localUser, DataView{ (void*)"hello, aaald!", 13 }); database.commit(); database.seed(databaseNode); auto start = chrono::high_resolution_clock::now(); while(chrono::high_resolution_clock::now() - start < 3s) { this_thread::sleep_for(10ms); } return 0; }