From be3c931f9b2db357c0b4306ad248c968d90254a3 Mon Sep 17 00:00:00 2001 From: Aleksi Lindeman Date: Sat, 10 Feb 2018 03:38:47 +0100 Subject: Add private/public key for users --- src/Database.cpp | 66 +++++++++++++++++++++++++++++++------ src/Signature.cpp | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 10 deletions(-) create mode 100644 src/Signature.cpp (limited to 'src') diff --git a/src/Database.cpp b/src/Database.cpp index c2d08cb..f0c7b04 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -1,6 +1,7 @@ #include "../include/Database.hpp" #include "../include/Group.hpp" -#include "../include/User.hpp" +#include "../include/LocalUser.hpp" +#include "../include/RemoteUser.hpp" #include #include #include @@ -22,11 +23,11 @@ static bool timestampSynced = false; static InfoHash CREATE_DATA_HASH = InfoHash::get("__odhtdb__.create_data"); static InfoHash ADD_DATA_HASH = InfoHash::get("__odhtdb__.add_data"); -#define OPENDHT_INFOHASH_LEN 20 +const int OPENDHT_INFOHASH_LEN = 20; namespace odhtdb { - Database::Database(const char *bootstrapNodeAddr, u16 port) + Database::Database(const char *bootstrapNodeAddr, u16 port, boost::filesystem::path storageDir) { node.run(port, dht::crypto::generateIdentity(), true); fmt::MemoryWriter portStr; @@ -126,21 +127,32 @@ namespace odhtdb serializer.add(stagedObject.timestamp); serializer.add((u8)stagedObject.primaryAdminGroup->getName().size()); serializer.add((u8*)stagedObject.primaryAdminGroup->getName().data(), stagedObject.primaryAdminGroup->getName().size()); - serializer.add((u32)stagedObject.primaryAdminGroup->getUsers().size()); + assert(stagedObject.primaryAdminGroup->getUsers().size() <= 255); + serializer.add((u8)stagedObject.primaryAdminGroup->getUsers().size()); for(User *user : stagedObject.primaryAdminGroup->getUsers()) { + serializer.add((u8*)user->getPublicKey().getData(), PUBLIC_KEY_NUM_BYTES); serializer.add((u8)user->getName().size()); serializer.add((u8*)user->getName().data(), user->getName().size()); } // TODO: Verify if serializer buffer needs to survive longer than this scope - Value value(serializer.getBuffer().data(), serializer.getBuffer().size()); - node.put(CREATE_DATA_HASH, move(value), [](bool ok) + Value createDataValue(serializer.getBuffer().data(), serializer.getBuffer().size()); + node.put(CREATE_DATA_HASH, move(createDataValue), [](bool ok) { // TODO: Handle failure to put data if(!ok) fprintf(stderr, "Failed to put: %s, what to do?\n", "commitStagedCreateObject"); }, time_point(), false); + + // Post data for listeners of this key + Value putKeyValue(serializer.getBuffer().data() + OPENDHT_INFOHASH_LEN, serializer.getBuffer().size() - OPENDHT_INFOHASH_LEN); + node.put(stagedObject.key.hashedKey, move(putKeyValue), [](bool ok) + { + // TODO: Handle failure to put data + if(!ok) + fprintf(stderr, "Failed to put for listeners: %s, what to do?\n", "commitStagedCreateObject"); + }, time_point(), false); } void Database::commitStagedAddObject(const StagedAddObject &stagedObject) @@ -154,12 +166,21 @@ namespace odhtdb serializer.add((u8*)stagedObject.data.data, stagedObject.data.size); // TODO: Verify if serializer buffer needs to survive longer than this scope - Value value(serializer.getBuffer().data(), serializer.getBuffer().size()); - node.put(ADD_DATA_HASH, move(value), [](bool ok) + Value addDataValue(serializer.getBuffer().data(), serializer.getBuffer().size()); + node.put(ADD_DATA_HASH, move(addDataValue), [](bool ok) + { + // TODO: Handle failure to put data + if(!ok) + fprintf(stderr, "Failed to put for all: %s, what to do?\n", "commitStagedAddObject"); + }, time_point(), false); + + // Post data for listeners of this key + Value putKeyValue(serializer.getBuffer().data() + OPENDHT_INFOHASH_LEN, serializer.getBuffer().size() - OPENDHT_INFOHASH_LEN); + node.put(stagedObject.key.hashedKey, move(putKeyValue), [](bool ok) { // TODO: Handle failure to put data if(!ok) - fprintf(stderr, "Failed to put: %s, what to do?\n", "commitStagedAddObject"); + fprintf(stderr, "Failed to put for listeners: %s, what to do?\n", "commitStagedAddObject"); }, time_point(), false); } @@ -182,6 +203,29 @@ namespace odhtdb result.key.hashedKey = InfoHash(entryKeyRaw, OPENDHT_INFOHASH_LEN); result.timestamp = deserializer.extract(); + u8 adminGroupNameSize = deserializer.extract(); + string adminGroupName; + adminGroupName.resize(adminGroupNameSize); + deserializer.extract((u8*)&adminGroupName[0], adminGroupNameSize); + result.primaryAdminGroup = new Group(adminGroupName); + + u8 numUsers = deserializer.extract(); + for(int i = 0; i < numUsers; ++i) + { + char userPublicKeyRaw[PUBLIC_KEY_NUM_BYTES]; + deserializer.extract((u8*)userPublicKeyRaw, PUBLIC_KEY_NUM_BYTES); + Signature::PublicKey userPublicKey(userPublicKeyRaw, PUBLIC_KEY_NUM_BYTES); + + u8 userNameSize = deserializer.extract(); + string userName; + userName.resize(userNameSize); + deserializer.extract((u8*)&userName[0], userNameSize); + + RemoteUser *user = RemoteUser::create(userPublicKey, userName); + result.primaryAdminGroup->addUser(user); + } + + // NOTE: There might be more data in deserializer, but we can ignore those; we already got all data we need return result; } @@ -204,7 +248,9 @@ namespace odhtdb { try { + // TODO: Verify createObject timestamp is not in the future StagedCreateObject createObject = deserializeCreateRequest(value); + delete createObject.primaryAdminGroup; } catch (sibs::DeserializeException &e) { @@ -229,4 +275,4 @@ namespace odhtdb } return true; } -} \ No newline at end of file +} diff --git a/src/Signature.cpp b/src/Signature.cpp new file mode 100644 index 0000000..804047e --- /dev/null +++ b/src/Signature.cpp @@ -0,0 +1,97 @@ +#include "../include/Signature.hpp" +#include +#include +#include + +using namespace std; + +namespace odhtdb +{ + namespace Signature + { + PublicKey::PublicKey(char *_data, size_t size) + { + if(size != PUBLIC_KEY_NUM_BYTES) + { + string errMsg = "Expected public key size to be "; + errMsg += to_string(PUBLIC_KEY_NUM_BYTES); + errMsg += " bytes, was: "; + errMsg += to_string(size); + throw InvalidSignatureKeySize(errMsg); + } + memmove(data, _data, PUBLIC_KEY_NUM_BYTES); + } + + PublicKey::PublicKey(const PublicKey &other) + { + memmove(data, other.data, PUBLIC_KEY_NUM_BYTES); + } + + PublicKey& PublicKey::operator=(const PublicKey &other) + { + memmove(data, other.data, PUBLIC_KEY_NUM_BYTES); + return *this; + } + + string PublicKey::toString() const + { + string result; + result.resize(PUBLIC_KEY_NUM_BYTES * 2); + sodium_bin2hex(&result[0], PUBLIC_KEY_NUM_BYTES * 2 + 1, (const unsigned char*)data, PUBLIC_KEY_NUM_BYTES); + return result; + } + + PrivateKey::PrivateKey(char *_data, size_t size) + { + if(size != PRIVATE_KEY_NUM_BYTES) + { + string errMsg = "Expected private key size to be "; + errMsg += to_string(PRIVATE_KEY_NUM_BYTES); + errMsg += " bytes, was: "; + errMsg += to_string(size); + throw InvalidSignatureKeySize(errMsg); + } + memmove(data, _data, PRIVATE_KEY_NUM_BYTES); + } + + PrivateKey::PrivateKey(const PrivateKey &other) + { + memmove(data, other.data, PRIVATE_KEY_NUM_BYTES); + } + + PrivateKey& PrivateKey::operator=(const PrivateKey &other) + { + memmove(data, other.data, PRIVATE_KEY_NUM_BYTES); + return *this; + } + + string PrivateKey::sign(const string &dataToSign) const + { + string result; + result.resize(crypto_sign_ed25519_BYTES + dataToSign.size()); + unsigned long long resultSize; + + if(crypto_sign_ed25519((unsigned char*)&result[0], &resultSize, (unsigned char*)dataToSign.data(), dataToSign.size(), (unsigned char*)data) != 0) + throw DataSignException("Failed to sign data. Is private key invalid?"); + + if(resultSize != result.size()) + throw DataSignException("Failed to sign data. The signed data is not of expected size (bug)"); + + return result; + } + + string PrivateKey::toString() const + { + string result; + result.resize(PRIVATE_KEY_NUM_BYTES * 2); + sodium_bin2hex(&result[0], PRIVATE_KEY_NUM_BYTES * 2 + 1, (const unsigned char*)data, PRIVATE_KEY_NUM_BYTES); + return result; + } + + KeyPair::KeyPair() + { + if(crypto_sign_ed25519_keypair((unsigned char*)publicKey.data, (unsigned char*)privateKey.data) != 0) + throw SignatureGenerationException("Failed to generate signature keypair"); + } + } +} -- cgit v1.2.3