Transaction Roundtrip success

This commit is contained in:
Dario 2019-11-03 19:48:26 +01:00
parent cd12c0fdbf
commit 0bb6332a13
11 changed files with 201 additions and 23 deletions

View File

@ -39,6 +39,7 @@ namespace ServerConfig {
int g_SessionTimeout = SESSION_TIMEOUT_DEFAULT;
std::string g_serverPath;
std::string g_php_serverPath;
std::string g_php_serverHost;
Poco::Mutex g_TimeMutex;
bool loadMnemonicWordLists()
@ -93,6 +94,7 @@ namespace ServerConfig {
g_SessionTimeout = cfg.getInt("session.timeout", SESSION_TIMEOUT_DEFAULT);
g_serverPath = cfg.getString("loginServer.path", "");
g_php_serverPath = cfg.getString("phpServer.url", "");
g_php_serverHost = cfg.getString("phpServer.host", "");
return true;
}

View File

@ -38,6 +38,7 @@ namespace ServerConfig {
extern int g_SessionTimeout;
extern std::string g_serverPath;
extern std::string g_php_serverPath;
extern std::string g_php_serverHost;
extern Poco::Mutex g_TimeMutex;

View File

@ -11,6 +11,7 @@
#include "../lib/ErrorList.h"
#include "../proto/gradido/BasicTypes.pb.h"
#include "../SingletonManager/MemoryManager.h"
class TransactionBase : public ErrorList
{

View File

@ -47,4 +47,5 @@ int TransactionCreation::prepare()
return 0;
}
}

View File

@ -11,4 +11,4 @@ int TransactionTransfer::prepare()
{
return 0;
}
}

View File

@ -17,7 +17,7 @@ class TransactionTransfer : public TransactionBase
public:
TransactionTransfer(const std::string& memo, const model::messages::gradido::Transfer& protoTransfer);
int prepare();
int prepare();
protected:
const model::messages::gradido::Transfer& mProtoTransfer;

View File

