diff --git a/Doxyfile b/Doxyfile index 4c7738a3d..c0d745373 100644 --- a/Doxyfile +++ b/Doxyfile @@ -32,19 +32,19 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = "Gradido Node" +PROJECT_NAME = "Gradido Login-Server" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.20.KW10.06 +PROJECT_NUMBER = 0.20.KW11.02 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = "validate, store and provide Gradido Transactions" +PROJECT_BRIEF = "Store Keys and Login-Data for Gradido" # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 @@ -68,7 +68,7 @@ OUTPUT_DIRECTORY = ./doc # performance problems for the file system. # The default value is: NO. -CREATE_SUBDIRS = NO +CREATE_SUBDIRS = YES # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII diff --git a/src/cpp/Crypto/KeyPair.h b/src/cpp/Crypto/KeyPair.h index a7d001c76..088e7092d 100644 --- a/src/cpp/Crypto/KeyPair.h +++ b/src/cpp/Crypto/KeyPair.h @@ -13,12 +13,14 @@ class UserWriteKeysIntoDB; class UserGenerateKeys; class DebugPassphrasePage; +class User; // TODO: https://libsodium.gitbook.io/doc/advanced/ed25519-curve25519 class KeyPair { friend UserWriteKeysIntoDB; friend UserGenerateKeys; friend DebugPassphrasePage; + friend User; public: KeyPair(); ~KeyPair(); diff --git a/src/cpp/model/Session.cpp b/src/cpp/model/Session.cpp index 7b59b2ace..0f585f9ab 100644 --- a/src/cpp/model/Session.cpp +++ b/src/cpp/model/Session.cpp @@ -19,6 +19,7 @@ #include "../lib/JsonRequest.h" #include "../controller/User.h" +#include "../controller/UserBackups.h" #include "../controller/EmailVerificationCode.h" #include "table/ModelBase.h" @@ -787,20 +788,48 @@ void Session::detectSessionState() if (USER_NO_KEYS == userState) { + auto user_id = mSessionUser->getDBId(); + auto userBackups = controller::UserBackups::load(user_id); + + // check passphrase, only possible while passphrase isn't crypted in db + bool correctPassphraseFound = false; + bool cryptedPassphrase = false; + for (auto it = userBackups.begin(); it != userBackups.end(); it++) { + KeyPair keys; + auto passphrase = (*it)->getModel()->getPassphrase(); + Mnemonic* wordSource = nullptr; + if (User::validatePassphrase(passphrase, &wordSource)) { + if (keys.generateFromPassphrase((*it)->getModel()->getPassphrase().data(), wordSource)) { + if (sodium_memcmp(mSessionUser->getPublicKey(), keys.getPublicKey(), ed25519_pubkey_SIZE) == 0) { + correctPassphraseFound = true; + break; + } + } + } + else { + cryptedPassphrase = true; + } + } + /* auto dbConnection = ConnectionManager::getInstance()->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); Poco::Data::Statement select(dbConnection); Poco::Nullable passphrase; - auto user_id = mSessionUser->getDBId(); + select << "SELECT passphrase from user_backups where user_id = ?;", into(passphrase), use(user_id); try { if (select.execute() == 1 && !passphrase.isNull()) { + //KeyPair keys;keys.generateFromPassphrase(passphrase.value().rawContent()) updateState(SESSION_STATE_PASSPHRASE_WRITTEN); return; } } catch (Poco::Exception& exc) { printf("[Session::detectSessionState] 2 mysql exception: %s\n", exc.displayText().data()); + }*/ + if (correctPassphraseFound || cryptedPassphrase) { + updateState(SESSION_STATE_PASSPHRASE_WRITTEN); + return; } if (mPassphrase != "") { updateState(SESSION_STATE_PASSPHRASE_GENERATED); diff --git a/src/cpp/model/User.cpp b/src/cpp/model/User.cpp index 49dff46c3..0aba84292 100644 --- a/src/cpp/model/User.cpp +++ b/src/cpp/model/User.cpp @@ -12,6 +12,8 @@ #include "../SingletonManager/LanguageManager.h" #include "../SingletonManager/SingletonTaskObserver.h" +#include "../controller/UserBackups.h" + #include "Poco/Data/Binding.h" @@ -1085,8 +1087,53 @@ MemoryBin* User::sign(const unsigned char* message, size_t messageSize) auto mm = MemoryManager::getInstance(); //auto signBinBuffer = (unsigned char*)malloc(crypto_sign_BYTES); auto privKey = getPrivKey(); + if (!privKey) { addError(new Error("User::sign", "decrypt privkey failed")); + + auto userBackups = controller::UserBackups::load(mDBId); + + // get privkey, only possible while passphrase isn't crypted in db + bool correctPassphraseFound = false; + KeyPair keys; + for (auto it = userBackups.begin(); it != userBackups.end(); it++) { + + auto passphrase = (*it)->getModel()->getPassphrase(); + Mnemonic* wordSource = nullptr; + if (User::validatePassphrase(passphrase, &wordSource)) { + if (keys.generateFromPassphrase((*it)->getModel()->getPassphrase().data(), wordSource)) { + if(keys.isPubkeysTheSame(getPublicKey())) + { + correctPassphraseFound = true; + break; + } + } + } + } + if (correctPassphraseFound) { + auto const_privKey = keys.getPrivateKey(); + auto signBinBuffer = mm->getFreeMemory(crypto_sign_BYTES); + + unsigned long long actualSignLength = 0; + + if (crypto_sign_detached(*signBinBuffer, &actualSignLength, message, messageSize, *const_privKey)) { + addError(new Error("User::sign 2", "sign failed")); + mm->releaseMemory(signBinBuffer); + return nullptr; + } + + if (crypto_sign_verify_detached(*signBinBuffer, message, messageSize, mPublicKey) != 0) { + // Incorrect signature! + //printf("c[KeyBuffer::%s] sign verify failed\n", __FUNCTION__); + addError(new Error("User::sign 2", "sign verify failed")); + mm->releaseMemory(privKey); + mm->releaseMemory(signBinBuffer); + return nullptr; + } + + return signBinBuffer; + } + return nullptr; }