make it more modular

This commit is contained in:
Dario 2020-06-01 19:13:38 +02:00
parent 80cd472597
commit 1aeb506cd3
8 changed files with 372 additions and 8 deletions

View File

@ -12,15 +12,8 @@
using namespace Poco::Data::Keywords;
#define STR_BUFFER_SIZE 25
static std::vector<Poco::Tuple<int, std::string>> g_specialChars = {
{ 0xa4, "auml" },{ 0x84, "Auml" },
{ 0xbc, "uuml" },{ 0x9c, "Uuml" },
{ 0xb6, "ouml" },{ 0x96, "Ouml" },
{ 0x9f, "szlig" }
};
KeyPair::KeyPair()

View File

@ -52,12 +52,19 @@ protected:
private:
// 32 Byte
//! \brief ed25519 ref10 private key
MemoryBin* mPrivateKey;
// 64 Byte
//! \brief ed25519 libsodium private key
MemoryBin* mSodiumSecret;
// 32 Byte
//! \brief ed25519 ref10 public key
unsigned char mPublicKey[ed25519_pubkey_SIZE];
// 32 Byte
//! \brief ed25519 libsodium public key
unsigned char mSodiumPublic[crypto_sign_PUBLICKEYBYTES];
};

View File

@ -0,0 +1,240 @@
#include "Passphrase.h"
#include "Poco/Types.h"
#include "Poco/Tuple.h"
#include "../SingletonManager/ErrorManager.h"
#include "../ServerConfig.h"
#define STR_BUFFER_SIZE 25
static std::vector<Poco::Tuple<int, std::string>> g_specialChars = {
{ 0xa4, "auml" },{ 0x84, "Auml" },
{ 0xbc, "uuml" },{ 0x9c, "Uuml" },
{ 0xb6, "ouml" },{ 0x96, "Ouml" },
{ 0x9f, "szlig" }
};
Passphrase::Passphrase(const std::string& passphrase, const Mnemonic* wordSource)
: mPassphraseString(filter(passphrase)), mWordSource(wordSource)
{
memset(mWordIndices, 0, PHRASE_WORD_COUNT * sizeof(Poco::UInt16));
}
std::string Passphrase::filter(const std::string& passphrase)
{
std::string filteredPassphrase;
auto passphrase_size = passphrase.size();
for (int i = 0; i < passphrase_size; i++) {
unsigned char c = passphrase.data()[i];
// asci 128 even by utf8 (hex)
// 0000 0000 0000 007F
// utf8
if (c > 0x0000007F) {
int additionalUtfByteCount = 0;
//filteredPassphrase += c;
if ((c & 0x00000080) == 0x00000080) {
// c3 a4 => ä
// c3 bc => ü
// c3 b6 => ö
// c3 84 => Ä
// c3 96 => Ö
// c3 9c => Ü
// c3 9f => ß
unsigned char c2 = passphrase.data()[i + 1];
bool insertedHtmlEntitie = false;
for (auto it = g_specialChars.begin(); it != g_specialChars.end(); it++) {
if (c2 == it->get<0>()) {
auto htmlEntitie = it->get<1>();
filteredPassphrase += "&";
filteredPassphrase += htmlEntitie;
filteredPassphrase += ";";
i++;
insertedHtmlEntitie = true;
break;
}
}
if (insertedHtmlEntitie) continue;
additionalUtfByteCount = 1;
}
else if ((c & 0x00000800) == 0x00000800) {
additionalUtfByteCount = 2;
}
else if ((c & 0x00010000) == 0x00010000) {
additionalUtfByteCount = 3;
}
for (int j = 0; j <= additionalUtfByteCount; j++) {
filteredPassphrase += passphrase.data()[i + j];
i++;
}
}
else {
// 32 = Space
// 65 = A
// 90 = Z
// 97 = a
// 122 = z
// 59 = ;
// 38 = &
if (c == 32 || c == 59 || c == 38 ||
(c >= 65 && c <= 90) ||
(c >= 97 && c <= 122)) {
filteredPassphrase += c;
}
else if (c == '\n' || c == '\r') {
filteredPassphrase += ' ';
}
}
}
return filteredPassphrase;
}
Poco::SharedPtr<Passphrase> Passphrase::transform(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);*/
// Poco::SharedPtr<Passphrase> transformedPassphrase = new Passphrase()
}
Poco::SharedPtr<Passphrase> Passphrase::create(const MemoryBin* wordIndices, const Mnemonic* wordSource)
{
//Poco::SharedPtr<Passphrase> passphrase = new Passphrase()
const Poco::UInt64* word_indices_p = (const Poco::UInt64*)wordIndices->data();
std::string clearPassphrase;
for (int i = 0; i < PHRASE_WORD_COUNT; i++) {
if (i * sizeof(Poco::UInt64) >= wordIndices->size()) break;
auto word = wordSource->getWord(word_indices_p[i]);
if (word) {
clearPassphrase += word;
clearPassphrase += " ";
}
}
return new Passphrase(clearPassphrase, wordSource);
}
bool Passphrase::createWordIndices()
{
auto er = ErrorManager::getInstance();
auto mm = MemoryManager::getInstance();
const char* functionName = "Passphrase::createWordIndices";
if (!mWordSource) {
er->addError(new Error(functionName, "word source is empty"));
return false;
}
//DHASH key = DRMakeStringHash(passphrase);
size_t pass_phrase_size = mPassphraseString.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 = mPassphraseString.begin(); it != mPassphraseString.end(); it++)
{
if (*it == ' ') {
if (buffer_cursor < 3) {
continue;
}
if (PHRASE_WORD_COUNT > word_cursor && mWordSource->isWordExist(acBuffer)) {
mWordIndices[word_cursor] = mWordSource->getWordIndex(acBuffer);
//word_indices_old[word_cursor] = word_source->getWordIndex(acBuffer);
}
else {
er->addError(new ParamError(functionName, "word didn't exist", acBuffer));
er->sendErrorsAsEmail();
return false;
}
word_cursor++;
memset(acBuffer, 0, STR_BUFFER_SIZE);
buffer_cursor = 0;
}
else {
acBuffer[buffer_cursor++] = *it;
}
}
if (PHRASE_WORD_COUNT > word_cursor && mWordSource->isWordExist(acBuffer)) {
mWordIndices[word_cursor] = mWordSource->getWordIndex(acBuffer);
//word_indices_old[word_cursor] = word_source->getWordIndex(acBuffer);
word_cursor++;
}
//printf("word cursor: %d\n", word_cursor);
/*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 true;
}
const Poco::UInt16* Passphrase::getWordIndices()
{
if (!(mWordIndices[0] | mWordIndices[1] | mWordIndices[2] | mWordIndices[3])) {
if (createWordIndices()) return mWordIndices;
}
return mWordIndices;
}
bool Passphrase::checkIfValid()
{
std::istringstream iss(mPassphraseString);
std::vector<std::string> results(std::istream_iterator<std::string>{iss},
std::istream_iterator<std::string>());
bool existAll = true;
for (auto it = results.begin(); it != results.end(); it++) {
if (*it == "\0" || *it == "" || it->size() < 3) continue;
if (!mWordSource->isWordExist(*it)) {
return false;
}
}
return true;
}
const Mnemonic* Passphrase::detectMnemonic(const std::string& passphrase, const MemoryBin* publicKey /* = nullptr*/)
{
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;
for (auto it = results.begin(); it != results.end(); it++) {
if (*it == "\0" || *it == "" || it->size() < 3) continue;
if (!m.isWordExist(*it)) {
existAll = false;
// leave inner for-loop
break;
}
}
if (existAll) {
if (publicKey) {
}
return &ServerConfig::g_Mnemonic_WordLists[i];
}
}
return nullptr;
}

