new passphrase generate code

This commit is contained in:
Dario 2020-02-26 16:39:49 +01:00
parent fc22bbc1e0
commit a7a1758db8
9 changed files with 199 additions and 46 deletions

View File

@ -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;

View File

@ -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:

View File

@ -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();

View File

@ -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);

View File

@ -38,6 +38,8 @@ public:
inline size_t size() const { return static_cast<size_t>(mSize); }
inline operator size_t() const { return static_cast<size_t>(mSize); }
inline unsigned char* data() { return mData; }
protected:
MemoryBin(Poco::UInt32 size);
~MemoryBin();

View File

@ -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;
}

View File

@ -551,6 +551,7 @@ bool User::validatePassphrase(const std::string& passphrase, Mnemonic** wordSour
std::istringstream iss(passphrase);
std::vector<std::string> results(std::istream_iterator<std::string>{iss},
std::istream_iterator<std::string>());
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;
}
}

View File

@ -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

View File

@ -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&uuml;ltig, bitte &uuml;berpr&uuml;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" %>
<div class="row mb-3" style="margin-top:70px;">
<h2 class="mx-auto"><%= gettext("Passphrase umwandeln") %></h2>
</div>
<div class="item-wrapper">
<div class="row mb-3">
<div class="col-md-10 mx-auto">
<div class="form-group row showcase_row_area">
<div class="col-md-12 col-lg-12 ">
<div class="alert alert-orange">
<h5 class="alert-heading"><%= gettext("Was zu tun ist:") %></h5>
<p><%= gettext("Kopiere/schreibe deine Passphrase in die Textbox und du bekommst sie in die jeweils andere Sprache umgewandelt.") %></p>
<p><%= gettext("Du kannst mit beiden Varianten dein Konto wiederherstellen oder dein Passwort ändern.") %></p>
</div>
</div>
<div class="col-lg-12 col-md-12 mb-5">
<form action="<%= uri_start %>/transform_passphrase">
<div class="form-group row-showcase_row_area">
<textarea name="inputPassphrase" cols="10" rows="5" id="inputPassphrase" class="form-control" placeholder="<%= gettext("deine Passphrase") %>"><%= inputPassphrase %></textarea>
</div>
<input name="btnTransform" type="submit" value="Umwandeln" class="btn btn btn-orange">
<% if(controller::USER_ROLE_ADMIN == role) { %>
<input name="btnGenerate" type="submit" value="Neue generieren" class="btn btn-secondary">
<% } %>
</form>
</div>
<% if(passphrase != "") { %>
<div class="col-lg-12 col-md-12">
<div class="alert alert-success">
<h5 class="alert-heading">Umgewandelte Passphrase: </h5>
<p><%= passphrase %></p>
</div>
</div>
<% } %>
</div>
</div>
</div>
<%@ include file="footer_ripple.cpsp" %>