diff --git a/src/cpp/Crypto/KeyPair.cpp b/src/cpp/Crypto/KeyPair.cpp index f435e166c..842d3902c 100644 --- a/src/cpp/Crypto/KeyPair.cpp +++ b/src/cpp/Crypto/KeyPair.cpp @@ -6,7 +6,9 @@ #include "../SingletonManager/ErrorManager.h" #include "../SingletonManager/ConnectionManager.h" -//#include "Poco/ISO8859_4Encoding.h" +#include "Poco/Types.h" + +#include "../ServerConfig.h" using namespace Poco::Data::Keywords; @@ -39,46 +41,37 @@ KeyPair::~KeyPair() } } -bool KeyPair::generateFromPassphrase(const char* passphrase, Mnemonic* word_source) +std::string KeyPair::passphraseTransform(const std::string& passphrase, const Mnemonic* currentWordSource, const Mnemonic* targetWordSource) +{ + if (!currentWordSource || !targetWordSource) { + return ""; + } + if (targetWordSource == currentWordSource) { + return passphrase; + } + auto word_indices = createWordIndices(passphrase, currentWordSource); + if (!word_indices) { + return ""; + } + + return createClearPassphraseFromWordIndices(word_indices, targetWordSource); +} + +bool KeyPair::generateFromPassphrase(const char* passphrase, const Mnemonic* word_source) { auto er = ErrorManager::getInstance(); + auto mm = MemoryManager::getInstance(); // libsodium doc: https://libsodium.gitbook.io/doc/advanced/hmac-sha2 // https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki //crypto_auth_hmacsha512_keygen - unsigned long word_indices[PHRASE_WORD_COUNT]; - memset(word_indices, 0, PHRASE_WORD_COUNT); - - //DHASH key = DRMakeStringHash(passphrase); - size_t pass_phrase_size = strlen(passphrase); - std::string clearPassphrase = ""; - char acBuffer[STR_BUFFER_SIZE]; memset(acBuffer, 0, STR_BUFFER_SIZE); - size_t buffer_cursor = 0; - // get word indices for hmac key - unsigned char word_cursor = 0; - for (size_t i = 0; i <= pass_phrase_size; i++) { - if (passphrase[i] == ' ' || passphrase[i] == '\0') { - if(buffer_cursor < 3) continue; - if (word_source->isWordExist(acBuffer)) { - clearPassphrase += acBuffer; - clearPassphrase += " "; - word_indices[word_cursor] = word_source->getWordIndex(acBuffer); - //printf("index for %s is: %hu\n", acBuffer, word_source->getWordIndex(acBuffer)); - } - else { - er->addError(new ParamError("KeyPair::generateFromPassphrase", "word didn't exist", acBuffer)); - er->sendErrorsAsEmail(); - return false; - } - - word_cursor++; - memset(acBuffer, 0, STR_BUFFER_SIZE); - buffer_cursor = 0; - } - else { - acBuffer[buffer_cursor++] = passphrase[i]; - } - + auto word_indices = createWordIndices(passphrase, word_source); + if (!word_indices) { + return false; } + std::string clearPassphrase = + createClearPassphraseFromWordIndices(word_indices, &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]); + + sha_context state; unsigned char hash[SHA_512_SIZE]; @@ -92,6 +85,8 @@ bool KeyPair::generateFromPassphrase(const char* passphrase, Mnemonic* word_sour sha512_final(&state, hash); //crypto_auth_hmacsha512_final(&state, hash); + mm->releaseMemory(word_indices); + // debug passphrase // printf("\passsphrase: <%s>\n", passphrase); //printf("word_indices: \n%s\n", getHex((unsigned char*)word_indices, sizeof(word_indices)).data()); @@ -111,8 +106,6 @@ bool KeyPair::generateFromPassphrase(const char* passphrase, Mnemonic* word_sour public_key_t pbl_key_t; ed25519_derive_public_key(&prv_key_t, &pbl_key_t); - auto mm = MemoryManager::getInstance(); - //memcpy(private_key, prv_key_t.data, 32); if (!mPrivateKey) { //delete mPrivateKey; @@ -151,6 +144,70 @@ bool KeyPair::generateFromPassphrase(const char* passphrase, Mnemonic* word_sour return true; } +MemoryBin* KeyPair::createWordIndices(const std::string& passphrase, const Mnemonic* word_source) +{ + auto er = ErrorManager::getInstance(); + auto mm = MemoryManager::getInstance(); + + auto word_indices = mm->getFreeMemory(sizeof(Poco::UInt32) * PHRASE_WORD_COUNT); + Poco::UInt32* word_indices_p = (Poco::UInt32*)(word_indices->data()); + unsigned long word_indices_old[PHRASE_WORD_COUNT] = { 0 }; + //memset(word_indices_old, 0, PHRASE_WORD_COUNT);// *sizeof(unsigned long)); + memset(*word_indices, 0, word_indices->size()); + + //DHASH key = DRMakeStringHash(passphrase); + size_t pass_phrase_size = passphrase.size(); + + char acBuffer[STR_BUFFER_SIZE]; memset(acBuffer, 0, STR_BUFFER_SIZE); + size_t buffer_cursor = 0; + + // get word indices for hmac key + unsigned char word_cursor = 0; + for (auto it = passphrase.begin(); it != passphrase.end(); it++) { + if (*it == ' ' || *it == '\0') { + if (buffer_cursor < 3) continue; + if (word_source->isWordExist(acBuffer)) { + word_indices_p[word_cursor] = word_source->getWordIndex(acBuffer); + word_indices_old[word_cursor] = word_source->getWordIndex(acBuffer); + } + else { + er->addError(new ParamError("KeyPair::generateFromPassphrase", "word didn't exist", acBuffer)); + er->sendErrorsAsEmail(); + mm->releaseMemory(word_indices); + return nullptr; + } + word_cursor++; + memset(acBuffer, 0, STR_BUFFER_SIZE); + buffer_cursor = 0; + + } + else { + acBuffer[buffer_cursor++] = *it; + } + } + if (memcmp(word_indices_p, word_indices_old, word_indices->size()) != 0) { + + printf("not identical\n"); + memcpy(word_indices_p, word_indices_old, word_indices->size()); + } + return word_indices; +} + +std::string KeyPair::createClearPassphraseFromWordIndices(MemoryBin* word_indices, const Mnemonic* word_source) +{ + Poco::UInt32* word_indices_p = (Poco::UInt32*)word_indices->data(); + std::string clearPassphrase; + for (int i = 0; i < PHRASE_WORD_COUNT; i++) { + if (i * sizeof(Poco::UInt32) >= word_indices->size()) break; + auto word = word_source->getWord(word_indices_p[i]); + if (word) { + clearPassphrase += word; + clearPassphrase += " "; + } + } + return clearPassphrase; +} + std::string KeyPair::filterPassphrase(const std::string& passphrase) { std::string filteredPassphrase; diff --git a/src/cpp/Crypto/KeyPair.h b/src/cpp/Crypto/KeyPair.h index 3445f69bd..a7d001c76 100644 --- a/src/cpp/Crypto/KeyPair.h +++ b/src/cpp/Crypto/KeyPair.h @@ -23,8 +23,10 @@ public: KeyPair(); ~KeyPair(); - bool generateFromPassphrase(const char* passphrase, Mnemonic* word_source); + bool generateFromPassphrase(const char* passphrase, const Mnemonic* word_source); + static std::string passphraseTransform(const std::string& passphrase, const Mnemonic* currentWordSource, const Mnemonic* targetWordSource); static std::string filterPassphrase(const std::string& passphrase); + std::string getPubkeyHex(); bool savePrivKey(int userId); static std::string getHex(const unsigned char* data, Poco::UInt32 size); @@ -37,6 +39,8 @@ public: protected: const MemoryBin* getPrivateKey() const { return mSodiumSecret; } + static MemoryBin* createWordIndices(const std::string& passphrase, const Mnemonic* word_source); + static std::string createClearPassphraseFromWordIndices(MemoryBin* word_indices, const Mnemonic* word_source); private: diff --git a/src/cpp/Crypto/mnemonic.h b/src/cpp/Crypto/mnemonic.h index 3197922a8..22cf753b3 100644 --- a/src/cpp/Crypto/mnemonic.h +++ b/src/cpp/Crypto/mnemonic.h @@ -30,9 +30,9 @@ public: int init(void(*fill_words_func)(unsigned char*), unsigned int original_size, unsigned int compressed_size); - inline const char* getWord(unsigned int index) { Poco::Mutex::ScopedLock _lock(mWorkingMutex, 500); if (index < 2048 && index >= 0) return mWords[index]; return nullptr; } - inline unsigned short getWordIndex(const char* word) { Poco::Mutex::ScopedLock _lock(mWorkingMutex, 500); DHASH word_hash = DRMakeStringHash(word); return mWordHashIndices.find(word_hash)->second; } - inline bool isWordExist(const std::string& word) { Poco::Mutex::ScopedLock _lock(mWorkingMutex, 500); DHASH word_hash = DRMakeStringHash(word.data()); return mWordHashIndices.find(word_hash) != mWordHashIndices.end(); } + inline const char* getWord(unsigned int index) const { if (index < 2048 && index >= 0) return mWords[index]; return nullptr; } + inline unsigned short getWordIndex(const char* word) const { DHASH word_hash = DRMakeStringHash(word); return mWordHashIndices.find(word_hash)->second; } + inline bool isWordExist(const std::string& word) const { DHASH word_hash = DRMakeStringHash(word.data()); return mWordHashIndices.find(word_hash) != mWordHashIndices.end(); } // using only for debugging std::string getCompleteWordList(); diff --git a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp index 1982ec801..92d58c666 100644 --- a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp +++ b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp @@ -21,6 +21,7 @@ #include "RegisterAdminPage.h" #include "DebugPassphrasePage.h" #include "AdminCheckUserBackup.h" +#include "TranslatePassphrase.h" #include "DecodeTransactionPage.h" @@ -121,7 +122,6 @@ Poco::Net::HTTPRequestHandler* PageRequestHandlerFactory::createRequestHandler(c if (externReferer != "") { s->setLastReferer(externReferer); } - auto user = s->getUser(); if (s->errorCount() || (!user.isNull() && user->errorCount())) { user->sendErrorsAsEmail(); @@ -134,6 +134,11 @@ Poco::Net::HTTPRequestHandler* PageRequestHandlerFactory::createRequestHandler(c pageRequestHandler->setProfiler(timeUsed); return pageRequestHandler; } + if (url_first_part == "/transform_passphrase") { + auto pageRequestHandler = new TranslatePassphrase(s); + pageRequestHandler->setProfiler(timeUsed); + return pageRequestHandler; + } if (s->getNewUser()->getModel()->getRole() == model::table::ROLE_ADMIN) { if (url_first_part == "/adminRegister") { auto pageRequestHandler = new RegisterAdminPage(s); diff --git a/src/cpp/SingletonManager/MemoryManager.h b/src/cpp/SingletonManager/MemoryManager.h index 1dca91678..49ad9c5c2 100644 --- a/src/cpp/SingletonManager/MemoryManager.h +++ b/src/cpp/SingletonManager/MemoryManager.h @@ -38,6 +38,8 @@ public: inline size_t size() const { return static_cast(mSize); } inline operator size_t() const { return static_cast(mSize); } + inline unsigned char* data() { return mData; } + protected: MemoryBin(Poco::UInt32 size); ~MemoryBin(); diff --git a/src/cpp/model/Session.cpp b/src/cpp/model/Session.cpp index fecd3c71d..b9e2e7298 100644 --- a/src/cpp/model/Session.cpp +++ b/src/cpp/model/Session.cpp @@ -926,13 +926,13 @@ bool Session::useOrGeneratePassphrase(const std::string& passphase) bool Session::generatePassphrase() { auto lang = getLanguage(); - if (lang == LANG_EN) { + /*if (lang == LANG_EN) { mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]); } else { mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]); - } - + }*/ + mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]); updateState(SESSION_STATE_PASSPHRASE_GENERATED); return true; } diff --git a/src/cpp/model/User.cpp b/src/cpp/model/User.cpp index 3cde6bb9c..7d584eb23 100644 --- a/src/cpp/model/User.cpp +++ b/src/cpp/model/User.cpp @@ -551,6 +551,7 @@ bool User::validatePassphrase(const std::string& passphrase, Mnemonic** wordSour std::istringstream iss(passphrase); std::vector results(std::istream_iterator{iss}, std::istream_iterator()); + for (int i = 0; i < ServerConfig::Mnemonic_Types::MNEMONIC_MAX; i++) { Mnemonic& m = ServerConfig::g_Mnemonic_WordLists[i]; bool existAll = true; @@ -569,6 +570,7 @@ bool User::validatePassphrase(const std::string& passphrase, Mnemonic** wordSour if (wordSource) { *wordSource = &m; } + return true; } } diff --git a/src/cpsp/passphrase.cpsp b/src/cpsp/passphrase.cpsp index 9979b71ea..79aeed429 100644 --- a/src/cpsp/passphrase.cpsp +++ b/src/cpsp/passphrase.cpsp @@ -38,7 +38,7 @@ enum PageState //Mnemonic* wordSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]; Mnemonic* wordSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]; if(lang == LANG_DE) { - wordSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]; + //wordSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]; } // remove old cookies if exist diff --git a/src/cpsp/translatePassphrase.cpsp b/src/cpsp/translatePassphrase.cpsp index b556ddb5e..e6f84ebd6 100644 --- a/src/cpsp/translatePassphrase.cpsp +++ b/src/cpsp/translatePassphrase.cpsp @@ -4,3 +4,86 @@ <%@ header include="SessionHTTPRequestHandler.h" %> <%@ page form="true" %> <%@ page compressed="true" %> +<%! +#include "../Crypto/KeyPair.h" +#include "../ServerConfig.h" +%> +<%% + chooseLanguage(request); + // variable needed for flags + auto lang = mSession->getLanguage(); + auto uri_start = ServerConfig::g_serverPath; + const char* pageName = gettext("Passphrase Transformieren"); + std::string passphrase; + auto role = mSession->getNewUser()->getModel()->getRole(); + std::string inputPassphrase; + + Mnemonic* wordSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]; + Mnemonic* targetSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]; + if(lang == LANG_DE) { + wordSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]; + targetSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]; + } + + if(!form.empty()) + { + + inputPassphrase = form.get("inputPassphrase", ""); + auto localPassphrase = KeyPair::filterPassphrase(inputPassphrase); + if(localPassphrase != "" && !User::validatePassphrase(localPassphrase, &wordSource)) { + addError(new Error( + gettext("Fehler"), + gettext("Diese Passphrase ist ungültig, bitte überprüfen oder neu generieren (lassen).") + )); + } else { + if(wordSource == &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]) { + targetSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]; + } else { + targetSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]; + } + passphrase = KeyPair::passphraseTransform(localPassphrase, wordSource, targetSource); + } + + auto btnGenerate = form.get("btnGenerate", ""); + if("" != btnGenerate) { + passphrase = mSession->generatePassphrase(); + } + } +%><%@ include file="login_header.cpsp" %><%@ include file="flags.cpsp" %> +
+

<%= gettext("Passphrase umwandeln") %>

+
+
+
+
+
+
+
+
<%= gettext("Was zu tun ist:") %>
+

<%= gettext("Kopiere/schreibe deine Passphrase in die Textbox und du bekommst sie in die jeweils andere Sprache umgewandelt.") %>

+

<%= gettext("Du kannst mit beiden Varianten dein Konto wiederherstellen oder dein Passwort ändern.") %>

+
+
+
+
+
+ +
+ + <% if(controller::USER_ROLE_ADMIN == role) { %> + + <% } %> +
+
+ <% if(passphrase != "") { %> +
+
+
Umgewandelte Passphrase:
+

<%= passphrase %>

+
+
+ <% } %> +
+
+
+<%@ include file="footer_ripple.cpsp" %> \ No newline at end of file