aboutsummaryrefslogtreecommitdiff
path: root/include/odhtdb
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-03-13 06:26:06 +0100
committerdec05eba <dec05eba@protonmail.com>2020-08-18 23:25:46 +0200
commit5a8727e34b938b70623ca865273fd81c7604b461 (patch)
treea2921e90aa454072dc58fced36b508f67f5d1226 /include/odhtdb
parent9ffc25c9d99fe86d4789108d1d8615ecb0388cc6 (diff)
Expose include dir
Diffstat (limited to 'include/odhtdb')
-rw-r--r--include/odhtdb/DataView.hpp30
-rw-r--r--include/odhtdb/Database.hpp153
-rw-r--r--include/odhtdb/DatabaseNode.hpp31
-rw-r--r--include/odhtdb/DatabaseStorage.hpp95
-rw-r--r--include/odhtdb/DhtKey.hpp19
-rw-r--r--include/odhtdb/Encryption.hpp64
-rw-r--r--include/odhtdb/Group.hpp45
-rw-r--r--include/odhtdb/Hash.hpp58
-rw-r--r--include/odhtdb/Key.hpp15
-rw-r--r--include/odhtdb/LocalUser.hpp29
-rw-r--r--include/odhtdb/Log.hpp12
-rw-r--r--include/odhtdb/Permission.hpp46
-rw-r--r--include/odhtdb/RemoteUser.hpp24
-rw-r--r--include/odhtdb/Signature.hpp126
-rw-r--r--include/odhtdb/StagedObject.hpp22
-rw-r--r--include/odhtdb/User.hpp38
-rw-r--r--include/odhtdb/bin2hex.hpp23
-rw-r--r--include/odhtdb/types.hpp22
-rwxr-xr-xinclude/odhtdb/utils.hpp6
19 files changed, 858 insertions, 0 deletions
diff --git a/include/odhtdb/DataView.hpp b/include/odhtdb/DataView.hpp
new file mode 100644
index 0000000..0ecf9fb
--- /dev/null
+++ b/include/odhtdb/DataView.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+#include "types.hpp"
+#include "Hash.hpp"
+#include <unordered_map>
+
+namespace odhtdb
+{
+ class DataView
+ {
+ public:
+ DataView() : data(nullptr), size(0) {}
+ DataView(void *_data, usize _size) : data(_data), size(_size) {}
+ bool operator == (const DataView &other) const;
+
+ void *data;
+ usize size;
+ };
+
+ struct DataViewHasher
+ {
+ size_t operator()(const DataView &dataView) const
+ {
+ return fnvHash((const unsigned char*)dataView.data, dataView.size);
+ }
+ };
+
+ template <typename ValueType>
+ using DataViewMap = std::unordered_map<DataView, ValueType, DataViewHasher>;
+}
diff --git a/include/odhtdb/Database.hpp b/include/odhtdb/Database.hpp
new file mode 100644
index 0000000..6bc7bc5
--- /dev/null
+++ b/include/odhtdb/Database.hpp
@@ -0,0 +1,153 @@
+#pragma once
+
+#include "types.hpp"
+#include "Key.hpp"
+#include "DataView.hpp"
+#include "DatabaseStorage.hpp"
+#include "Hash.hpp"
+#include "utils.hpp"
+#include "StagedObject.hpp"
+#include "Signature.hpp"
+#include "Permission.hpp"
+#include "DatabaseNode.hpp"
+#include <opendht/dhtrunner.h>
+#include <vector>
+#include <ntp/NtpClient.hpp>
+#include <boost/filesystem/path.hpp>
+#include <stdexcept>
+
+namespace odhtdb
+{
+ class User;
+ class LocalUser;
+ class Group;
+
+ class CommitCreateException : public std::runtime_error
+ {
+ public:
+ CommitCreateException(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ class CommitAddException : public std::runtime_error
+ {
+ public:
+ CommitAddException(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ class DatabaseCreateException : public std::runtime_error
+ {
+ public:
+ DatabaseCreateException(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ class DatabaseAddException : public std::runtime_error
+ {
+ public:
+ DatabaseAddException(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ enum class DatabaseOperation : u8
+ {
+ ADD_DATA,
+ ADD_USER
+ };
+
+ struct DatabaseCreateRequest
+ {
+ DISABLE_COPY(DatabaseCreateRequest)
+
+ u64 timestamp; // In microseconds
+ Group *creatorGroup;
+ std::string name;
+
+ DatabaseCreateRequest(u64 _timestamp, Group *_creatorGroup, std::string &&_name) :
+ timestamp(_timestamp),
+ creatorGroup(_creatorGroup),
+ name(std::move(_name))
+ {
+
+ }
+
+ DatabaseCreateRequest(DatabaseCreateRequest &&other)
+ {
+ timestamp = other.timestamp;
+ creatorGroup = other.creatorGroup;
+ name = std::move(other.name);
+
+ other.timestamp = 0;
+ other.creatorGroup = nullptr;
+ }
+ };
+
+ struct DatabaseAddRequest
+ {
+ DISABLE_COPY(DatabaseAddRequest)
+
+ u64 timestamp; // In microseconds
+ const User *creatorUser;
+ Decryption decryptedData;
+
+ DatabaseAddRequest(u64 _timestamp, const User *_creatorUser, Decryption &&_decryptedData) :
+ timestamp(_timestamp),
+ creatorUser(_creatorUser),
+ decryptedData(std::move(_decryptedData))
+ {
+
+ }
+
+ DatabaseAddRequest(DatabaseAddRequest &&other)
+ {
+ timestamp = other.timestamp;
+ creatorUser = other.creatorUser;
+ decryptedData = std::move(other.decryptedData);
+
+ other.timestamp = 0;
+ other.creatorUser = nullptr;
+ }
+ };
+
+ class DatabaseCreateResponse
+ {
+ public:
+ DatabaseCreateResponse(LocalUser *nodeAdminUser, const std::shared_ptr<char*> &key, const std::shared_ptr<Hash> &hash);
+
+ const LocalUser* getNodeAdminUser() const;
+ const std::shared_ptr<char*> getNodeEncryptionKey() const;
+ const std::shared_ptr<Hash> getRequestHash() const;
+ private:
+ LocalUser *nodeAdminUser;
+ std::shared_ptr<char*> key;
+ std::shared_ptr<Hash> hash;
+ };
+
+ class Database
+ {
+ public:
+ Database(const char *bootstrapNodeAddr, u16 port, boost::filesystem::path storageDir);
+ ~Database();
+
+ void seed(const std::shared_ptr<Hash> hash, const std::shared_ptr<char*> encryptionKey);
+ // Throws DatabaseCreateException on failure.
+ std::unique_ptr<DatabaseCreateResponse> create(const std::string &ownerName, const std::string &nodeName);
+ // Throws DatabaseAddException on failure
+ void addData(const DatabaseNode &nodeInfo, LocalUser *userToPerformActionWith, DataView dataToAdd);
+ // Throws PermissionDeniedException if user @userToPerformActionWith is not allowed to add user @userToAdd to group @groupToAddUserTo
+ void addUserToGroup(const DatabaseNode &nodeInfo, LocalUser *userToPerformActionWith, const std::string &userToAddName, const Signature::PublicKey &userToAddPublicKey, Group *groupToAddUserTo);
+ void commit();
+ private:
+ // Throws CommitCreateException on failure
+ void commitStagedCreateObject(const std::unique_ptr<StagedObject> &stagedObject);
+ // Throws CommitAddException on failure
+ void commitStagedAddObject(const std::unique_ptr<StagedObject> &stagedObject);
+ ntp::NtpTimestamp getSyncedTimestampUtc() const;
+ DatabaseCreateRequest deserializeCreateRequest(const std::shared_ptr<dht::Value> &value, const Hash &hash, const std::shared_ptr<char*> encryptionKey);
+ void deserializeAddRequest(const std::shared_ptr<dht::Value> &value, const Hash &requestDataHash, const std::shared_ptr<char*> encryptionKey);
+ bool listenCreateData(std::shared_ptr<dht::Value> value, const Hash &hash, const std::shared_ptr<char*> encryptionKey);
+ bool listenAddData(std::shared_ptr<dht::Value> value, const Hash &requestDataHash, const std::shared_ptr<char*> encryptionKey);
+ private:
+ dht::DhtRunner node;
+ std::vector<std::unique_ptr<StagedObject>> stagedCreateObjects;
+ std::vector<std::unique_ptr<StagedObject>> stagedAddObjects;
+ DatabaseStorage databaseStorage;
+ };
+}
diff --git a/include/odhtdb/DatabaseNode.hpp b/include/odhtdb/DatabaseNode.hpp
new file mode 100644
index 0000000..3ca4be3
--- /dev/null
+++ b/include/odhtdb/DatabaseNode.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "Hash.hpp"
+#include <memory>
+
+namespace odhtdb
+{
+ class DatabaseNode
+ {
+ public:
+ DatabaseNode(const std::shared_ptr<char*> &_encryptionKey, const std::shared_ptr<Hash> &_nodeHash) :
+ encryptionKey(_encryptionKey),
+ nodeHash(_nodeHash)
+ {
+
+ }
+
+ const std::shared_ptr<char*> getNodeEncryptionKey() const
+ {
+ return encryptionKey;
+ }
+
+ const std::shared_ptr<Hash> getRequestHash() const
+ {
+ return nodeHash;
+ }
+ private:
+ std::shared_ptr<char*> encryptionKey;
+ std::shared_ptr<Hash> nodeHash;
+ };
+}
diff --git a/include/odhtdb/DatabaseStorage.hpp b/include/odhtdb/DatabaseStorage.hpp
new file mode 100644
index 0000000..ad4f70b
--- /dev/null
+++ b/include/odhtdb/DatabaseStorage.hpp
@@ -0,0 +1,95 @@
+#pragma once
+
+#include "types.hpp"
+#include "Hash.hpp"
+#include "DataView.hpp"
+#include "Signature.hpp"
+#include "Encryption.hpp"
+#include <vector>
+#include <stdexcept>
+
+namespace odhtdb
+{
+ class Group;
+ class User;
+
+ struct DatabaseStorageObject
+ {
+ DataView data;
+ u64 createdTimestamp; // In microseconds
+ Signature::PublicKey creatorPublicKey;
+
+ DatabaseStorageObject(DataView &_data, u64 _timestamp, const Signature::PublicKey &_creatorPublicKey);
+ };
+
+ struct DatabaseStorageObjectList
+ {
+ DataView data;
+ u64 createdTimestamp; // In microseconds
+ std::vector<Group*> groups;
+ std::vector<DatabaseStorageObject*> objects;
+ };
+
+ struct DatabaseStorageQuarantineObject
+ {
+ DataView data;
+ u64 createdTimestamp; // In microseconds
+ u64 storedTimestamp; // In microseconds
+ Signature::PublicKey creatorPublicKey;
+
+ DatabaseStorageQuarantineObject(DataView &_data, u64 _timestamp, const Signature::PublicKey &_creatorPublicKey);
+ };
+
+ class DatabaseStorageAlreadyExists : public std::runtime_error
+ {
+ public:
+ DatabaseStorageAlreadyExists(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ class DatabaseStorageNotFound : public std::runtime_error
+ {
+ public:
+ DatabaseStorageNotFound(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ using DatabaseStorageMap = MapHash<DatabaseStorageObjectList*>;
+ using DatabaseStorageQuarantineMap = Signature::MapPublicKey<std::vector<DatabaseStorageQuarantineObject*>>;
+
+ class DatabaseStorage
+ {
+ public:
+ // Throws DatabaseStorageAlreadyExists if data with hash already exists
+ void createStorage(const Hash &hash, Group *creatorGroup, u64 timestamp, const u8 *data, usize dataSize);
+
+ // Throws DatabaseStorageNotFound if data with @nodeHash hash has not been created yet.
+ // Throws DatabaseStorageAlreadyExists if same data has been added before (hash of @data, in @dataHash)
+ void appendStorage(const Hash &nodeHash, const Hash &dataHash, const User *creatorUser, u64 timestamp, const u8 *data, usize dataSize);
+
+ // Throws DatabaseStorageAlreadyExists if same data has been added before (hash of @data, in @dataHash)
+ void addToQuarantine(const Hash &dataHash, const Signature::PublicKey &creatorPublicKey, u64 timestamp, const u8 *data, usize dataSize);
+
+ void addUser(User *user, const Hash &hash);
+
+ // Returns nullptr if no storage with provided hash exists
+ const DatabaseStorageObjectList* getStorage(const Hash &hash) const;
+
+ // Returns nullptr if no node with the user exists
+ const Hash* getNodeByUserPublicKey(const Signature::PublicKey &userPublicKey) const;
+
+ // Returns nullptr if no user with public key exists
+ const User* getUserByPublicKey(const Signature::PublicKey &userPublicKey) const;
+
+ // Returns nullptr if a group with id @groupId doesn't exist
+ Group* getGroupById(uint8_t groupId[16]);
+
+ // Update storage state (remove quarantine objects if they are too old, etc)
+ void update();
+ private:
+ DatabaseStorageMap storageMap;
+ DatabaseStorageQuarantineMap quarantineStorageMap;
+ SetHash storedDataHash; // Prevent duplicate data from being added
+ Signature::MapPublicKey<Hash*> userPublicKeyNodeMap;
+ Signature::MapPublicKey<const User*> publicKeyUserMap;
+ DataViewMap<Group*> groupByIdMap;
+ };
+}
diff --git a/include/odhtdb/DhtKey.hpp b/include/odhtdb/DhtKey.hpp
new file mode 100644
index 0000000..7c30ee3
--- /dev/null
+++ b/include/odhtdb/DhtKey.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "Hash.hpp"
+#include <opendht/infohash.h>
+
+namespace odhtdb
+{
+ class DhtKey
+ {
+ public:
+ DhtKey(const Hash &key);
+
+ const dht::InfoHash& getNewDataListenerKey();
+ const dht::InfoHash& getRequestOldDataKey();
+ private:
+ dht::InfoHash infoHash;
+ unsigned char firstByteOriginalValue;
+ };
+}
diff --git a/include/odhtdb/Encryption.hpp b/include/odhtdb/Encryption.hpp
new file mode 100644
index 0000000..4697b35
--- /dev/null
+++ b/include/odhtdb/Encryption.hpp
@@ -0,0 +1,64 @@
+#pragma once
+
+/*
+ * Encrypts/decrypts data using xchacha20-poly1305 ietf
+ */
+
+#include "DataView.hpp"
+#include "utils.hpp"
+#include <string>
+#include <stdexcept>
+
+namespace odhtdb
+{
+ const int NONCE_BYTE_SIZE = 24;
+ const int KEY_BYTE_SIZE = 32;
+
+ class EncryptionException : public std::runtime_error
+ {
+ public:
+ EncryptionException(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ class DecryptionException : public std::runtime_error
+ {
+ public:
+ DecryptionException(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ class Encryption
+ {
+ DISABLE_COPY(Encryption)
+ public:
+ // Throws EncryptionException on failure (or std::bad_alloc on failed memory allocation)
+ Encryption(const DataView &data, const DataView &additionalData = DataView(), const DataView &key = DataView());
+ ~Encryption();
+
+ DataView getKey() const;
+ DataView getNonce() const;
+ DataView getCipherText() const;
+ private:
+ unsigned char key[KEY_BYTE_SIZE];
+ unsigned char nonce[NONCE_BYTE_SIZE];
+ unsigned char *cipherText;
+ unsigned long long cipherTextLength;
+ };
+
+ class Decryption
+ {
+ DISABLE_COPY(Decryption)
+ public:
+ Decryption() : decryptedText(nullptr), decryptedTextLength(0) {}
+
+ // Throws DecryptionException on failure
+ Decryption(const DataView &data, const DataView &nonce, const DataView &key);
+ Decryption(Decryption &&other);
+ Decryption& operator=(Decryption &&other);
+ ~Decryption();
+
+ DataView getDecryptedText() const;
+ private:
+ unsigned char *decryptedText;
+ unsigned long long decryptedTextLength;
+ };
+}
diff --git a/include/odhtdb/Group.hpp b/include/odhtdb/Group.hpp
new file mode 100644
index 0000000..315961d
--- /dev/null
+++ b/include/odhtdb/Group.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include "types.hpp"
+#include "DataView.hpp"
+#include "Permission.hpp"
+#include <string>
+#include <vector>
+#include <stdexcept>
+
+namespace odhtdb
+{
+ class User;
+
+ class GroupNameTooLongException : public std::runtime_error
+ {
+ public:
+ GroupNameTooLongException(const std::string &groupName) :
+ std::runtime_error(std::string("The group name ") + groupName + " is longer than 255 bytes")
+ {
+
+ }
+ };
+
+
+
+ class Group
+ {
+ friend class User;
+ public:
+ Group(const std::string &name, uint8_t id[16], const Permission &permission);
+ ~Group();
+
+ const std::string& getName() const;
+ DataView getId() const;
+ const Permission& getPermission() const;
+ const std::vector<const User*>& getUsers() const;
+ private:
+ void addUser(const User *user);
+ private:
+ std::string name;
+ uint8_t id[16];
+ Permission permission;
+ std::vector<const User*> users;
+ };
+}
diff --git a/include/odhtdb/Hash.hpp b/include/odhtdb/Hash.hpp
new file mode 100644
index 0000000..9dce168
--- /dev/null
+++ b/include/odhtdb/Hash.hpp
@@ -0,0 +1,58 @@
+#pragma once
+
+#include "utils.hpp"
+#include <stdexcept>
+#include <unordered_map>
+#include <unordered_set>
+
+namespace odhtdb
+{
+ const int HASH_BYTE_SIZE = 32;
+
+ // Source: https://stackoverflow.com/a/11414104 (public license)
+ static size_t fnvHash(const unsigned char *key, int len)
+ {
+ size_t h = 2166136261;
+ for (int i = 0; i < len; i++)
+ h = (h * 16777619) ^ key[i];
+ return h;
+ }
+
+ class HashException : public std::runtime_error
+ {
+ public:
+ HashException(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ class Hash
+ {
+ public:
+ Hash();
+ // Throws HashException on failure
+ Hash(const void *input, const size_t inputSize);
+ Hash(const Hash &other);
+
+ void* getData() const { return (void*)data; }
+ size_t getSize() const { return HASH_BYTE_SIZE; }
+
+ size_t operator()() const;
+ bool operator==(const Hash &other) const;
+
+ std::string toString() const;
+ private:
+ char data[HASH_BYTE_SIZE];
+ };
+
+ struct HashHasher
+ {
+ size_t operator()(const Hash &hash) const
+ {
+ return hash();
+ }
+ };
+
+ template <typename ValueType>
+ using MapHash = std::unordered_map<Hash, ValueType, HashHasher>;
+
+ using SetHash = std::unordered_set<Hash, HashHasher>;
+}
diff --git a/include/odhtdb/Key.hpp b/include/odhtdb/Key.hpp
new file mode 100644
index 0000000..18971d1
--- /dev/null
+++ b/include/odhtdb/Key.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <opendht/infohash.h>
+
+namespace odhtdb
+{
+ class Key
+ {
+ public:
+ Key() {}
+ Key(const char *key) : hashedKey(dht::InfoHash::get(key)) {}
+
+ dht::InfoHash hashedKey;
+ };
+}
diff --git a/include/odhtdb/LocalUser.hpp b/include/odhtdb/LocalUser.hpp
new file mode 100644
index 0000000..d60cb38
--- /dev/null
+++ b/include/odhtdb/LocalUser.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "User.hpp"
+
+namespace odhtdb
+{
+ class LocalUser : public User
+ {
+ public:
+ static LocalUser* create(const Signature::KeyPair &keyPair, const std::string &name, Group *group)
+ {
+ return new LocalUser(keyPair, name, group);
+ }
+
+ const Signature::PublicKey& getPublicKey() const override
+ {
+ return keyPair.getPublicKey();
+ }
+
+ const Signature::PrivateKey& getPrivateKey() const
+ {
+ return keyPair.getPrivateKey();
+ }
+ private:
+ LocalUser(const Signature::KeyPair &_keyPair, const std::string &name, Group *group) : User(name, group), keyPair(_keyPair) {}
+ private:
+ Signature::KeyPair keyPair;
+ };
+}
diff --git a/include/odhtdb/Log.hpp b/include/odhtdb/Log.hpp
new file mode 100644
index 0000000..d09c2a2
--- /dev/null
+++ b/include/odhtdb/Log.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+namespace odhtdb
+{
+ class Log
+ {
+ public:
+ static void debug(const char *fmt, ...);
+ static void warn(const char *fmt, ...);
+ static void error(const char *fmt, ...);
+ };
+}
diff --git a/include/odhtdb/Permission.hpp b/include/odhtdb/Permission.hpp
new file mode 100644
index 0000000..1ae2642
--- /dev/null
+++ b/include/odhtdb/Permission.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+#include "types.hpp"
+#include <initializer_list>
+#include <stdexcept>
+
+namespace odhtdb
+{
+ class PermissionDeniedException : public std::runtime_error
+ {
+ public:
+ PermissionDeniedException(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ enum class PermissionType : u32
+ {
+ ADD_DATA = (1 << 0),
+ ADD_USER_SAME_LEVEL = (1 << 1),
+ ADD_USER_LOWER_LEVEL = (1 << 2),
+ ADD_GROUP = (1 << 3),
+ REMOVE_GROUP = (1 << 4)
+ };
+
+ const PermissionType ALL_PERMISSION_TYPES = (PermissionType)0xFFFFFFFF;
+
+ const u8 PERMISSION_LEVEL_ADMIN = 0;
+ const u8 PERMISSION_LEVEL_MODERATOR = 1;
+ const u8 PERMISSION_LEVEL_REGULAR_USER = 2;
+
+ class Permission
+ {
+ public:
+ // @permissionLevel is hierarchical access right. A group can only modify a group that has higher @permissionLevel value
+ Permission(u8 permissionLevel, std::initializer_list<PermissionType> permissions);
+
+ u8 getPermissionLevel() const { return permissionLevel; }
+ u32 getPermissionFlags() const { return permissionFlags; }
+ bool getFlag(PermissionType permissionType) const;
+ private:
+ u8 permissionLevel;
+ u32 permissionFlags;
+ };
+
+ static const Permission ADMIN_PERMISSION(PERMISSION_LEVEL_ADMIN, { ALL_PERMISSION_TYPES });
+ static const Permission REGULAR_USER_PERMISSION(PERMISSION_LEVEL_REGULAR_USER, { PermissionType::ADD_DATA });
+}
diff --git a/include/odhtdb/RemoteUser.hpp b/include/odhtdb/RemoteUser.hpp
new file mode 100644
index 0000000..181a4c4
--- /dev/null
+++ b/include/odhtdb/RemoteUser.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "User.hpp"
+
+namespace odhtdb
+{
+ class RemoteUser : public User
+ {
+ public:
+ static RemoteUser* create(const Signature::PublicKey &publicKey, const std::string &name, Group *group)
+ {
+ return new RemoteUser(publicKey, name, group);
+ }
+
+ const Signature::PublicKey& getPublicKey() const override
+ {
+ return publicKey;
+ }
+ private:
+ RemoteUser(const Signature::PublicKey &_publicKey, const std::string &name, Group *group) : User(name, group), publicKey(_publicKey){}
+ private:
+ Signature::PublicKey publicKey;
+ };
+}
diff --git a/include/odhtdb/Signature.hpp b/include/odhtdb/Signature.hpp
new file mode 100644
index 0000000..62c41c3
--- /dev/null
+++ b/include/odhtdb/Signature.hpp
@@ -0,0 +1,126 @@
+#pragma once
+
+#include "DataView.hpp"
+#include <stdexcept>
+#include <unordered_map>
+
+namespace odhtdb
+{
+ const int PUBLIC_KEY_NUM_BYTES = 32;
+ const int PRIVATE_KEY_NUM_BYTES = 64;
+ const int SIGNED_HASH_SIZE = 64;
+
+ class InvalidSignatureKeySize : public std::runtime_error
+ {
+ public:
+ InvalidSignatureKeySize(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ class SignatureGenerationException : public std::runtime_error
+ {
+ public:
+ SignatureGenerationException(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ class DataSignException : public std::runtime_error
+ {
+ public:
+ DataSignException(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ class UnsignException : public std::runtime_error
+ {
+ public:
+ UnsignException(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ virtual ~UnsignException(){}
+ };
+
+ class UnsignInvalidSizeException : public UnsignException
+ {
+ public:
+ UnsignInvalidSizeException(const std::string &errMsg) : UnsignException(errMsg) {}
+ };
+
+ class UnsignWrongKeyException : public UnsignException
+ {
+ public:
+ UnsignWrongKeyException(const std::string &errMsg) : UnsignException(errMsg) {}
+ };
+
+ namespace Signature
+ {
+ class PublicKey
+ {
+ friend class KeyPair;
+ public:
+ static PublicKey ZERO;
+
+ // Throws InvalidSignatureKeySize if size is not PUBLIC_KEY_NUM_BYTES
+ PublicKey(const char *data, size_t size);
+ PublicKey(const PublicKey &other);
+ PublicKey& operator=(const PublicKey &other);
+
+ const char* getData() const { return data; }
+ size_t getSize() const { return PUBLIC_KEY_NUM_BYTES; }
+
+ // Throws UnsignWrongKeyException if signed message was not signed using the matching private key of this public key.
+ // Throws UnsignInvalidSizeException if signed message is too small (< SIGNED_HASH_SIZE).
+ // Both exceptions are derived from UnsignException
+ std::string unsign(const DataView &signedMessage) const;
+
+ size_t operator()() const;
+ bool operator==(const PublicKey &other) const;
+
+ std::string toString() const;
+ private:
+ PublicKey(){}
+ private:
+ char data[PUBLIC_KEY_NUM_BYTES];
+ };
+
+ struct PublicKeyHasher
+ {
+ size_t operator()(const PublicKey &publicKey) const
+ {
+ return publicKey();
+ }
+ };
+
+ template <typename ValueType>
+ using MapPublicKey = std::unordered_map<PublicKey, ValueType, PublicKeyHasher>;
+
+ class PrivateKey
+ {
+ friend class KeyPair;
+ public:
+ // Throws InvalidSignatureKeySize if size is not PRIVATE_KEY_NUM_BYTES
+ PrivateKey(const char *data, size_t size);
+ PrivateKey(const PrivateKey &other);
+ PrivateKey& operator=(const PrivateKey &other);
+
+ const char* getData() const { return data; }
+ size_t getSize() const { return PRIVATE_KEY_NUM_BYTES; }
+
+ // Throws DataSignException if signing data failed for whatever reason. This wont happen unless there is an issue with the private key
+ std::string sign(const DataView &dataToSign) const;
+ std::string toString() const;
+ private:
+ PrivateKey(){}
+ private:
+ char data[PRIVATE_KEY_NUM_BYTES];
+ };
+
+ class KeyPair
+ {
+ public:
+ // Throws SignatureGenerationException if generation of private/public key pair fails (should never happen)
+ KeyPair();
+
+ const PublicKey& getPublicKey() const { return publicKey; }
+ const PrivateKey& getPrivateKey() const { return privateKey; }
+ private:
+ PublicKey publicKey;
+ PrivateKey privateKey;
+ };
+ }
+}
diff --git a/include/odhtdb/StagedObject.hpp b/include/odhtdb/StagedObject.hpp
new file mode 100644
index 0000000..0c9b534
--- /dev/null
+++ b/include/odhtdb/StagedObject.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "utils.hpp"
+#include "Hash.hpp"
+#include "DataView.hpp"
+
+namespace odhtdb
+{
+ struct StagedObject
+ {
+ DISABLE_COPY(StagedObject)
+ DataView data;
+ std::shared_ptr<Hash> requestKey;
+
+ StagedObject(DataView &_data, const std::shared_ptr<Hash> &_requestKey) :
+ data(_data),
+ requestKey(_requestKey)
+ {
+
+ }
+ };
+}
diff --git a/include/odhtdb/User.hpp b/include/odhtdb/User.hpp
new file mode 100644
index 0000000..fb37876
--- /dev/null
+++ b/include/odhtdb/User.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "Signature.hpp"
+#include <string>
+#include <stdexcept>
+#include <vector>
+
+namespace odhtdb
+{
+ class Group;
+
+ class UserNameTooLongException : public std::runtime_error
+ {
+ public:
+ UserNameTooLongException(const std::string &userName) :
+ std::runtime_error(std::string("The username ") + userName + " is longer than 255 bytes")
+ {
+
+ }
+ };
+
+ class User
+ {
+ public:
+ virtual ~User(){}
+
+ void addToGroup(Group *group);
+
+ const std::string& getName() const { return name; }
+ const std::vector<Group*>& getGroups() const { return groups; }
+ virtual const Signature::PublicKey& getPublicKey() const = 0;
+ protected:
+ User(const std::string &name, Group *group);
+ private:
+ std::string name;
+ std::vector<Group*> groups;
+ };
+}
diff --git a/include/odhtdb/bin2hex.hpp b/include/odhtdb/bin2hex.hpp
new file mode 100644
index 0000000..72b57c1
--- /dev/null
+++ b/include/odhtdb/bin2hex.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <string>
+
+namespace odhtdb
+{
+ static const char HEX_TABLE[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+ static std::string bin2hex(const char *data, size_t dataSize)
+ {
+ std::string result;
+ result.resize(dataSize * 2);
+
+ for(int i = 0; i < dataSize; ++i)
+ {
+ char c = data[i];
+ result[i * 2 + 0] = HEX_TABLE[(c & 0xF0) >> 4];
+ result[i * 2 + 1] = HEX_TABLE[(c & 0x0F)];
+ }
+
+ return result;
+ }
+}
diff --git a/include/odhtdb/types.hpp b/include/odhtdb/types.hpp
new file mode 100644
index 0000000..3cf7f02
--- /dev/null
+++ b/include/odhtdb/types.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <cstdint>
+
+namespace odhtdb
+{
+ typedef int8_t i8;
+ typedef int16_t i16;
+ typedef int32_t i32;
+ typedef int64_t i64;
+
+ typedef uint8_t u8;
+ typedef uint16_t u16;
+ typedef uint32_t u32;
+ typedef uint64_t u64;
+
+ typedef float f32;
+ typedef double f64;
+
+ typedef intptr_t isize;
+ typedef uintptr_t usize;
+}
diff --git a/include/odhtdb/utils.hpp b/include/odhtdb/utils.hpp
new file mode 100755
index 0000000..01e478d
--- /dev/null
+++ b/include/odhtdb/utils.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+// Disable copying for a class or struct
+#define DISABLE_COPY(ClassName) \
+ ClassName(ClassName&) = delete; \
+ ClassName& operator = (ClassName&) = delete;