From 2ffb47d0043e57707474e5ae811f97c2e5e93f25 Mon Sep 17 00:00:00 2001 From: Aleksi Lindeman <0xdec05eba@gmail.com> Date: Mon, 5 Mar 2018 22:45:56 +0100 Subject: Implement 'create' operation, add seeding Seeding is currently only done on the key you specify, in the future the user should request data that it can seed. --- include/Database.hpp | 121 +++++++++++++++++++++++++++++++++++++++----- include/DatabaseStorage.hpp | 18 ++++--- include/DhtKey.hpp | 19 +++++++ include/Encryption.hpp | 56 +++++++++++++++----- include/Group.hpp | 8 +-- include/Hash.hpp | 46 +++++++++++++++++ include/Key.hpp | 29 ----------- include/StagedObject.hpp | 38 ++++---------- include/bin2hex.hpp | 23 +++++++++ 9 files changed, 267 insertions(+), 91 deletions(-) create mode 100644 include/DhtKey.hpp create mode 100644 include/Hash.hpp create mode 100644 include/bin2hex.hpp (limited to 'include') 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 #include #include #include +#include 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 &key, const std::shared_ptr &hash); + + const std::shared_ptr getNodeEncryptionKey() const; + const std::shared_ptr getRequestHash() const; + private: + std::shared_ptr key; + std::shared_ptr 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, const std::shared_ptr encryptionKey); + // Throws DatabaseCreateException on failure. + std::unique_ptr 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 &stagedObject); + // Throws CommitAddException on failure + void commitStagedAddObject(const DataView &stagedObject); ntp::NtpTimestamp getSyncedTimestampUtc() const; - StagedCreateObject deserializeCreateRequest(const std::shared_ptr &value); - StagedAddObject deserializeAddRequest(const std::shared_ptr &value); - bool listenCreateData(std::shared_ptr value); - bool listenAddData(std::shared_ptr value); + DatabaseCreateRequest deserializeCreateRequest(const std::shared_ptr &value, const Hash &hash, const std::shared_ptr encryptionKey); + DatabaseAddRequest deserializeAddRequest(const std::shared_ptr &value, const Hash &hash, const std::shared_ptr encryptionKey); + bool listenCreateData(std::shared_ptr value, const Hash &hash, const std::shared_ptr encryptionKey); + bool listenAddData(std::shared_ptr value, const Hash &hash, const std::shared_ptr encryptionKey); private: dht::DhtRunner node; - std::vector stagedCreateObjects; - std::vector stagedAddObjects; + std::vector> stagedCreateObjects; + std::vector> 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 #include @@ -28,6 +29,8 @@ namespace odhtdb u64 timestamp; // In microseconds std::vector groups; std::vector 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; + using DatabaseStorageMap = MapHashKey; class DatabaseStorage { public: - // Throws DatabaseStorageAlreadyExists if data with key already exists - void createStorage(const Key &key, std::vector &&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 + +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 +#include 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& getUsers() const; + const std::vector& getUsers() const; private: std::string name; - std::vector users; + std::vector 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 +#include +#include + +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 + using MapHashKey = std::unordered_map; +} 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 -#include 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 - using KeyMap = std::unordered_map; } 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 data; - u64 timestamp; // In microseconds - Signature::PublicKey creatorPublicKey; - - StagedAddObject() : key(), data(), timestamp(0), creatorPublicKey(Signature::PublicKey::ZERO) {} - StagedAddObject(const Key &_key, std::unique_ptr &&_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 requestKey; + + StagedCreateObject(DataView &_encryptedBody, const std::shared_ptr &_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 + +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; + } +} -- cgit v1.2.3