View File

@ -0,0 +1,37 @@
#ifndef __GRADIDO_LOGIN_SERVER_CRYPTO_PASSPHRASE_H
#define __GRADIDO_LOGIN_SERVER_CRYPTO_PASSPHRASE_H
//#include <string>
#include "mnemonic.h"
#include "../SingletonManager/MemoryManager.h"
class Passphrase
{
public:
Passphrase(const std::string& passphrase, const Mnemonic* wordSource);
static Poco::SharedPtr<Passphrase> create(const MemoryBin* wordIndices, const Mnemonic* wordSource);
static const Mnemonic* detectMnemonic(const std::string& passphrase, const MemoryBin* publicKey = nullptr);
//! \brief transform passphrase into another language/mnemonic source
Poco::SharedPtr<Passphrase> transform(const Mnemonic* targetWordSource);
//! \brief replace utf8 characters with html special character encoding
//!
//! TODO: add more utf8 chars for other languages as they needed
static std::string filter(const std::string& passphrase);
bool checkIfValid();
const Poco::UInt16* getWordIndices();
protected:
bool createWordIndices();
std::string mPassphraseString;
const Mnemonic* mWordSource;
Poco::UInt16 mWordIndices[PHRASE_WORD_COUNT];
};
#endif // __GRADIDO_LOGIN_SERVER_CRYPTO_PASSPHRASE

