#include "../include/Database.hpp" #include "../include/Group.hpp" #include "../include/LocalUser.hpp" #include "../include/Encryption.hpp" #include #include #include using namespace std; using namespace chrono_literals; using namespace odhtdb; #define assertEquals(expected, actual) do { if((expected) != (actual)) { fprintf(stderr, "Assert failed:\nExpected: %s, actual: %s\n", #expected, #actual); exit(1); } } while(0) void fail(const string &errMsg) { fprintf(stderr, "Fail:\n%.*s\n", errMsg.size(), errMsg.c_str()); } void testSignData(LocalUser *localUser) { std::string publicKeyStr = localUser->getPublicKey().toString(); printf("Local user public key: %s\n", publicKeyStr.c_str()); std::string privateKeyStr = localUser->getPrivateKey().toString(); printf("Local user private key: %s\n", 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() { EncryptionKey encryptionKey; generateEncryptionKey(&encryptionKey); const char *message = "hello, world!"; const unsigned long long messageLength = 13; EncryptedData encryptedData; int encrypted = encrypt(&encryptedData, &encryptionKey, message, messageLength); if(encrypted != 0) fail("Failed to encrypt data"); std::string decryptedText; int decrypted = decrypt(&decryptedText, &encryptionKey, &encryptedData); if(decrypted != 0) fail("Failed to decrypt data"); assertEquals(messageLength, decryptedText.size()); assertEquals(0, strncmp(message, decryptedText.c_str(), messageLength)); } int main() { LocalUser *localUser = LocalUser::create(Signature::KeyPair(), "dec05eba"); testSignData(localUser); testEncryption(); // TODO: For tests, dont run against bootstrap.ring.cx. // Run against a bootstrap node made only for testing which doesn't persist added data. Database database("bootstrap.ring.cx", 4222, "storage"); database.seed(); database.create(localUser, "galax.channel.latenight.chat"); const char *data = "hello, world!"; database.add(localUser, "galax.channel.latenight.chat", DataView{ (void*)data, strlen(data) }); database.commit(); auto start = chrono::high_resolution_clock::now(); while(chrono::high_resolution_clock::now() - start < 5s) { this_thread::sleep_for(10ms); } return 0; }