1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
#include "../include/Database.hpp"
#include "../include/Group.hpp"
#include "../include/LocalUser.hpp"
#include "../include/Encryption.hpp"
#include <vector>
#include <chrono>
#include <thread>
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;
}
|