View File

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

View File

@ -73,8 +73,8 @@ public:
inline Poco::AutoPtr<controller::User> getNewUser() { return mNewUser; }
// ---------------- User functions ----------------------------
// TODO: automatic redirect after some time, median profiled time for register
// TODO: register state: written into db, mails sended, update state only if new state is higher as old state
// create User send e-mail activation link
bool createUser(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password);
// adminRegister without passwort

View File

@ -33,6 +33,7 @@
{
switch(type) {
case ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER: return "de";
case ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER_FIXED_CASES: return "de";
case ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER: return "en";
}
return "unknown";

View File

@ -0,0 +1,85 @@
<%@ page class="RegisterDirectPage" %>
<%@ page form="true" %>
<%@ page compressed="true" %>
<%@ page baseClass="PageRequestMessagedHandler" %>
<%@ header include="PageRequestMessagedHandler.h" %>
<%!
#include "../SingletonManager/SessionManager.h"
#include "Poco/Net/HTTPCookie.h"
%>
<%%
const char* pageName = "Registrieren";
auto sm = SessionManager::getInstance();
bool userReturned = false;
if(!form.empty()) {
if(form.get("register-password2", "") != form.get("register-password", "")) {
addError(new Error("Passwort", "Passw&ouml;rter sind nicht identisch."), false);
} else {
auto session = sm->getSession(request);
if(!session) {
session = sm->getNewSession();
auto user_host = request.clientAddress().host();
session->setClientIp(user_host);
response.addCookie(session->getLoginCookie());
}
userReturned = session->createUser(
form.get("register-first-name", ""),
form.get("register-last-name", ""),
form.get("register-email", ""),
form.get("register-password", "")
);
getErrors(session);
}
} else {
// on enter login page with empty form
// remove old cookies if exist
sm->deleteLoginCookies(request, response);
}
%><%@ include file="header_old.cpsp" %>
<div class="grd_container">
<h1>Einen neuen Account anlegen</h1>
<%= getErrorsHtml() %>
<% if(!form.empty() && userReturned) {%>
<div class="grd_text-max-width">
<div class="grd_text">
Deine Anmeldung wird verarbeitet und es wird dir eine E-Mail zugeschickt.
Wenn sie da ist, befolge ihren Anweisungen.
</div>
</div>
<% } else { %>
<form method="POST">
<fieldset class="grd_container_small">
<legend>Account anlegen</legend>
<p>Bitte gebe deine Daten um einen Account anzulegen</p>
<p class="grd_small">
<label for="register-first-name">Vorname</label>
<input id="register-first-name" type="text" name="register-first-name" value="<%= !form.empty() ? form.get("register-first-name") : "" %>"/>
</p>
<p class="grd_small">
<label for="register-last-name">Nachname</label>
<input id="register-last-name" type="text" name="register-last-name" value="<%= !form.empty() ? form.get("register-last-name") : "" %>"/>
</p>
<p class="grd_small">
<label for="register-email">E-Mail</label>
<input id="register-email" type="email" name="register-email" value="<%= !form.empty() ? form.get("register-email") : "" %>"/>
</p>
<p class="grd_small">
<label for="register-password">Passwort</label>
<input id="register-password" type="password" name="register-password"/>
</p>
<p class="grd_small">
<label for="register-password">Passwort Best&auml;tigung</label>
<input id="register-password2" type="password" name="register-password2"/>
</p>
</fieldset>
<input class="grd-form-bn grd-form-bn-succeed" type="submit" name="submit" value="Anmelden">
</form>
<% } %>
</div>
<%@ include file="footer.cpsp" %>