change encryption state of crypto_keys

This commit is contained in:
Dario 2020-09-11 12:29:06 +02:00 committed by Ulf Gebhardt
parent 155f394500
commit 5862a61d59
No known key found for this signature in database
GPG Key ID: 81308EFE29ABFEBD
17 changed files with 377 additions and 89 deletions

View File

@ -1,6 +1,6 @@
CREATE TABLE `crypto_keys` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`private_key` binary(80) NOT NULL,
`private_key` varbinary(80) NOT NULL,
`public_key` binary(32) NOT NULL,
`crypto_key_type_id` int NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),

View File

@ -184,6 +184,7 @@ MemoryBin* KeyPairHedera::getCryptedPrivKey(const Poco::AutoPtr<SecretKeyCryptog
}
MemoryBin* KeyPairHedera::getPrivateKeyCopy() const
{
if (!mPrivateKey) return nullptr;

View File

@ -15,6 +15,7 @@
#include "sodium.h"
#include "SecretKeyCryptography.h"
#include "iroha-ed25519/include/ed25519/ed25519.h"
#include "../lib/DataTypeConverter.h"
class KeyPairHedera : public IKeyPair
{
@ -38,6 +39,7 @@ public:
inline const unsigned char* getPublicKey() const { return mPublicKey; }
MemoryBin* getPublicKeyCopy() const;
inline std::string getPublicKeyHex() const { return DataTypeConverter::binToHex(mPublicKey, getPublicKeySize()); }
const static size_t getPublicKeySize() {return ed25519_pubkey_SIZE;}
inline bool isTheSame(const KeyPairHedera& b) const {
@ -68,6 +70,7 @@ public:
//! \brief
MemoryBin* getCryptedPrivKey(const Poco::AutoPtr<SecretKeyCryptography> password) const;
MemoryBin* getPrivateKeyCopy() const;
inline std::string getPrivateKeyHex(const Poco::AutoPtr<SecretKeyCryptography> password) const { if (!mPrivateKey) return "0x0"; return DataTypeConverter::binToHex(mPrivateKey); }
protected:

View File

@ -51,40 +51,58 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
Poco::URI uri(request.getURI());
auto uri_query = uri.getQueryParameters();
std::string action = "";
std::string account_id_from_query;
Poco::AutoPtr<controller::HederaAccount> query_hedera_account;
// parsing get query params
if(uri_query.size() >= 2) {
if(uri_query[0].first == "action") {
action = uri_query[0].second;
}
if(uri_query[1].first == "account_id") {
std::string account_id_from_query;
int account_id = 0;
account_id_from_query = uri_query[1].second;
}
}
if(action == "updateBalance") {
int account_id = 0;
if(DataTypeConverter::strToInt(account_id_from_query, account_id) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting account_id_from_query to int"));
} else {
auto hedera_account = controller::HederaAccount::load("id", account_id);
if(!hedera_account.size() || hedera_account[0].isNull()) {
addError(new Error("Action Update Balance", "hedera id not found"));
if(DataTypeConverter::strToInt(account_id_from_query, account_id) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting account_id_from_query to int"));
} else {
hedera_time.reset();
hedera_account[0]->hederaAccountGetBalance(user, this);
addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string()));
auto hedera_accounts = controller::HederaAccount::load("id", account_id);
if(!hedera_accounts.size() || hedera_accounts[0].isNull()) {
addError(new Error("Action", "hedera account not found"));
} else {
query_hedera_account = hedera_accounts[0];
}
}
}
}
// add
else if(!form.empty()) {
// actions
if(!query_hedera_account.isNull())
{
if(action == "updateBalance")
{
hedera_time.reset();
query_hedera_account->hederaAccountGetBalance(user);
addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string()));
}
else if(action == "changeEncryption")
{
if(query_hedera_account->changeEncryption(user)) {
addNotification(new Success("Hedera Account", "success in changing encryption"));
}
}
}
else if(!form.empty()) // add
{
// collect
auto shardNumString = form.get("account-shard-num", "0");
auto realmNumString = form.get("account-realm-num", "0");
auto numString = form.get("account-num", "0");
auto privateKeyString = form.get("account-private-key", "");
auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false");
auto publicKeyString = form.get("account-public-key", "");
auto networkTypeString = form.get("account-network-type", "0");
//printf("private key encrypted: %s\n", privateKeyEncryptedString.data());
int shardNum = 0;
int realmNum = 0;
int num = 0;
@ -144,7 +162,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE);
if(crypto_key.isNull()) {
crypto_key = controller::CryptoKey::create(&key_pair, user);
crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true");
if(!crypto_key->getModel()->insertIntoDB(true)) {
addError(new Error("DB Error", "Error saving crypto key in DB"));
}
@ -152,15 +170,26 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
printf("crypto key found in db\n");
}
if(0 == errorCount()) {
auto hedera_account = controller::HederaAccount::create(
user->getModel()->getID(),
hedera_id->getModel()->getID(),
crypto_key->getModel()->getID(),
0,
(model::table::HederaNetworkType)networkType
);
if(!hedera_account->getModel()->insertIntoDB(false)) {
addError(new Error("DB Error", "Error saving hedera account into DB"));
if(hedera_id->isExistInDB()) {
auto hedera_account = controller::HederaAccount::load(hedera_id);
if(hedera_account.isNull()) {
addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist"));
} else {
addError(new Error("Hedera Account", "Account already exist (same account id"));
}
} else {
auto hedera_account = controller::HederaAccount::create(
user->getModel()->getID(),
hedera_id->getModel()->getID(),
crypto_key->getModel()->getID(),
0,
(model::table::HederaNetworkType)networkType
);
if(!hedera_account->getModel()->insertIntoDB(false)) {
addError(new Error("DB Error", "Error saving hedera account into DB"));
}
}
}
@ -169,7 +198,9 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
}
}
if(!query_hedera_account.isNull()) {
getErrors(query_hedera_account);
}
// list accounts
auto hedera_accounts = controller::HederaAccount::load("user_id", user->getModel()->getID());
@ -231,7 +262,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
responseStream << "\t\t<div class=\"content\">";
// end include header_large.cpsp
responseStream << "\n";
#line 156 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 187 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( getErrorsHtml() );
responseStream << "\n";
responseStream << "<div class=\"center-form-container\">\n";
@ -244,41 +275,63 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
responseStream << "\t\t\t\t<div class=\"cell header-cell c2\">Hedera Id</div>\t\t\t\n";
responseStream << "\t\t\t\t<div class=\"cell header-cell c3\">Balance</div>\n";
responseStream << "\t\t\t\t<div class=\"cell header-cell c2\">Server Type</div>\n";
responseStream << "\t\t\t\t<div class=\"cell header-cell c3\">Verschlüsselt?</div>\n";
responseStream << "\t\t\t\t<div class=\"cell header-cell c3\">Last Updated</div>\n";
responseStream << "\t\t\t\t<div class=\"cell header-cell c5\">Aktionen</div>\n";
responseStream << "\t\t\t</div>\n";
responseStream << "\t\t\t";
#line 171 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 203 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
for(auto it = hedera_accounts.begin(); it != hedera_accounts.end(); it++) {
auto hedera_account_model = (*it)->getModel();
auto updateUrl = ServerConfig::g_serverPath + "/hedera_account?action=updateBalance&account_id=" + std::to_string(hedera_account_model->getID());
std::string changeEncryption("");
if(hedera_account_model->getUserId() == user->getModel()->getID()) {
changeEncryption = ServerConfig::g_serverPath + "/hedera_account?action=changeEncryption&account_id=" + std::to_string(hedera_account_model->getID());
}
//printf("change encryption: %s\n", changeEncryption.data());
responseStream << "\n";
responseStream << "\t\t\t\t<div class=\"row\">\n";
responseStream << "\t\t\t\t\t<div class=\"cell c2\">";
#line 176 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 213 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( (*it)->getHederaId()->getModel()->toString() );
responseStream << "</div>\n";
responseStream << "\t\t\t\t\t<div class=\"cell c3\">";
#line 177 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 214 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( hedera_account_model->getBalanceDouble() );
responseStream << " hbar</div>\n";
responseStream << "\t\t\t\t\t<div class=\"cell c2\">";
#line 178 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 215 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) );
responseStream << "</div>\n";
responseStream << "\t\t\t\t\t<div class=\"cell c3\">";
#line 179 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 216 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( (*it)->getCryptoKey()->getModel()->isEncrypted() ? "Ja": "Nein" );
responseStream << "</div>\n";
responseStream << "\t\t\t\t\t<div class=\"cell c3\">";
#line 217 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( hedera_account_model->getUpdatedString() );
responseStream << "</div>\n";
responseStream << "\t\t\t\t\t<button class=\"form-button\" title=\"Anfrage an Hedera, kostet etwas\" onclick=\"window.location.href='";
#line 180 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << "\t\t\t\t\t<button class=\"form-button\" title=\"Anfrage an Hedera, aktuell kostenlos\" onclick=\"window.location.href='";
#line 218 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( updateUrl );
responseStream << "'\" >\n";
responseStream << "\t\t\t\t\t\tUpdate Balance\n";
responseStream << "\t\t\t\t\t</button>\n";
responseStream << "\t\t\t\t\t";
#line 221 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
if(changeEncryption != "") { responseStream << "\n";
responseStream << "\t\t\t\t\t\t<button class=\"form-button\" title=\"Ändere den Verschlüsselungsstatus des Private Keys in der Datenbank\" onclick=\"window.location.href='";
#line 222 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( changeEncryption );
responseStream << "'\">\n";
responseStream << "\t\t\t\t\t\t\tChange Encryption\n";
responseStream << "\t\t\t\t\t\t</button>\n";
responseStream << "\t\t\t\t\t";
#line 225 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
} responseStream << "\n";
responseStream << "\t\t\t\t</div>\n";
responseStream << "\t\t\t";
#line 184 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 227 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
} responseStream << "\n";
responseStream << "\t\t</div>\n";
responseStream << "\t</div>\n";
@ -287,7 +340,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
responseStream << "\t</div>\n";
responseStream << "\t<div class=\"center-form-form\">\n";
responseStream << "\t\t<form method=\"POST\" action=\"";
#line 191 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 234 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( ServerConfig::g_serverPath );
responseStream << "/hedera_account\">\n";
responseStream << "\t\t\t<label class=\"form-label\">Hedera Account ID</label>\n";
@ -296,26 +349,28 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
responseStream << "\t\t\t<input class=\"form-control\" id=\"account-num\" placeholder=\"num\" type=\"number\" name=\"account-num\"/>\n";
responseStream << "\t\t\t<label class=\"form-label\" for=\"account-private-key\">Private Key</label>\n";
responseStream << "\t\t\t<input class=\"form-control\" id=\"account-private-key\" type=\"text\" name=\"account-private-key\"/>\n";
responseStream << "\t\t\t<label class=\"form-label\" for=\"account-private-key-encrypted\" title=\"Wenn er verschlüsselt ist, kannst nur du Hedera Transaktionen damit bezahlen, wenn er nicht verschlüsselt ist kann er für alle Hedera Transaktionen automatisch verwendet werden. Ich empfehle dafür ein separates Konto mit wenigen Hashbars anzulegen.\">Private Key verschlüsseln?</label>\n";
responseStream << "\t\t\t<input class=\"form-control\" id=\"account-private-key-encrypted\" type=\"checkbox\" name=\"account-private-key-encrypted\" value=\"true\"/>\n";
responseStream << "\t\t\t<label class=\"form-label\" for=\"account-public-key\">Public Key</label>\n";
responseStream << "\t\t\t<input class=\"form-control\" id=\"account-public-key\" type=\"text\" name=\"account-public-key\"/>\n";
responseStream << "\t\t\t<label class=\"form-label\" for=\"account-network-type\">Network Type</label>\n";
responseStream << "\t\t\t<select class=\"form-control\" name=\"account-network-type\" id=\"account-network-type\">\n";
responseStream << "\t\t\t";
#line 202 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 247 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
for(int i = 0; i < model::table::HEDERA_NET_COUNT; i++) { responseStream << "\n";
responseStream << "\t\t\t\t<option value=\"";
#line 203 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 248 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( i );
responseStream << "\">";
#line 203 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 248 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( model::table::HederaAccount::hederaNetworkTypeToString((model::table::HederaNetworkType)i) );
responseStream << "</option>\n";
responseStream << "\t\t\t";
#line 204 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 249 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
} responseStream << "\n";
responseStream << "\t\t\t</select>\n";
responseStream << "\t\t\t<input class=\"center-form-submit form-button\" type=\"submit\" name=\"submit\" value=\"";
#line 206 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 251 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( gettext("Add Account") );
responseStream << "\">\n";
responseStream << "\t\t</form>\n";

