use controller::User for login in Session, for direct register without showing passphrase direct and using new KeyPairEd25519, AuthenticatedEncryption and Passphrase classes

This commit is contained in:
Dario 2020-06-25 15:58:05 +02:00
parent 9f010cc5df
commit 30ba3d7f78
5 changed files with 88 additions and 14 deletions

View File

@ -4,6 +4,7 @@
#include "../SingletonManager/SessionManager.h" #include "../SingletonManager/SessionManager.h"
#include "../SingletonManager/ErrorManager.h" #include "../SingletonManager/ErrorManager.h"
#include "../SingletonManager/SingletonTaskObserver.h"
#include "../lib/DataTypeConverter.h" #include "../lib/DataTypeConverter.h"
@ -15,7 +16,7 @@
namespace controller { namespace controller {
User::User(model::table::User* dbModel) User::User(model::table::User* dbModel)
: mPassword(nullptr), mGradidoKeyPair(nullptr) : mPassword(nullptr), mGradidoKeyPair(nullptr), mCanDecryptPrivateKey(false)
{ {
mDBModel = dbModel; mDBModel = dbModel;
} }
@ -130,15 +131,23 @@ namespace controller {
if (!mPassword.isNull() && mPassword->hasKey()) { if (!mPassword.isNull() && mPassword->hasKey()) {
return 2; return 2;
} }
auto observer = SingletonTaskObserver::getInstance();
std::unique_lock<std::shared_mutex> _lock(mSharedMutex); std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
assert(mPassword.isNull()); assert(mPassword.isNull());
Poco::AutoPtr<AuthenticatedEncryption> authenticated_encryption(new AuthenticatedEncryption);
auto model = getModel(); auto model = getModel();
auto email_hash = observer->makeHash(model->getEmail());
if (observer->getTaskCount(email_hash, TASK_OBSERVER_PASSWORD_CREATION) > 0) {
return -3;
}
observer->addTask(email_hash, TASK_OBSERVER_PASSWORD_CREATION);
Poco::AutoPtr<AuthenticatedEncryption> authenticated_encryption(new AuthenticatedEncryption);
assert(!authenticated_encryption.isNull() && model); assert(!authenticated_encryption.isNull() && model);
authenticated_encryption->createKey(model->getEmail(), password); authenticated_encryption->createKey(model->getEmail(), password);
observer->removeTask(email_hash, TASK_OBSERVER_PASSWORD_CREATION);
if (authenticated_encryption->getKeyHashed() == model->getPasswordHashed()) if (authenticated_encryption->getKeyHashed() == model->getPasswordHashed())
{ {
// printf("[User::login] password key hashed is the same as saved password hash\n"); // printf("[User::login] password key hashed is the same as saved password hash\n");
@ -155,6 +164,7 @@ namespace controller {
if (mGradidoKeyPair) { if (mGradidoKeyPair) {
if (mGradidoKeyPair->isTheSame(clear_private_key) == 0) { if (mGradidoKeyPair->isTheSame(clear_private_key) == 0) {
mPassword = authenticated_encryption; mPassword = authenticated_encryption;
mCanDecryptPrivateKey = true;
return 1; return 1;
} }
else { else {
@ -171,6 +181,7 @@ namespace controller {
} }
//printf("correct pwd\n"); //printf("correct pwd\n");
mPassword = authenticated_encryption; mPassword = authenticated_encryption;
mCanDecryptPrivateKey = true;
return 1; return 1;
} }
else { else {
@ -193,16 +204,30 @@ namespace controller {
std::unique_lock<std::shared_mutex> _lock(mSharedMutex); std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
if (mGradidoKeyPair) delete mGradidoKeyPair; if (mGradidoKeyPair) delete mGradidoKeyPair;
mGradidoKeyPair = gradidoKeyPair; mGradidoKeyPair = gradidoKeyPair;
getModel()->setPublicKey(mGradidoKeyPair->getPublicKey());
if (mPassword && mPassword->hasKey()) {
auto model = getModel(); auto model = getModel();
model->setPublicKey(mGradidoKeyPair->getPublicKey());
if (mPassword && mPassword->hasKey()) {
model->setPrivateKey(mGradidoKeyPair->getCryptedPrivKey(mPassword)); model->setPrivateKey(mGradidoKeyPair->getCryptedPrivKey(mPassword));
return 1; return 1;
} }
return 0; return 0;
} }
int User::setNewPassword(const std::string& password)
{
auto observer = SingletonTaskObserver::getInstance();
auto model = getModel();
auto email_hash = observer->makeHash(model->getEmail());
int User::setPassword(Poco::AutoPtr<AuthenticatedEncryption> passwd) observer->addTask(email_hash, TASK_OBSERVER_PASSWORD_CREATION);
Poco::AutoPtr<AuthenticatedEncryption> authenticated_encryption(new AuthenticatedEncryption);
assert(!authenticated_encryption.isNull() && model);
authenticated_encryption->createKey(model->getEmail(), password);
observer->removeTask(email_hash, TASK_OBSERVER_PASSWORD_CREATION);
return setNewPassword(authenticated_encryption);
}
int User::setNewPassword(Poco::AutoPtr<AuthenticatedEncryption> passwd)
{ {
std::unique_lock<std::shared_mutex> _lock(mSharedMutex); std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
auto model = getModel(); auto model = getModel();
@ -232,6 +257,7 @@ namespace controller {
if (*mGradidoKeyPair != model->getPublicKey()) { if (*mGradidoKeyPair != model->getPublicKey()) {
delete mGradidoKeyPair; delete mGradidoKeyPair;
mGradidoKeyPair = nullptr; mGradidoKeyPair = nullptr;
mCanDecryptPrivateKey = false;
return -1; return -1;
} }
} }
@ -249,6 +275,7 @@ namespace controller {
MemoryManager::getInstance()->releaseMemory(encryptedPrivateKey); MemoryManager::getInstance()->releaseMemory(encryptedPrivateKey);
result = model->updatePrivkeyAndPasswordHash(); result = model->updatePrivkeyAndPasswordHash();
mCanDecryptPrivateKey = true;
} }
else { else {
model->updateIntoDB("password", mPassword->getKeyHashed()); model->updateIntoDB("password", mPassword->getKeyHashed());

View File

@ -50,12 +50,13 @@ namespace controller {
std::string getEmailWithNames(); std::string getEmailWithNames();
const std::string& getPublicHex(); const std::string& getPublicHex();
//! \brief check if password match saved password, long duration //! \brief check if password match saved password, long duration, load Key pair
//! \return 1 logged in //! \return 1 logged in
//! \return 2 already logged in //! \return 2 already logged in
//! \return 0 password didn't match //! \return 0 password didn't match
//! \return -1 error saved public key didn't match with private key //! \return -1 error saved public key didn't match with private key
//! \return -2 error decrypting private key //! \return -2 error decrypting private key
//! \return -3 password key creation already running
//! - create authenticated encryption key from password and email //! - create authenticated encryption key from password and email
//! - compare hash with in db saved hash //! - compare hash with in db saved hash
@ -69,7 +70,16 @@ namespace controller {
//! \return 1 = password changed, private key re-encrypted and saved into db //! \return 1 = password changed, private key re-encrypted and saved into db
//! \return 2 = password changed, only hash stored in db, couldn't load private key for re-encryption //! \return 2 = password changed, only hash stored in db, couldn't load private key for re-encryption
//! \return -1 = stored pubkey and private key didn't match //! \return -1 = stored pubkey and private key didn't match
int setPassword(Poco::AutoPtr<AuthenticatedEncryption> passwd); int setNewPassword(Poco::AutoPtr<AuthenticatedEncryption> passwd);
//! \brief set authenticated encryption and save hash in db, also re encrypt private key if exist
//! \param password as string
//! \return 0 = new and current passwords are the same
//! \return 1 = password changed, private key re-encrypted and saved into db
//! \return 2 = password changed, only hash stored in db, couldn't load private key for re-encryption
//! \return -1 = stored pubkey and private key didn't match
int setNewPassword(const std::string& password);
//! \brief return AuthenticatedEncryption Auto Pointer //! \brief return AuthenticatedEncryption Auto Pointer
inline const Poco::AutoPtr<AuthenticatedEncryption> getPassword() { inline const Poco::AutoPtr<AuthenticatedEncryption> getPassword() {
@ -80,10 +90,14 @@ namespace controller {
std::shared_lock<std::shared_mutex> _lock(mSharedMutex); std::shared_lock<std::shared_mutex> _lock(mSharedMutex);
return !mPassword.isNull(); return !mPassword.isNull();
} }
inline bool canDecryptPrivateKey() {
std::shared_lock<std::shared_mutex> _lock(mSharedMutex);
return mCanDecryptPrivateKey;
}
inline bool hasPublicKey() { inline bool hasPublicKey() {
return getModel()->getPublicKey(); return getModel()->getPublicKey();
} }
//! \brief set key pair, public in model, private if password exist else with next setPassword call into model //! \brief set key pair, public in model, private if password exist else with next setPassword call into model, overwrite existing key pair, not saving into db
//! \param gradidoKeyPair take owner ship //! \param gradidoKeyPair take owner ship
//! \param return 0 if public key set //! \param return 0 if public key set
//! \param return 1 if also private key set (and password exist) //! \param return 1 if also private key set (and password exist)
@ -104,6 +118,8 @@ namespace controller {
Poco::AutoPtr<AuthenticatedEncryption> mPassword; Poco::AutoPtr<AuthenticatedEncryption> mPassword;
KeyPairEd25519* mGradidoKeyPair; KeyPairEd25519* mGradidoKeyPair;
bool mCanDecryptPrivateKey;
mutable std::shared_mutex mSharedMutex; mutable std::shared_mutex mSharedMutex;
}; };
} }

View File

@ -1,5 +1,7 @@
#include "UserBackups.h" #include "UserBackups.h"
#include "../Crypto/Passphrase.h"
namespace controller { namespace controller {
UserBackups::UserBackups(model::table::UserBackups* dbModel) UserBackups::UserBackups(model::table::UserBackups* dbModel)
{ {
@ -61,7 +63,12 @@ namespace controller {
KeyPairEd25519* UserBackups::createGradidoKeyPair() KeyPairEd25519* UserBackups::createGradidoKeyPair()
{ {
auto model = getModel();
auto mnemonicType = model->getMnemonicType();
assert(mnemonicType >= 0 && mnemonicType < ServerConfig::MNEMONIC_MAX);
auto wordSource = &ServerConfig::g_Mnemonic_WordLists[mnemonicType];
Poco::AutoPtr<Passphrase> passphrase = new Passphrase(model->getPassphrase(), wordSource);
return KeyPairEd25519::create(passphrase);
} }
std::string UserBackups::getPassphrase(ServerConfig::Mnemonic_Types type) std::string UserBackups::getPassphrase(ServerConfig::Mnemonic_Types type)

View File

@ -665,7 +665,7 @@ void Session::finalizeTransaction(bool sign, bool reject)
if (!reject) { if (!reject) {
if (sign) { if (sign) {
Poco::AutoPtr<SigningTransaction> signingTransaction(new SigningTransaction(mCurrentActiveProcessingTransaction, mSessionUser)); Poco::AutoPtr<SigningTransaction> signingTransaction(new SigningTransaction(mCurrentActiveProcessingTransaction, mNewUser));
signingTransaction->scheduleTask(signingTransaction); signingTransaction->scheduleTask(signingTransaction);
} }
} }
@ -745,7 +745,27 @@ UserStates Session::loadUser(const std::string& email, const std::string& passwo
} }
// error decrypting private key // error decrypting private key
if (-2 == loginResult) { if (-2 == loginResult) {
// check if we have access to the passphrase, if so we can reencrypt the private key
auto user_model = mNewUser->getModel();
auto user_backups = controller::UserBackups::load(user_model->getID());
for (auto it = user_backups.begin(); it != user_backups.end(); it++) {
auto key = (*it)->createGradidoKeyPair();
if (key->isTheSame(user_model->getPublicKey())) {
auto crypted_private_key = key->getCryptedPrivKey(mNewUser->getPassword());
if (crypted_private_key) {
user_model->setPrivateKey(crypted_private_key);
MemoryManager::getInstance()->releaseMemory(crypted_private_key);
}
else {
auto em = ErrorManager::getInstance();
em->addError(new Error(functionName, "error reencrypt private key"));
em->addError(new ParamError(functionName, "for user with email", user_model->getEmail()));
em->sendErrorsAsEmail();
}
break;
}
delete key;
}
} }
// can be removed if session user isn't used any more // can be removed if session user isn't used any more
if (mNewUser->getModel()->getPasswordHashed() && !mSessionUser->validatePwd(password, this)) { if (mNewUser->getModel()->getPasswordHashed() && !mSessionUser->validatePwd(password, this)) {
@ -1103,7 +1123,7 @@ bool Session::generateKeys(bool savePrivkey, bool savePassphrase)
} }
if (savePassphrase) { if (savePassphrase) {
auto user_backup = controller::UserBackups::create(user_model->getID(), passphrase->getString()); auto user_backup = controller::UserBackups::create(user_model->getID(), passphrase->getString(), mnemonic_type);
// sync version // sync version
//user_backup->getModel()->insertIntoDB(false); //user_backup->getModel()->insertIntoDB(false);

View File

@ -125,9 +125,12 @@ public:
// ------------------------ Passphrase functions ---------------------------- // ------------------------ Passphrase functions ----------------------------
inline void setPassphrase(Poco::AutoPtr<Passphrase> passphrase) { mNewPassphrase = passphrase; }
inline Poco::AutoPtr<Passphrase> getPassphrase() { return mNewPassphrase; }
inline void setPassphrase(const std::string& passphrase) { mPassphrase = passphrase; } inline void setPassphrase(const std::string& passphrase) { mPassphrase = passphrase; }
inline const std::string& getPassphrase() { return mPassphrase; } inline const std::string& getOldPassphrase() { return mPassphrase; }
bool generatePassphrase(); bool generatePassphrase();
bool generateKeys(bool savePrivkey, bool savePassphrase); bool generateKeys(bool savePrivkey, bool savePassphrase);
@ -187,6 +190,7 @@ private:
Poco::AutoPtr<User> mSessionUser; Poco::AutoPtr<User> mSessionUser;
Poco::AutoPtr<controller::User> mNewUser; Poco::AutoPtr<controller::User> mNewUser;
std::string mPassphrase; std::string mPassphrase;
Poco::AutoPtr<Passphrase> mNewPassphrase;
Poco::DateTime mLastActivity; Poco::DateTime mLastActivity;
Poco::Net::IPAddress mClientLoginIP; Poco::Net::IPAddress mClientLoginIP;
std::string mLastExternReferer; std::string mLastExternReferer;