From 04cfe9c03baa5691ebfad6e039e4f0acd74fd8e1 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 27 Apr 2018 04:15:33 +0200 Subject: Add local user storage function (locally stored encrypted user private key) --- src/DatabaseStorage.cpp | 125 ++++++++++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 57 deletions(-) (limited to 'src/DatabaseStorage.cpp') 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 *publicKeyUserDataMap = nullptr; + Signature::MapPublicKey *publicKeyUserDataMap = nullptr; auto publicKeyUserDataMapIt = nodePublicKeyUserDataMap.find(nodeHash); if(publicKeyUserDataMapIt == nodePublicKeyUserDataMap.end()) { - publicKeyUserDataMap = new Signature::MapPublicKey(); + publicKeyUserDataMap = new Signature::MapPublicKey(); nodePublicKeyUserDataMap[nodeHash] = publicKeyUserDataMap; } else @@ -156,8 +158,6 @@ namespace odhtdb else groupByIdMap = groupByIdMapIt->second; - User::Type userType = deserializer.extract(); - u8 usernameSize = deserializer.extract(); 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(); 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(); + 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 *publicKeyUserDataMap = nullptr; + Signature::MapPublicKey *publicKeyUserDataMap = nullptr; auto publicKeyUserDataMapIt = nodePublicKeyUserDataMap.find(nodeHash); if(publicKeyUserDataMapIt == nodePublicKeyUserDataMap.end()) { - publicKeyUserDataMap = new Signature::MapPublicKey(); + publicKeyUserDataMap = new Signature::MapPublicKey(); 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(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(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::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 -- cgit v1.2.3