@ -49,6 +49,7 @@ int UserGenerateKeys::run()
mKeys.generateFromPassphrase(mPassphrase.data(), &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]);
mUser->setPublicKeyHex(mKeys.getPubkeyHex());
mUser->setPublicKey(mKeys.getPublicKey());
if (mUser->hasCryptoKey()) {
mUser->setPrivKey(mKeys.getPrivateKey());
}
@ -176,7 +177,7 @@ User::User(const char* email, const char* first_name, const char* last_name)
: mState(USER_EMPTY), mDBId(0), mEmail(email), mFirstName(first_name), mLastName(last_name), mPasswordHashed(0), mPrivateKey(nullptr), mEmailChecked(false), mCryptoKey(nullptr),
mReferenceCount(1)
{
memset(mPublicKey, 0, crypto_sign_PUBLICKEYBYTES);
}
// load from db
User::User(const char* email)
@ -187,6 +188,8 @@ User::User(const char* email)
auto cm = ConnectionManager::getInstance();
auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
memset(mPublicKey, 0, crypto_sign_PUBLICKEYBYTES);
Poco::Nullable<Poco::Data::BLOB> pubkey;
Poco::Nullable<Poco::Data::BLOB> privkey;
@ -207,6 +210,12 @@ User::User(const char* email)
if (!pubkey.isNull()) {
auto pubkey_value = pubkey.value();
if (pubkey_value.size() == crypto_sign_PUBLICKEYBYTES) {
memcpy(mPublicKey, pubkey_value.content().data(), crypto_sign_PUBLICKEYBYTES);
}
else {
addError(new Error("User", "pubkey from db has other size as expected"));
}
size_t hexSize = pubkey_value.size() * 2 + 1;
char* hexString = (char*)malloc(hexSize);
memset(hexString, 0, hexSize);
@ -234,6 +243,8 @@ User::User(int user_id)
auto cm = ConnectionManager::getInstance();
auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
memset(mPublicKey, 0, crypto_sign_PUBLICKEYBYTES);
Poco::Nullable<Poco::Data::BLOB> pubkey;
Poco::Nullable<Poco::Data::BLOB> privkey;
@ -254,6 +265,12 @@ User::User(int user_id)
if (!pubkey.isNull()) {
auto pubkey_value = pubkey.value();
if (pubkey_value.size() == crypto_sign_PUBLICKEYBYTES) {
memcpy(mPublicKey, pubkey_value.content().data(), crypto_sign_PUBLICKEYBYTES);
}
else {
addError(new Error("User", "pubkey from db has other size as expected"));
}
size_t hexSize = pubkey_value.size() * 2 + 1;
char* hexString = (char*)malloc(hexSize);
memset(hexString, 0, hexSize);
@ -283,6 +300,8 @@ User::User(const unsigned char* pubkey_array)
auto cm = ConnectionManager::getInstance();
auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
memcpy(mPublicKey, pubkey_array, crypto_sign_PUBLICKEYBYTES);
Poco::Data::BLOB pubkey(pubkey_array, 32);
Poco::Nullable<Poco::Data::BLOB> privkey;
@ -769,15 +788,19 @@ MemoryBin* User::sign(const unsigned char* message, size_t messageSize)
//auto signBinBuffer = (unsigned char*)malloc(crypto_sign_BYTES);
auto signBinBuffer = mm->getFreeMemory(crypto_sign_BYTES);
auto privKey = getPrivKey();
size_t actualSignLength = 0;
crypto_sign_detached(*signBinBuffer, NULL, message, messageSize, *privKey);
if (crypto_sign_detached(*signBinBuffer, &actualSignLength, message, messageSize, *privKey)) {
addError(new Error("User::sign", "sign failed"));
mm->releaseMemory(privKey);
mm->releaseMemory(signBinBuffer);
return nullptr;
}
if (crypto_sign_verify_detached(*signBinBuffer, message, messageSize, *privKey) != 0) {
if (crypto_sign_verify_detached(*signBinBuffer, message, messageSize, mPublicKey) != 0) {
// Incorrect signature!
//printf("c[KeyBuffer::%s] sign verify failed\n", __FUNCTION__);
auto em = ErrorManager::getInstance();
em->addError(new Error("User::sign", "sign verify failed"));
em->sendErrorsAsEmail();
addError(new Error("User::sign", "sign verify failed"));
mm->releaseMemory(privKey);
mm->releaseMemory(signBinBuffer);
return nullptr;

View File

@ -80,7 +80,9 @@ public:
inline const char* getLastName() const { return mLastName.data(); }
inline int getDBId() const { return mDBId; }
inline std::string getPublicKeyHex() { lock(); std::string pubkeyHex = mPublicHex; unlock(); return pubkeyHex; }
inline const unsigned char* getPublicKey() { return mPublicKey; }
inline void setPublicKeyHex(const std::string& publicKeyHex) { lock(); mPublicHex = publicKeyHex; unlock(); }
inline void setPublicKey(const unsigned char* key) { lock(); memcpy(mPublicKey, key, crypto_sign_PUBLICKEYBYTES); unlock();}
UserStates getUserState();
@ -134,6 +136,7 @@ private:
passwordHashed mPasswordHashed;
std::string mPublicHex;
unsigned char mPublicKey[crypto_sign_PUBLICKEYBYTES];
MemoryBin* mPrivateKey;
// TODO: insert created if necessary

View File

@ -87,6 +87,25 @@ std::string ProcessingTransaction::getMemo()
return "<uninitalized>";
}
std::string ProcessingTransaction::getBodyBytes()
{
lock();
if (mTransactionBody.IsInitialized()) {
auto size = mTransactionBody.ByteSize();
//auto bodyBytesSize = MemoryManager::getInstance()->getFreeMemory(mProtoCreation.ByteSizeLong());
std::string resultString(size, 0);
if (!mTransactionBody.SerializeToString(&resultString)) {
addError(new Error("TransactionCreation::getBodyBytes", "error serializing string"));
unlock();
return "";
}
unlock();
return resultString;
}
unlock();
return "<uninitalized>";
}
TransactionCreation* ProcessingTransaction::getCreationTransaction()
{
return dynamic_cast<TransactionCreation*>(mTransactionSpecific);

View File

@ -50,6 +50,7 @@ public:
static HASH calculateHash(const std::string& proto_message_base64);
inline HASH getHash() { mHashMutex.lock(); HASH hs = mHash; mHashMutex.unlock(); return hs; }
std::string ProcessingTransaction::getBodyBytes();
protected:
TransactionType mType;

View File

@ -3,6 +3,18 @@
#include "../SingletonManager/ErrorManager.h"
#include "../SingletonManager/MemoryManager.h"
#include "../proto/gradido/Transaction.pb.h"
#include "sodium.h"
#include "../ServerConfig.h"
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
#include "Poco/StreamCopier.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
SigningTransaction::SigningTransaction(Poco::AutoPtr<ProcessingTransaction> processingeTransaction, Poco::AutoPtr<User> user)
: mProcessingeTransaction(processingeTransaction), mUser(user)
{
@ -15,33 +27,148 @@ SigningTransaction::~SigningTransaction()
}
int SigningTransaction::run() {
auto em = ErrorManager::getInstance();
auto mm = MemoryManager::getInstance();
Error* transactionError = new Error("SigningTransaction start", mProcessingeTransaction->mProtoMessageBase64.data());
Error* transactionError = new Error("SigningTransaction", mProcessingeTransaction->mProtoMessageBase64.data());
addError(transactionError);
//= new Error("SigningTransaction start", mProcessingeTransaction->g)
if (mUser.isNull() || !mUser->hasCryptoKey()) {
em->addError(transactionError);
em->addError(new Error("SigningTransaction", "user hasn't crypto key or is null"));
em->sendErrorsAsEmail();
addError(new Error("SigningTransaction", "user hasn't crypto key or is null"));
sendErrorsAsEmail();
return -1;
}
//auto privKey = mUser->getPrivKey();
if (!mUser->hasPrivKey()) {
em->addError(transactionError);
em->getErrors(mUser);
em->addError(new Error("SigningTransaction", "couldn't get user priv key"));
em->sendErrorsAsEmail();
getErrors(mUser);
addError(new Error("SigningTransaction", "couldn't get user priv key"));
sendErrorsAsEmail();
return -2;
}
// get body bytes
model::messages::gradido::Transaction transaction;
auto bodyBytes = transaction.mutable_bodybytes();
*bodyBytes = mProcessingeTransaction->getBodyBytes();
if (*bodyBytes == "") {
getErrors(mProcessingeTransaction);
sendErrorsAsEmail();
return -3;
}
// sign
auto sign = mUser->sign((const unsigned char*)bodyBytes->data(), bodyBytes->size());
if (!sign) {
getErrors(mUser);
sendErrorsAsEmail();
mm->releaseMemory(sign);
return -4;
}
auto pubkeyHex = mUser->getPublicKeyHex();
// pubkey for signature
/*auto pubkeyBin = mm->getFreeMemory(ed25519_pubkey_SIZE);
size_t realBin = 0;
if (sodium_hex2bin(*pubkeyBin, *pubkeyBin, pubkeyHex.data(), pubkeyHex.size(), nullptr, &realBin, nullptr)) {
addError(new Error("SigningTransaction", "error in sodium_hex2bin"));
sendErrorsAsEmail();
mm->releaseMemory(pubkeyBin);
mm->releaseMemory(sign);
return -5;
}
*/
// add to message
auto sigMap = transaction.mutable_sigmap();
auto sigPair = sigMap->add_sigpair();
//auto sign = mUser->sign(mProcessingeTransaction->)
delete transactionError;
//delete privKey;
//mm->releaseMemory(privKey);
auto pubkeyBytes = sigPair->mutable_pubkey();
auto pubkeyBin = mUser->getPublicKey();
*pubkeyBytes = std::string((const char*)pubkeyBin, crypto_sign_PUBLICKEYBYTES);
auto sigBytes = sigPair->mutable_ed25519();
*sigBytes = std::string((char*)*sign, sign->size());
mm->releaseMemory(sign);
// finalize
std::string finalTransactionBin = transaction.SerializeAsString();
if (finalTransactionBin == "") {
addError(new Error("SigningTransaction", "error serializing final transaction"));
sendErrorsAsEmail();
return -6;
}
// finale to base64
auto finalBase64Size = sodium_base64_encoded_len(finalTransactionBin.size(), sodium_base64_VARIANT_ORIGINAL);
auto finalBase64Bin = mm->getFreeMemory(finalBase64Size);
if (!sodium_bin2base64(*finalBase64Bin, finalBase64Size, (const unsigned char*)finalTransactionBin.data(), finalTransactionBin.size(), sodium_base64_VARIANT_ORIGINAL)) {
addError(new Error("SigningTransaction", "error convert final transaction to base64"));
sendErrorsAsEmail();
mm->releaseMemory(finalBase64Bin);
return -7;
}
// create json request
Poco::JSON::Object requestJson;
requestJson.set("method", "putTransaction");
requestJson.set("transaction", std::string((char*)*finalBase64Bin, finalBase64Size));
printf("base64 transaction: %s\n", (char*)*finalBase64Bin);
mm->releaseMemory(finalBase64Bin);
//std::string request = requestJson.stringify();
// send post request via https
// 443 = HTTPS Default
// TODO: adding port into ServerConfig
try {
Poco::Net::HTTPSClientSession httpsClientSession(ServerConfig::g_php_serverHost, 443);
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, "/TransactionJsonRequestHandler");
request.setChunkedTransferEncoding(true);
std::ostream& requestStream = httpsClientSession.sendRequest(request);
requestJson.stringify(requestStream);
Poco::Net::HTTPResponse response;
std::istream& request_stream = httpsClientSession.receiveResponse(response);
// debugging answer
std::stringstream responseStringStream;
for (std::string line; std::getline(request_stream, line); ) {
responseStringStream << line << std::endl;
}
//printf("server response: %s\n", responseStringStream.str().data());
FILE* f = fopen("response.html", "wt");
std::string responseString = responseStringStream.str();
fwrite(responseString.data(), 1, responseString.size(), f);
fclose(f);
// extract parameter from request
Poco::JSON::Parser jsonParser;
Poco::Dynamic::Var parsedJson;
try {
parsedJson = jsonParser.parse(request_stream);
}
catch (Poco::Exception& ex) {
//printf("[JsonRequestHandler::handleRequest] Exception: %s\n", ex.displayText().data());
addError(new ParamError("SigningTransaction", "error parsing request answer", ex.displayText().data()));
sendErrorsAsEmail();
return -9;
}
if (parsedJson.isStruct()) {
}
int zahl = 1;
}
catch (Poco::Exception& e) {
addError(new ParamError("SigningTransaction", "connect error to php server", e.displayText().data()));
sendErrorsAsEmail();
return -8;
}
return 0;
}