aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-04-27 04:15:33 +0200
committerdec05eba <dec05eba@protonmail.com>2020-08-18 23:25:46 +0200
commit04cfe9c03baa5691ebfad6e039e4f0acd74fd8e1 (patch)
treeaafcc5450024b1f72dfb8b287b70c4185b890dc6 /src
parent8841ea78fd3386118c7514c89c22fae057cc151a (diff)
Add local user storage function (locally stored encrypted user private key)
Diffstat (limited to 'src')
-rw-r--r--src/Database.cpp9
-rw-r--r--src/DatabaseStorage.cpp125
-rw-r--r--src/Encryption.cpp4
-rw-r--r--src/LocalUser.cpp5
-rw-r--r--src/LocalUserEncrypted.cpp6
-rw-r--r--src/PasswordHash.cpp7
6 files changed, 81 insertions, 75 deletions
diff --git a/src/Database.cpp b/src/Database.cpp
index d4ae190..9b01f72 100644
--- a/src/Database.cpp
+++ b/src/Database.cpp
@@ -127,10 +127,7 @@ namespace odhtdb
}
timestampSynced = false;
});
-
- // TODO: Catch std::system_error instead of this if-statement
- if(ntpThread->joinable())
- ntpThread->detach();
+ ntpThread->detach();
}
}
@@ -235,13 +232,13 @@ namespace odhtdb
//node.listen(ADD_DATA_HASH, bind(&Database::listenAddData, this, _1));
}
- unique_ptr<DatabaseCreateResponse> Database::create(const string &ownerName, const std::string &ownerPlainPassword, const string &nodeName)
+ unique_ptr<DatabaseCreateResponse> Database::create(const string &ownerName, const string &nodeName)
{
// TODO: Should this be declared static? is there any difference in behavior/performance?
boost::uuids::random_generator uuidGen;
auto adminGroupId = uuidGen();
auto adminGroup = new Group("administrator", adminGroupId.data, ADMIN_PERMISSION);
- LocalUser *nodeAdminUser = LocalUser::create(Signature::KeyPair(), ownerName, adminGroup, ownerPlainPassword);
+ LocalUser *nodeAdminUser = LocalUser::create(Signature::KeyPair(), ownerName, adminGroup);
// Header
sibs::SafeSerializer serializer;
diff --git a/src/DatabaseStorage.cpp b/src/DatabaseStorage.cpp
index c507f02..7ce4919 100644
--- a/src/DatabaseStorage.cpp
+++ b/src/DatabaseStorage.cpp
@@ -43,7 +43,8 @@ namespace odhtdb
groupsFilePath(storagePath / "groups"),
usersFilePath(storagePath / "users"),
dataFilePath(storagePath / "data"),
- metadataFilePath(storagePath / "metadata")
+ metadataFilePath(storagePath / "metadata"),
+ localUsersFilePath(storagePath / "local_users")
{
boost::filesystem::create_directories(storagePath);
@@ -55,11 +56,12 @@ namespace odhtdb
loadGroupsFromFile();
loadUsersFromFile();
loadDataFromFile();
+ loadLocalUsersFromFile();
//loadQuarantineFromFile();
}
catch(FileException &e)
{
- Log::warn("Failed to load data from file: %s, reason: %s. Ignoring...", dataFilePath.string().c_str(), e.what());
+ Log::warn("Failed to load storage data, reason: %s. Ignoring...", e.what());
if(!metadataLoaded)
{
sibs::SafeSerializer metadataSerializer;
@@ -136,11 +138,11 @@ namespace odhtdb
Hash nodeHash;
deserializer.extract((u8*)nodeHash.getData(), HASH_BYTE_SIZE);
- Signature::MapPublicKey<UserData*> *publicKeyUserDataMap = nullptr;
+ Signature::MapPublicKey<User*> *publicKeyUserDataMap = nullptr;
auto publicKeyUserDataMapIt = nodePublicKeyUserDataMap.find(nodeHash);
if(publicKeyUserDataMapIt == nodePublicKeyUserDataMap.end())
{
- publicKeyUserDataMap = new Signature::MapPublicKey<UserData*>();
+ publicKeyUserDataMap = new Signature::MapPublicKey<User*>();
nodePublicKeyUserDataMap[nodeHash] = publicKeyUserDataMap;
}
else
@@ -156,8 +158,6 @@ namespace odhtdb
else
groupByIdMap = groupByIdMapIt->second;
- User::Type userType = deserializer.extract<User::Type>();
-
u8 usernameSize = deserializer.extract<u8>();
string username;
username.resize(usernameSize);
@@ -167,18 +167,7 @@ namespace odhtdb
deserializer.extract(userPublicKeyRaw, PUBLIC_KEY_NUM_BYTES);
Signature::PublicKey userPublicKey((const char*)userPublicKeyRaw, PUBLIC_KEY_NUM_BYTES);
- UserData *userData = new UserData();
- if(userType == User::Type::LOCAL)
- {
- EncryptedPrivateKey encryptedPrivateKey;
- deserializer.extract(encryptedPrivateKey.nonce, ENCRYPTION_NONCE_BYTE_SIZE);
- deserializer.extract(encryptedPrivateKey.encryptedPrivateKey, 16 + PRIVATE_KEY_NUM_BYTES);
- userData->user = LocalUserEncrypted::create(userPublicKey, encryptedPrivateKey, username, nullptr);
- }
- else
- {
- userData->user = RemoteUser::create(userPublicKey, username, nullptr);
- }
+ User *user = RemoteUser::create(userPublicKey, username, nullptr);
u8 numGroups = deserializer.extract<u8>();
for(int i = 0; i < numGroups; ++i)
@@ -194,10 +183,10 @@ namespace odhtdb
errMsg += " does not exist";
throw DatabaseStorageCorrupt(errMsg);
}
- userData->user->addToGroup(groupIt->second);
+ user->addToGroup(groupIt->second);
}
- (*publicKeyUserDataMap)[userData->user->getPublicKey()] = userData;
+ (*publicKeyUserDataMap)[user->getPublicKey()] = user;
}
}
@@ -295,6 +284,32 @@ namespace odhtdb
}
}
+ void DatabaseStorage::loadLocalUsersFromFile()
+ {
+ if(!boost::filesystem::exists(localUsersFilePath)) return;
+
+ OwnedMemory localUsersFileContent = fileGetContent(localUsersFilePath);
+ sibs::SafeDeserializer deserializer((u8*)localUsersFileContent.data, localUsersFileContent.size);
+
+ while(!deserializer.empty())
+ {
+ u8 usernameSize = deserializer.extract<u8>();
+ string username;
+ username.resize(usernameSize);
+ deserializer.extract((u8*)&username[0], usernameSize);
+
+ u8 userPublicKeyRaw[PUBLIC_KEY_NUM_BYTES];
+ deserializer.extract(userPublicKeyRaw, PUBLIC_KEY_NUM_BYTES);
+ Signature::PublicKey userPublicKey((const char*)userPublicKeyRaw, PUBLIC_KEY_NUM_BYTES);
+
+ EncryptedPrivateKey encryptedPrivateKey;
+ deserializer.extract(encryptedPrivateKey.nonce, ENCRYPTION_NONCE_BYTE_SIZE);
+ deserializer.extract(encryptedPrivateKey.encryptedPrivateKey, ENCRYPTION_CHECKSUM_BYTE_SIZE + PRIVATE_KEY_NUM_BYTES);
+
+ nameLocalUsersMap[username] = LocalUserEncrypted::create(userPublicKey, encryptedPrivateKey, username);
+ }
+ }
+
void DatabaseStorage::loadMetadataFromFile()
{
OwnedMemory metadataFileContent = fileGetContent(metadataFilePath);
@@ -449,11 +464,11 @@ namespace odhtdb
bool DatabaseStorage::addUser(const Hash &nodeHash, User *user)
{
- Signature::MapPublicKey<UserData*> *publicKeyUserDataMap = nullptr;
+ Signature::MapPublicKey<User*> *publicKeyUserDataMap = nullptr;
auto publicKeyUserDataMapIt = nodePublicKeyUserDataMap.find(nodeHash);
if(publicKeyUserDataMapIt == nodePublicKeyUserDataMap.end())
{
- publicKeyUserDataMap = new Signature::MapPublicKey<UserData*>();
+ publicKeyUserDataMap = new Signature::MapPublicKey<User*>();
nodePublicKeyUserDataMap[nodeHash] = publicKeyUserDataMap;
}
else
@@ -462,20 +477,7 @@ namespace odhtdb
if(publicKeyUserDataMap->find(user->getPublicKey()) != publicKeyUserDataMap->end())
return false;
- UserData *userData = new UserData();
- userData->user = user;
- if(user->getType() == User::Type::LOCAL)
- {
- LocalUser *localUser = static_cast<LocalUser*>(user);
- //DataView plainPassword((void*)localUser->getPlainPassword().data(), localUser->getPlainPassword().size());
- OwnedMemory hashedPassword = hashPassword(DataView((void*)localUser->getPlainPassword().data(), localUser->getPlainPassword().size()), DataView(passwordSalt, PASSWORD_SALT_LEN));
- memcpy(userData->hashedPassword, hashedPassword.data, hashedPassword.size);
- }
- else
- {
- memset(userData->hashedPassword, 0, HASHED_PASSWORD_LEN);
- }
- (*publicKeyUserDataMap)[user->getPublicKey()] = userData;
+ (*publicKeyUserDataMap)[user->getPublicKey()] = user;
// TODO: Instead of directly saving user to file, maybe user should be added to buffer and then save to file after we have several users (performance improvement)
@@ -483,23 +485,10 @@ namespace odhtdb
serializer.add((u8*)nodeHash.getData(), HASH_BYTE_SIZE);
- serializer.add(user->getType());
-
serializer.add((u8)user->getName().size());
serializer.add((u8*)user->getName().data(), user->getName().size());
serializer.add((u8*)user->getPublicKey().getData(), PUBLIC_KEY_NUM_BYTES);
- if(user->getType() == User::Type::LOCAL)
- {
- LocalUser *localUser = static_cast<LocalUser*>(user);
- static_assert(HASHED_PASSWORD_LEN == ENCRYPTION_KEY_BYTE_SIZE, "Encryption key size has changed but hashed password size hasn't");
- Encryption encryptedPrivateKey(DataView((void*)localUser->getPrivateKey().getData(), localUser->getPrivateKey().getSize()),
- DataView(),
- DataView(userData->hashedPassword, HASHED_PASSWORD_LEN));
- serializer.add((u8*)encryptedPrivateKey.getNonce().data, ENCRYPTION_NONCE_BYTE_SIZE);
- assert(16 + PRIVATE_KEY_NUM_BYTES == encryptedPrivateKey.getCipherText().size);
- serializer.add((u8*)encryptedPrivateKey.getCipherText().data, encryptedPrivateKey.getCipherText().size);
- }
serializer.add((u8)user->getGroups().size());
for(Group *group : user->getGroups())
@@ -520,7 +509,7 @@ namespace odhtdb
return nullptr;
}
- Group* DatabaseStorage::getGroupById(const Hash &nodeHash, uint8_t groupId[GROUP_ID_LENGTH])
+ Group* DatabaseStorage::getGroupById(const Hash &nodeHash, uint8_t groupId[GROUP_ID_LENGTH]) const
{
auto groupByIdMapIt = nodeGroupByIdMap.find(nodeHash);
if(groupByIdMapIt != nodeGroupByIdMap.end())
@@ -532,24 +521,46 @@ namespace odhtdb
return nullptr;
}
- User* DatabaseStorage::getUserByPublicKey(const Hash &nodeHash, Signature::PublicKey &userPublicKey)
+ User* DatabaseStorage::getUserByPublicKey(const Hash &nodeHash, const Signature::PublicKey &userPublicKey) const
{
auto publicKeyUserDataMapIt = nodePublicKeyUserDataMap.find(nodeHash);
if(publicKeyUserDataMapIt != nodePublicKeyUserDataMap.end())
{
auto it = publicKeyUserDataMapIt->second->find(userPublicKey);
if(it != publicKeyUserDataMapIt->second->end())
- return it->second->user;
+ return it->second;
}
return nullptr;
}
- const Signature::MapPublicKey<DatabaseStorage::UserData*>* DatabaseStorage::getUsersData(const Hash &nodeHash) const
+ bool DatabaseStorage::storeLocalUser(const string &username, const Signature::PublicKey &publicKey, const Signature::PrivateKey &privateKey, const string &password)
{
- auto publicKeyUserDataMapIt = nodePublicKeyUserDataMap.find(nodeHash);
- if(publicKeyUserDataMapIt != nodePublicKeyUserDataMap.end())
- return publicKeyUserDataMapIt->second;
- return nullptr;
+ auto it = nameLocalUsersMap.find(username);
+ if(it != nameLocalUsersMap.end())
+ return false;
+
+ OwnedMemory hashedPassword = hashPassword(DataView((void*)password.data(), password.size()), DataView((void*)passwordSalt, PASSWORD_SALT_LEN));
+ DataView privateKeyView((void*)privateKey.getData(), PRIVATE_KEY_NUM_BYTES);
+ DataView hashedPasswordView(hashedPassword.data, hashedPassword.size);
+ Encryption encryptedPrivateKey(privateKeyView, {}, hashedPasswordView);
+
+ EncryptedPrivateKey userEncryptedPrivateKey;
+ memcpy(userEncryptedPrivateKey.nonce, encryptedPrivateKey.getNonce().data, ENCRYPTION_NONCE_BYTE_SIZE);
+ assert(sizeof(userEncryptedPrivateKey.encryptedPrivateKey) == encryptedPrivateKey.getCipherText().size);
+ memcpy(userEncryptedPrivateKey.encryptedPrivateKey, encryptedPrivateKey.getCipherText().data, encryptedPrivateKey.getCipherText().size);
+
+ LocalUserEncrypted *localUserEncrypted = LocalUserEncrypted::create(publicKey, userEncryptedPrivateKey, username);
+ nameLocalUsersMap[username] = localUserEncrypted;
+
+ sibs::SafeSerializer serializer;
+ serializer.add((u8)username.size());
+ serializer.add((const u8*)username.data(), username.size());
+ serializer.add((const u8*)publicKey.getData(), PUBLIC_KEY_NUM_BYTES);
+ serializer.add((const u8*)encryptedPrivateKey.getNonce().data, ENCRYPTION_NONCE_BYTE_SIZE);
+ serializer.add((const u8*)encryptedPrivateKey.getCipherText().data, ENCRYPTION_CHECKSUM_BYTE_SIZE + PRIVATE_KEY_NUM_BYTES);
+
+ fileAppend(localUsersFilePath, DataView(serializer.getBuffer().data(), serializer.getBuffer().size()));
+ return true;
}
const dht::crypto::Identity& DatabaseStorage::getIdentity() const
diff --git a/src/Encryption.cpp b/src/Encryption.cpp
index e67c719..1d6bfc0 100644
--- a/src/Encryption.cpp
+++ b/src/Encryption.cpp
@@ -7,8 +7,8 @@ namespace odhtdb
{
Encryption::Encryption(const DataView &data, const DataView &additionalData, const DataView &_key)
{
- cipherText = new unsigned char[crypto_aead_xchacha20poly1305_ietf_ABYTES + data.size];
cipherTextLength = crypto_aead_xchacha20poly1305_ietf_ABYTES + data.size;
+ cipherText = new unsigned char[cipherTextLength];
if(_key.data)
{
@@ -46,8 +46,8 @@ namespace odhtdb
Decryption::Decryption(const DataView &data, const DataView &nonce, const DataView &key)
{
- decryptedText = new unsigned char[data.size];
decryptedTextLength = data.size;
+ decryptedText = new unsigned char[decryptedTextLength];
if(nonce.size < ENCRYPTION_NONCE_BYTE_SIZE)
throw DecryptionException("Nonce is not big enough");
diff --git a/src/LocalUser.cpp b/src/LocalUser.cpp
index 660d09a..665f05d 100644
--- a/src/LocalUser.cpp
+++ b/src/LocalUser.cpp
@@ -2,10 +2,9 @@
namespace odhtdb
{
- LocalUser::LocalUser(const Signature::KeyPair &_keyPair, const std::string &name, Group *group, const std::string &_plainPassword) :
+ LocalUser::LocalUser(const Signature::KeyPair &_keyPair, const std::string &name, Group *group) :
User(User::Type::LOCAL, name, group),
- keyPair(_keyPair),
- plainPassword(_plainPassword)
+ keyPair(_keyPair)
{
}
diff --git a/src/LocalUserEncrypted.cpp b/src/LocalUserEncrypted.cpp
index 1c22488..a414c89 100644
--- a/src/LocalUserEncrypted.cpp
+++ b/src/LocalUserEncrypted.cpp
@@ -7,19 +7,19 @@ namespace odhtdb
EncryptedPrivateKey::EncryptedPrivateKey()
{
memset(nonce, 0, ENCRYPTION_NONCE_BYTE_SIZE);
- memset(encryptedPrivateKey, 0, 16 + PRIVATE_KEY_NUM_BYTES);
+ memset(encryptedPrivateKey, 0, ENCRYPTION_CHECKSUM_BYTE_SIZE + PRIVATE_KEY_NUM_BYTES);
}
EncryptedPrivateKey::EncryptedPrivateKey(const EncryptedPrivateKey &other)
{
memcpy(nonce, other.nonce, ENCRYPTION_NONCE_BYTE_SIZE);
- memcpy(encryptedPrivateKey, other.encryptedPrivateKey, 16 + PRIVATE_KEY_NUM_BYTES);
+ memcpy(encryptedPrivateKey, other.encryptedPrivateKey, ENCRYPTION_CHECKSUM_BYTE_SIZE + PRIVATE_KEY_NUM_BYTES);
}
Signature::PrivateKey EncryptedPrivateKey::decrypt(const DataView &plainPassword, const DataView &salt) const
{
OwnedMemory hashedPassword = hashPassword(plainPassword, salt);
- Decryption decryptedPrivateKey(DataView((void*)encryptedPrivateKey, 16 + PRIVATE_KEY_NUM_BYTES),
+ Decryption decryptedPrivateKey(DataView((void*)encryptedPrivateKey, ENCRYPTION_CHECKSUM_BYTE_SIZE + PRIVATE_KEY_NUM_BYTES),
DataView((void*)nonce, ENCRYPTION_NONCE_BYTE_SIZE),
DataView(hashedPassword.data, hashedPassword.size));
return { (const char*)decryptedPrivateKey.getDecryptedText().data, decryptedPrivateKey.getDecryptedText().size };
diff --git a/src/PasswordHash.cpp b/src/PasswordHash.cpp
index f6d3713..329733b 100644
--- a/src/PasswordHash.cpp
+++ b/src/PasswordHash.cpp
@@ -10,12 +10,11 @@ namespace odhtdb
const uint32_t tCost = 2;
const uint32_t mCost = 1 << 16;
const uint32_t parallelism = 1;
- const uint32_t HASHLEN = 32;
- result.data = new uint8_t[HASHLEN];
- result.size = HASHLEN;
+ result.data = new uint8_t[HASH_PASSWORD_LENGTH];
+ result.size = HASH_PASSWORD_LENGTH;
- if(argon2i_hash_raw(tCost, mCost, parallelism, plainPassword.data, plainPassword.size, salt.data, salt.size, result.data, HASHLEN) != ARGON2_OK)
+ if(argon2i_hash_raw(tCost, mCost, parallelism, plainPassword.data, plainPassword.size, salt.data, salt.size, result.data, HASH_PASSWORD_LENGTH) != ARGON2_OK)
throw std::runtime_error("Failed to hash password");
return result;