View File

@ -113,8 +113,38 @@ namespace controller {
return nullptr;
}
return std::make_unique<KeyPairHedera>(model->getPrivateKey(), model->getPublicKey(), model->getPublicKeySize());
}
bool CryptoKey::changeEncryption(Poco::AutoPtr<controller::User> user)
{
auto key_pair = getKeyPair(user);
if (!key_pair || !key_pair->hasPrivateKey()) {
addError(new Error("Crypto Key", "key pair or private key was null"));
return false;
}
auto model = getModel();
auto mm = MemoryManager::getInstance();
// update key type
model->changeKeyTypeToggleEncrypted();
MemoryBin* private_key = nullptr;
if (model->isEncrypted()) {
private_key = key_pair->getCryptedPrivKey(user->getPassword());
}
else {
private_key = key_pair->getPrivateKeyCopy();
}
if (!private_key) {
addError(new Error("Crypto Key", " private_key not get"));
return false;
}
model->setPrivateKey(private_key);
// save changes into db
model->updatePrivkeyAndKeyType();
mm->releaseMemory(private_key);
return true;
}
}

View File

@ -9,9 +9,15 @@
#include "TableControllerBase.h"
#include "User.h"
namespace controller {
class CryptoKey : public TableControllerBase
class HederaAccount;
class CryptoKey : public TableControllerBase, public NotificationList
{
friend HederaAccount;
public:
~CryptoKey();
@ -31,8 +37,11 @@ namespace controller {
std::unique_ptr<KeyPairHedera> getKeyPair(Poco::AutoPtr<controller::User> user) const;
std::unique_ptr<KeyPairHedera> getKeyPair() const;
protected:
bool changeEncryption(Poco::AutoPtr<controller::User> user);
CryptoKey(model::table::CryptoKey* dbModel);
};

View File

@ -40,6 +40,20 @@ namespace controller {
return resultVector;
}
Poco::AutoPtr<HederaAccount> HederaAccount::load(Poco::AutoPtr<controller::HederaId> hederaId)
{
if (!hederaId->isExistInDB()) return nullptr;
auto db = new model::table::HederaAccount();
auto result_count = db->loadFromDB("account_hedera_id", hederaId->getModel()->getID());
if (1 == result_count) {
return new HederaAccount(db);
}
// maybe change later to using error manager and send email
printf("[HederaAccount::load] result_count not expected: %d\n", result_count);
return nullptr;
}
std::vector<Poco::AutoPtr<HederaAccount>> HederaAccount::listAll()
{
auto db = new model::table::HederaAccount();
@ -73,7 +87,13 @@ namespace controller {
return resultVector;
}
bool HederaAccount::hederaAccountGetBalance(Poco::AutoPtr<controller::User> user, NotificationList* errorReceiver/* = nullptr*/)
Poco::AutoPtr<controller::CryptoKey> HederaAccount::getCryptoKey() const
{
auto model = getModel();
return controller::CryptoKey::load(model->getCryptoKeyId());
}
bool HederaAccount::hederaAccountGetBalance(Poco::AutoPtr<controller::User> user)
{
static const char* functionName = "HederaAccount::updateBalanceFromHedera";
@ -86,13 +106,13 @@ namespace controller {
auto hedera_node = NodeServer::pick(account_model->networkTypeToNodeServerType(account_model->getNetworkType()));
auto crypto_key = controller::CryptoKey::load(account_model->getCryptoKeyId());
if (crypto_key.isNull()) {
if (errorReceiver) { errorReceiver->addError(new Error("Keys", "could not found crypto key for account"));}
else { printf("[%s] error, crypto key with id: %d not found\n", functionName, account_model->getCryptoKeyId()); }
addError(new Error("Keys", "could not found crypto key for account"));
printf("[%s] error, crypto key with id: %d not found\n", functionName, account_model->getCryptoKeyId());
return false;
}
auto hedera_key_pair = crypto_key->getKeyPair(user);
if (!hedera_key_pair) {
if (errorReceiver) { errorReceiver->addError(new Error("Keys", "error decrypting private key"));}
addError(new Error("Keys", "error decrypting private key"));
printf("[%s] error decrypting private key with id: %d, with user: %d\n", functionName, account_model->getCryptoKeyId(), user->getModel()->getID());
return false;
}
@ -111,13 +131,8 @@ namespace controller {
account_model->updateIntoDB("balance", response.getAccountBalance());
}
else {
if (errorReceiver) {
errorReceiver->addError(new Error("Hedera", "Hedera request failed"));
errorReceiver->addError(new ParamError("Hedera", "Hedera Response Code", proto::ResponseCodeEnum_Name(response.getResponseCode())));
}
else {
printf("[%s] hedera response code: %s\n", functionName, proto::ResponseCodeEnum_Name(response.getResponseCode()).data());
}
addError(new Error("Hedera", "Hedera request failed"));
addError(new ParamError("Hedera", "Hedera Response Code", proto::ResponseCodeEnum_Name(response.getResponseCode())));
}
//request.requestViaPHPRelay(query);
}
@ -125,13 +140,32 @@ namespace controller {
printf("[HederaAccount::updateBalanceFromHedera] exception calling hedera request: %s\n", ex.displayText().data());
}
if (errorReceiver) {
errorReceiver->getErrors(&request);
}
getErrors(&request);
return false;
}
bool HederaAccount::changeEncryption(Poco::AutoPtr<controller::User> user)
{
assert(!user.isNull() && user->getModel());
auto model = getModel();
assert(!model.isNull());
if (user->getModel()->getID() != model->getUserId()) {
addError(new Error("Hedera Account", "wrong user"));
return false;
}
auto crypto_key = controller::CryptoKey::load(model->getCryptoKeyId());
if (crypto_key.isNull()) {
addError(new Error("Hedera Account", "couldn't find crypto key"));
return false;
}
bool result = crypto_key->changeEncryption(user);
getErrors(crypto_key);
return result;
}
std::string HederaAccount::toShortSelectOptionName()
{

View File

@ -8,9 +8,10 @@
#include "Poco/SharedPtr.h"
#include "TableControllerBase.h"
#include "CryptoKey.h"
namespace controller {
class HederaAccount : public TableControllerBase
class HederaAccount : public TableControllerBase, public NotificationList
{
public:
~HederaAccount();
@ -18,6 +19,7 @@ namespace controller {
static Poco::AutoPtr<HederaAccount> create(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance = 0, model::table::HederaNetworkType type = model::table::HEDERA_MAINNET);
static std::vector<Poco::AutoPtr<HederaAccount>> load(const std::string& fieldName, int fieldValue);
static Poco::AutoPtr<HederaAccount> load(Poco::AutoPtr<controller::HederaId> hederaId);
static std::vector<Poco::AutoPtr<HederaAccount>> listAll();
inline bool deleteFromDB() { return mDBModel->deleteFromDB(); }
@ -25,11 +27,15 @@ namespace controller {
std::string HederaAccount::toShortSelectOptionName();
inline Poco::AutoPtr<model::table::HederaAccount> getModel() { return _getModel<model::table::HederaAccount>(); }
inline const model::table::HederaAccount* getModel() const { return _getModel<model::table::HederaAccount>(); }
inline void setHederaId(Poco::AutoPtr<controller::HederaId> hederaId) { mHederaID = hederaId; }
inline Poco::AutoPtr<controller::HederaId> getHederaId() { return mHederaID; }
bool hederaAccountGetBalance(Poco::AutoPtr<controller::User> user, NotificationList* errorReceiver = nullptr);
Poco::AutoPtr<controller::CryptoKey> getCryptoKey() const;
bool hederaAccountGetBalance(Poco::AutoPtr<controller::User> user);
bool changeEncryption(Poco::AutoPtr<controller::User> user);
protected:
HederaAccount(model::table::HederaAccount* dbModel);

View File

@ -37,4 +37,14 @@ namespace controller {
protoAccountId->set_realmnum(model->getRealmNum());
protoAccountId->set_accountnum(model->getNum());
}
bool HederaId::isExistInDB()
{
auto model = getModel();
if (model->getID() > 0) return true;
//std::vector<Tuple> loadFromDB(const std::vector<std::string>& fieldNames, const std::vector<WhereFieldType>& fieldValues, MysqlConditionType conditionType = MYSQL_CONDITION_AND, int expectedResults = 0);
model->isExistInDB();
return model->getID() != 0;
}
}

View File

@ -20,6 +20,8 @@ namespace controller {
static Poco::AutoPtr<HederaId> load(int id);
bool isExistInDB();
inline bool deleteFromDB() { return mDBModel->deleteFromDB(); }
inline Poco::AutoPtr<model::table::HederaId> getModel() { return _getModel<model::table::HederaId>(); }

View File

@ -1,5 +1,5 @@
#include "CryptoKey.h"
#include "../../lib/DataTypeConverter.h"
using namespace Poco::Data::Keywords;
namespace model {
@ -51,6 +51,8 @@ namespace model {
return "<unknown type>";
}
bool CryptoKey::hasPrivateKeyEncrypted() const
{
const KeyType type = (KeyType)(mKeyType);
@ -70,6 +72,39 @@ namespace model {
return false;
}
void CryptoKey::setPrivateKey(const MemoryBin* privateKey)
{
if (!privateKey) {
mPrivateKey = Poco::Nullable<Poco::Data::BLOB>();
}
else {
mPrivateKey = Poco::Nullable<Poco::Data::BLOB>(Poco::Data::BLOB(*privateKey, privateKey->size()));
}
}
bool CryptoKey::changeKeyTypeToggleEncrypted()
{
const KeyType type = (KeyType)(mKeyType);
if (type == KEY_TYPE_ED25519_SODIUM_ENCRYPTED) {
mKeyType = KEY_TYPE_ED25519_SODIUM_CLEAR;
return true;
}
if (type == KEY_TYPE_ED25519_HEDERA_ENCRYPTED) {
mKeyType = KEY_TYPE_ED25519_HEDERA_CLEAR;
return true;
}
if (type == KEY_TYPE_ED25519_SODIUM_CLEAR) {
mKeyType = KEY_TYPE_ED25519_SODIUM_ENCRYPTED;
return true;
}
if (type == KEY_TYPE_ED25519_HEDERA_CLEAR) {
mKeyType = KEY_TYPE_ED25519_HEDERA_ENCRYPTED;
return true;
}
return false;
}
Poco::Data::Statement CryptoKey::_loadFromDB(Poco::Data::Session session, const std::string& fieldName)
{
Poco::Data::Statement select(session);
@ -103,5 +138,33 @@ namespace model {
unlock();
return insert;
}
size_t CryptoKey::updatePrivkeyAndKeyType()
{
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
if (mPrivateKey.isNull() || !mID) {
return 0;
}
auto cm = ConnectionManager::getInstance();
auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
Poco::Data::Statement update(session);
update << "UPDATE " << getTableName() << " SET private_key = ?, crypto_key_type_id = ? where id = ?;",
use(mPrivateKey), use(mKeyType), use(mID);
size_t resultCount = 0;
try {
return update.execute();
}
catch (Poco::Exception& ex) {
addError(new ParamError(getTableName(), "[updatePrivkeyAndKeyType] mysql error by update", ex.displayText().data()));
addError(new ParamError(getTableName(), "data set: \n", toString().data()));
}
//printf("data valid: %s\n", toString().data());
return 0;
}
}
}

View File

@ -3,6 +3,7 @@
#include "ModelBase.h"
#include "Poco/Types.h"
#include "../../lib/DataTypeConverter.h"
namespace model {
namespace table {
@ -27,13 +28,21 @@ namespace model {
std::string toString();
inline const unsigned char* getPublicKey() const { if (mPublicKey.isNull()) return nullptr; return mPublicKey.value().content().data(); }
inline std::string getPublicKeyHexString() const { return DataTypeConverter::binToHex(mPublicKey); };
size_t getPublicKeySize() const { if (mPublicKey.isNull()) return 0; return mPublicKey.value().content().size(); }
bool hasPrivateKeyEncrypted() const;
bool isEncrypted() const;
bool changeKeyTypeToggleEncrypted();
inline bool hasPrivateKey() const { return !mPrivateKey.isNull(); }
inline const std::vector<unsigned char>& getPrivateKey() const { return mPrivateKey.value().content(); }
size_t updatePrivkeyAndKeyType();
//! \brief set encrypted private key
//! \param privateKey copy data, didn't move memory bin
void setPrivateKey(const MemoryBin* privateKey);
static const char* typeToString(KeyType type);
protected:
Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName);

View File

@ -35,6 +35,7 @@ namespace model {
inline int getAccountHederaId() const { return mAccountHederaId; }
inline int getCryptoKeyId() const { return mAccountKeyId; }
inline int getUserId() const { return mUserId; }
inline Poco::UInt64 getBalance() { return mBalance; }
inline double getBalanceDouble() { return (double)mBalance / 100000000.0; }

View File

@ -55,6 +55,7 @@ namespace model {
return mID;
}
Poco::Data::Statement HederaId::_loadFromDB(Poco::Data::Session session, const std::string& fieldName)
{

View File

@ -78,6 +78,24 @@ namespace model {
return false;
}
bool ModelBase::isExistInDB()
{
auto cm = ConnectionManager::getInstance();
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
Poco::Data::Statement select = _loadIdFromDB(session);
try {
select.executeAsync();
return select.wait() == 1;
}
catch (Poco::Exception& ex) {
addError(new ParamError(getTableName(), "mysql error by select id, check if exist in db", ex.displayText().data()));
addError(new ParamError(getTableName(), "data set: ", toString().data()));
}
return false;
}
bool ModelBase::deleteFromDB()
{
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);

View File

@ -40,6 +40,7 @@ namespace model {
size_t loadFromDB(const std::string& fieldName, const T& fieldValue);
template<class T>
bool isExistInDB(const std::string& fieldName, const T& fieldValue);
bool isExistInDB();
template<class WhereFieldType, class Tuple>
std::vector<Tuple> loadFromDB(const std::string& fieldName, const WhereFieldType& fieldValue, int expectedResults = 0);
template<class Tuple>

View File

@ -30,40 +30,58 @@
Poco::URI uri(request.getURI());
auto uri_query = uri.getQueryParameters();
std::string action = "";
std::string account_id_from_query;
Poco::AutoPtr<controller::HederaAccount> query_hedera_account;
// parsing get query params
if(uri_query.size() >= 2) {
if(uri_query[0].first == "action") {
action = uri_query[0].second;
}
if(uri_query[1].first == "account_id") {
std::string account_id_from_query;
int account_id = 0;
account_id_from_query = uri_query[1].second;
}
}
if(action == "updateBalance") {
int account_id = 0;
if(DataTypeConverter::strToInt(account_id_from_query, account_id) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting account_id_from_query to int"));
} else {
auto hedera_account = controller::HederaAccount::load("id", account_id);
if(!hedera_account.size() || hedera_account[0].isNull()) {
addError(new Error("Action Update Balance", "hedera id not found"));
if(DataTypeConverter::strToInt(account_id_from_query, account_id) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting account_id_from_query to int"));
} else {
hedera_time.reset();
hedera_account[0]->hederaAccountGetBalance(user, this);
addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string()));
auto hedera_accounts = controller::HederaAccount::load("id", account_id);
if(!hedera_accounts.size() || hedera_accounts[0].isNull()) {
addError(new Error("Action", "hedera account not found"));
} else {
query_hedera_account = hedera_accounts[0];
}
}
}
}
// add
else if(!form.empty()) {
// actions
if(!query_hedera_account.isNull())
{
if(action == "updateBalance")
{
hedera_time.reset();
query_hedera_account->hederaAccountGetBalance(user);
addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string()));
}
else if(action == "changeEncryption")
{
if(query_hedera_account->changeEncryption(user)) {
addNotification(new Success("Hedera Account", "success in changing encryption"));
}
}
}
else if(!form.empty()) // add
{
// collect
auto shardNumString = form.get("account-shard-num", "0");
auto realmNumString = form.get("account-realm-num", "0");
auto numString = form.get("account-num", "0");
auto privateKeyString = form.get("account-private-key", "");
auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false");
auto publicKeyString = form.get("account-public-key", "");
auto networkTypeString = form.get("account-network-type", "0");
//printf("private key encrypted: %s\n", privateKeyEncryptedString.data());
int shardNum = 0;
int realmNum = 0;
int num = 0;
@ -123,7 +141,7 @@
auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE);
if(crypto_key.isNull()) {
crypto_key = controller::CryptoKey::create(&key_pair, user);
crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true");
if(!crypto_key->getModel()->insertIntoDB(true)) {
addError(new Error("DB Error", "Error saving crypto key in DB"));
}
@ -131,15 +149,26 @@
printf("crypto key found in db\n");
}
if(0 == errorCount()) {
auto hedera_account = controller::HederaAccount::create(
user->getModel()->getID(),
hedera_id->getModel()->getID(),
crypto_key->getModel()->getID(),
0,
(model::table::HederaNetworkType)networkType
);
if(!hedera_account->getModel()->insertIntoDB(false)) {
addError(new Error("DB Error", "Error saving hedera account into DB"));
if(hedera_id->isExistInDB()) {
auto hedera_account = controller::HederaAccount::load(hedera_id);
if(hedera_account.isNull()) {
addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist"));
} else {
addError(new Error("Hedera Account", "Account already exist (same account id"));
}
} else {
auto hedera_account = controller::HederaAccount::create(
user->getModel()->getID(),
hedera_id->getModel()->getID(),
crypto_key->getModel()->getID(),
0,
(model::table::HederaNetworkType)networkType
);
if(!hedera_account->getModel()->insertIntoDB(false)) {
addError(new Error("DB Error", "Error saving hedera account into DB"));
}
}
}
@ -148,7 +177,9 @@
}
}
if(!query_hedera_account.isNull()) {
getErrors(query_hedera_account);
}
// list accounts
auto hedera_accounts = controller::HederaAccount::load("user_id", user->getModel()->getID());
@ -165,21 +196,33 @@
<div class="cell header-cell c2">Hedera Id</div>
<div class="cell header-cell c3">Balance</div>
<div class="cell header-cell c2">Server Type</div>
<div class="cell header-cell c3">Verschlüsselt?</div>
<div class="cell header-cell c3">Last Updated</div>
<div class="cell header-cell c5">Aktionen</div>
</div>
<% for(auto it = hedera_accounts.begin(); it != hedera_accounts.end(); it++) {
auto hedera_account_model = (*it)->getModel();
auto updateUrl = ServerConfig::g_serverPath + "/hedera_account?action=updateBalance&account_id=" + std::to_string(hedera_account_model->getID());
std::string changeEncryption("");
if(hedera_account_model->getUserId() == user->getModel()->getID()) {
changeEncryption = ServerConfig::g_serverPath + "/hedera_account?action=changeEncryption&account_id=" + std::to_string(hedera_account_model->getID());
}
//printf("change encryption: %s\n", changeEncryption.data());
%>
<div class="row">
<div class="cell c2"><%= (*it)->getHederaId()->getModel()->toString() %></div>
<div class="cell c3"><%= hedera_account_model->getBalanceDouble() %> hbar</div>
<div class="cell c2"><%= model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) %></div>
<div class="cell c3"><%= (*it)->getCryptoKey()->getModel()->isEncrypted() ? "Ja": "Nein" %></div>
<div class="cell c3"><%= hedera_account_model->getUpdatedString() %></div>
<button class="form-button" title="Anfrage an Hedera, kostet etwas" onclick="window.location.href='<%= updateUrl %>'" >
<button class="form-button" title="Anfrage an Hedera, aktuell kostenlos" onclick="window.location.href='<%= updateUrl %>'" >
Update Balance
</button>
<% if(changeEncryption != "") { %>
<button class="form-button" title="Ändere den Verschlüsselungsstatus des Private Keys in der Datenbank" onclick="window.location.href='<%= changeEncryption %>'">
Change Encryption
</button>
<% } %>
</div>
<% } %>
</div>
@ -195,6 +238,8 @@
<input class="form-control" id="account-num" placeholder="num" type="number" name="account-num"/>
<label class="form-label" for="account-private-key">Private Key</label>
<input class="form-control" id="account-private-key" type="text" name="account-private-key"/>
<label class="form-label" for="account-private-key-encrypted" title="Wenn er verschlüsselt ist, kannst nur du Hedera Transaktionen damit bezahlen, wenn er nicht verschlüsselt ist kann er für alle Hedera Transaktionen automatisch verwendet werden. Ich empfehle dafür ein separates Konto mit wenigen Hashbars anzulegen.">Private Key verschlüsseln?</label>
<input class="form-control" id="account-private-key-encrypted" type="checkbox" name="account-private-key-encrypted" value="true"/>
<label class="form-label" for="account-public-key">Public Key</label>
<input class="form-control" id="account-public-key" type="text" name="account-public-key"/>
<label class="form-label" for="account-network-type">Network Type</label>