diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/Database.hpp | 121 | ||||
-rw-r--r-- | include/DatabaseStorage.hpp | 18 | ||||
-rw-r--r-- | include/DhtKey.hpp | 19 | ||||
-rw-r--r-- | include/Encryption.hpp | 56 | ||||
-rw-r--r-- | include/Group.hpp | 8 | ||||
-rw-r--r-- | include/Hash.hpp | 46 | ||||
-rw-r--r-- | include/Key.hpp | 29 | ||||
-rw-r--r-- | include/StagedObject.hpp | 38 | ||||
-rw-r--r-- | include/bin2hex.hpp | 23 |
9 files changed, 267 insertions, 91 deletions
diff --git a/include/Database.hpp b/include/Database.hpp index e8b35bb..d160133 100644 --- a/include/Database.hpp +++ b/include/Database.hpp @@ -2,17 +2,110 @@ #include "types.hpp" #include "Key.hpp" -#include "StagedObject.hpp" #include "DataView.hpp" #include "DatabaseStorage.hpp" +#include "Hash.hpp" +#include "utils.hpp" +#include "StagedObject.hpp" +#include "Signature.hpp" #include <opendht/dhtrunner.h> #include <vector> #include <ntp/NtpClient.hpp> #include <boost/filesystem/path.hpp> +#include <stdexcept> namespace odhtdb { 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) {} + }; + + 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) + + u16 packetStructureVersion; + u64 timestamp; // In microseconds + Signature::PublicKey creatorPublicKey; + DataView data; + + DatabaseAddRequest(u16 _packetStructureVersion, u64 _timestamp, Signature::PublicKey &&_creatorPublicKey, DataView &_data) : + packetStructureVersion(_packetStructureVersion), + timestamp(_timestamp), + creatorPublicKey(std::move(_creatorPublicKey)), + data(_data) + { + + } + + ~DatabaseAddRequest() + { + free(data.data); + data = DataView(); + } + }; + + class DatabaseCreateResponse + { + public: + DatabaseCreateResponse(const std::shared_ptr<char*> &key, const std::shared_ptr<Hash> &hash); + + const std::shared_ptr<char*> getNodeEncryptionKey() const; + const std::shared_ptr<Hash> getRequestHash() const; + private: + std::shared_ptr<char*> key; + std::shared_ptr<Hash> hash; + }; class Database { @@ -20,22 +113,26 @@ namespace odhtdb Database(const char *bootstrapNodeAddr, u16 port, boost::filesystem::path storageDir); ~Database(); - void seed(); - void create(LocalUser *owner, const Key &key); - void add(LocalUser *owner, const Key &key, DataView data); + void seed(const std::shared_ptr<Hash> hash, const std::shared_ptr<char*> encryptionKey); + // Throws DatabaseCreateException on failure. + std::unique_ptr<DatabaseCreateResponse> create(const LocalUser *owner, const std::string &name); + // Throws DatabaseAddException on failure + void add(const LocalUser *owner, const Key &key, DataView data); void commit(); private: - void commitStagedCreateObject(const StagedCreateObject &stagedObject); - void commitStagedAddObject(const StagedAddObject &stagedObject); + // Throws CommitCreateException on failure + void commitStagedCreateObject(const std::unique_ptr<StagedCreateObject> &stagedObject); + // Throws CommitAddException on failure + void commitStagedAddObject(const DataView &stagedObject); ntp::NtpTimestamp getSyncedTimestampUtc() const; - StagedCreateObject deserializeCreateRequest(const std::shared_ptr<dht::Value> &value); - StagedAddObject deserializeAddRequest(const std::shared_ptr<dht::Value> &value); - bool listenCreateData(std::shared_ptr<dht::Value> value); - bool listenAddData(std::shared_ptr<dht::Value> value); + DatabaseCreateRequest deserializeCreateRequest(const std::shared_ptr<dht::Value> &value, const Hash &hash, const std::shared_ptr<char*> encryptionKey); + DatabaseAddRequest deserializeAddRequest(const std::shared_ptr<dht::Value> &value, const Hash &hash, 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 &hash, const std::shared_ptr<char*> encryptionKey); private: dht::DhtRunner node; - std::vector<StagedCreateObject> stagedCreateObjects; - std::vector<StagedAddObject> stagedAddObjects; + std::vector<std::unique_ptr<StagedCreateObject>> stagedCreateObjects; + std::vector<std::unique_ptr<DataView>> stagedAddObjects; DatabaseStorage databaseStorage; }; } diff --git a/include/DatabaseStorage.hpp b/include/DatabaseStorage.hpp index 863c5d9..6f251d1 100644 --- a/include/DatabaseStorage.hpp +++ b/include/DatabaseStorage.hpp @@ -1,8 +1,9 @@ #pragma once -#include "Key.hpp" +#include "Hash.hpp" #include "DataView.hpp" #include "Signature.hpp" +#include "Encryption.hpp" #include <vector> #include <stdexcept> @@ -28,6 +29,8 @@ namespace odhtdb u64 timestamp; // In microseconds std::vector<Group*> groups; std::vector<DatabaseStorageObject> objects; + u8 *createData; + usize createDataSize; }; class DatabaseStorageAlreadyExists : public std::runtime_error @@ -42,16 +45,19 @@ namespace odhtdb DatabaseStorageNotFound(const std::string &errMsg) : std::runtime_error(errMsg) {} }; - using DatabaseStorageMap = KeyMap<DatabaseStorageObjectList*>; + using DatabaseStorageMap = MapHashKey<DatabaseStorageObjectList*>; class DatabaseStorage { public: - // Throws DatabaseStorageAlreadyExists if data with key already exists - void createStorage(const Key &key, std::vector<Group*> &&groups, u64 timestamp); + // 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 key does not exist - void appendStorage(const Key &key, DataView &data, u64 timestamp, const Signature::PublicKey &creatorPublicKey); + // Throws DatabaseStorageNotFound if data with hash does not exist + void appendStorage(const Hash &hash, DataView &data, u64 timestamp, const Signature::PublicKey &creatorPublicKey); + + // Returns nullptr if not storage with provided hash exists + const DatabaseStorageObjectList* getStorage(const Hash &hash) const; private: DatabaseStorageMap storageMap; }; diff --git a/include/DhtKey.hpp b/include/DhtKey.hpp new file mode 100644 index 0000000..7c30ee3 --- /dev/null +++ b/include/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/Encryption.hpp b/include/Encryption.hpp index b70687d..b2afe49 100644 --- a/include/Encryption.hpp +++ b/include/Encryption.hpp @@ -1,29 +1,61 @@ #pragma once /* - * Encrypts/decrypts data using xchacha20 + * 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; - struct EncryptedData + class EncryptionException : public std::runtime_error { - char nonce[NONCE_BYTE_SIZE]; - std::string data; + public: + EncryptionException(const std::string &errMsg) : std::runtime_error(errMsg) {} }; - using EncryptionKey = char[32]; - - // Stores randomly generated encryption key in @output - void generateEncryptionKey(EncryptionKey *output); + class DecryptionException : public std::runtime_error + { + public: + DecryptionException(const std::string &errMsg) : std::runtime_error(errMsg) {} + }; - // Returns 0 on success, storing encrypted data in @output - int encrypt(EncryptedData *output, const EncryptionKey *key, const void *data, size_t dataSize); + class Encryption + { + DISABLE_COPY(Encryption) + public: + // Throws EncryptionException on failure (or std::bad_alloc on failed memory allocation) + Encryption(const DataView &data) : Encryption(data, DataView()) {} + Encryption(const DataView &data, const DataView &additionalData); + ~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; + }; - // Returns 0 on success, storing decrypted data in @output - int decrypt(std::string *output, const EncryptionKey *key, const EncryptedData *encryptedData); + class Decryption + { + DISABLE_COPY(Decryption) + public: + // Throws DecryptionException on failure + Decryption(const DataView &data, const DataView &nonce, const DataView &key); + ~Decryption(); + + DataView getDecryptedText() const; + private: + unsigned char *decryptedText; + unsigned long long decryptedTextLength; + }; } diff --git a/include/Group.hpp b/include/Group.hpp index c909728..a8dcf83 100644 --- a/include/Group.hpp +++ b/include/Group.hpp @@ -24,12 +24,12 @@ namespace odhtdb Group(const std::string &name); ~Group(); - void addUser(User *user); + void addUser(const User *user); const std::string& getName() const; - const std::vector<User*>& getUsers() const; + const std::vector<const User*>& getUsers() const; private: std::string name; - std::vector<User*> users; + std::vector<const User*> users; }; -}
\ No newline at end of file +} diff --git a/include/Hash.hpp b/include/Hash.hpp new file mode 100644 index 0000000..d7c90b0 --- /dev/null +++ b/include/Hash.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include "utils.hpp" +#include <sodium/crypto_generichash_blake2b.h> +#include <stdexcept> +#include <unordered_map> + +namespace odhtdb +{ + const int HASH_BYTE_SIZE = 32; + + 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); + + 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 MapHashKey = std::unordered_map<Hash, ValueType, HashHasher>; +} diff --git a/include/Key.hpp b/include/Key.hpp index f7a600b..18971d1 100644 --- a/include/Key.hpp +++ b/include/Key.hpp @@ -1,7 +1,6 @@ #pragma once #include <opendht/infohash.h> -#include <unordered_map> namespace odhtdb { @@ -13,32 +12,4 @@ namespace odhtdb dht::InfoHash hashedKey; }; - - // Source: https://stackoverflow.com/a/11414104 (public license) - static unsigned int fnvHash(const unsigned char *key, int len) - { - unsigned int h = 2166136261; - for (int i = 0; i < len; i++) - h = (h * 16777619) ^ key[i]; - return h; - } - - struct KeyHash - { - size_t operator()(const Key &key) const - { - return fnvHash(key.hashedKey.data(), key.hashedKey.size()); - } - }; - - struct KeyCompare - { - bool operator()(const Key &lhs, const Key &rhs) const - { - return lhs.hashedKey == rhs.hashedKey; - } - }; - - template <typename ValueType> - using KeyMap = std::unordered_map<Key, ValueType, KeyHash, KeyCompare>; } diff --git a/include/StagedObject.hpp b/include/StagedObject.hpp index fccf4f6..a75664e 100644 --- a/include/StagedObject.hpp +++ b/include/StagedObject.hpp @@ -1,40 +1,22 @@ #pragma once -#include "Key.hpp" -#include "types.hpp" +#include "utils.hpp" +#include "Hash.hpp" #include "DataView.hpp" -#include "Signature.hpp" namespace odhtdb { - class Group; - struct StagedCreateObject { - Key key; - Group *primaryAdminGroup; - u64 timestamp; // In microseconds - - StagedCreateObject() : key(), primaryAdminGroup(nullptr), timestamp(0) {} - StagedCreateObject(const Key &_key, Group *_primaryAdminGroup, u64 _timestamp) : - key(_key), primaryAdminGroup(_primaryAdminGroup), timestamp(_timestamp) - { - - } - }; - - struct StagedAddObject - { - Key key; - std::unique_ptr<std::string> data; - u64 timestamp; // In microseconds - Signature::PublicKey creatorPublicKey; - - StagedAddObject() : key(), data(), timestamp(0), creatorPublicKey(Signature::PublicKey::ZERO) {} - StagedAddObject(const Key &_key, std::unique_ptr<std::string> &&_data, u64 _timestamp, const Signature::PublicKey &_creatorPublicKey) : - key(_key), data(std::move(_data)), timestamp(_timestamp), creatorPublicKey(_creatorPublicKey) + DISABLE_COPY(StagedCreateObject) + DataView encryptedBody; + std::shared_ptr<Hash> requestKey; + + StagedCreateObject(DataView &_encryptedBody, const std::shared_ptr<Hash> &_requestKey) : + encryptedBody(_encryptedBody), + requestKey(_requestKey) { - + } }; } diff --git a/include/bin2hex.hpp b/include/bin2hex.hpp new file mode 100644 index 0000000..72b57c1 --- /dev/null +++ b/include/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; + } +} |