1
0
Fork 0
forked from lthn/blockchain

implemented secure api for configuring wallets data

This commit is contained in:
cryptozoidberg 2020-03-20 04:19:25 +01:00
parent c0f651ff33
commit 31e328768e
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
8 changed files with 150 additions and 86 deletions

View file

@ -0,0 +1,66 @@
// Copyright (c) 2014-2020 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <string>
#include "wallet/view_iface.h"
namespace tools
{
#pragma pack(push, 1)
struct app_data_file_binary_header
{
uint64_t m_signature;
uint64_t m_cb_body;
};
#pragma pack (pop)
inline
std::string load_encrypted_file(const std::string& path, const std::string& key, std::string& body, uint64_t signature)
{
std::string app_data_buff;
bool r = epee::file_io_utils::load_file_to_string(path, app_data_buff);
if (!r)
{
return API_RETURN_CODE_NOT_FOUND;
}
if (app_data_buff.size() < sizeof(app_data_file_binary_header))
{
LOG_ERROR("app_data_buff.size()(" << app_data_buff.size() << ") < sizeof(app_data_file_binary_header) (" << sizeof(app_data_file_binary_header) << ") check failed while loading from " << path);
return API_RETURN_CODE_INVALID_FILE;
}
crypto::chacha_crypt(app_data_buff, key);
const app_data_file_binary_header* phdr = reinterpret_cast<const app_data_file_binary_header*>(app_data_buff.data());
if (phdr->m_signature != signature)
{
return API_RETURN_CODE_WRONG_PASSWORD;
}
body = app_data_buff.substr(sizeof(app_data_file_binary_header)).c_str();
return API_RETURN_CODE_OK;
}
inline
std::string store_encrypted_file(const std::string& path, const std::string& key, const std::string& body, uint64_t signature)
{
std::string buff(sizeof(app_data_file_binary_header), 0);
app_data_file_binary_header* phdr = (app_data_file_binary_header*)buff.data();
phdr->m_signature = signature;
phdr->m_cb_body = 0; // for future use
buff.append(body);
crypto::chacha_crypt(buff, key);
bool r = epee::file_io_utils::save_string_to_file(path, buff);
if (r)
return API_RETURN_CODE_OK;
else
return API_RETURN_CODE_FAIL;
}
}

View file

@ -12,6 +12,7 @@
#include "string_coding.h"
#include "gui_utils.h"
#include "notification_helper.h"
#include "common/config_encrypt_helper.h"
#define PREPARE_ARG_FROM_JSON(arg_type, var_name) \
arg_type var_name = AUTO_VAL_INIT(var_name); \
@ -1047,6 +1048,35 @@ void MainWindow::on_clear_events()
CATCH_ENTRY2(void());
}
QString MainWindow::store_secure_app_data(const QString& param)
{
TRY_ENTRY();
LOG_API_TIMING();
if (!tools::create_directories_if_necessary(m_backend.get_config_folder()))
{
view::api_response ar;
LOG_PRINT_L0("Failed to create data directory: " << m_backend.get_config_folder());
ar.error_code = API_RETURN_CODE_FAIL;
return MAKE_RESPONSE(ar);
}
view::api_response ar = AUTO_VAL_INIT(ar);
ar.error_code = tools::store_encrypted_file(m_backend.get_config_folder() + "/" + GUI_SECURE_CONFIG_FILENAME,
m_master_password, param.toStdString(), APP_DATA_FILE_BINARY_SIGNATURE);
if (ar.error_code != API_RETURN_CODE_OK)
{
return MAKE_RESPONSE(ar);
}
crypto::hash master_password_pre_hash = crypto::cn_fast_hash(m_master_password.c_str(), m_master_password.length());
crypto::hash master_password_hash = crypto::cn_fast_hash(&master_password_pre_hash, sizeof master_password_pre_hash);
LOG_PRINT_L0("store_secure_app_data, r = " << ar.error_code << ", pass hash: " << master_password_hash);
return MAKE_RESPONSE(ar);
CATCH_ENTRY_FAIL_API_RESPONCE();
}
QString MainWindow::get_secure_app_data(const QString& param)
{
TRY_ENTRY();
@ -1060,41 +1090,21 @@ QString MainWindow::get_secure_app_data(const QString& param)
return MAKE_RESPONSE(ar);
}
std::string app_data_buff;
std::string filename = m_backend.get_config_folder() + "/" + GUI_SECURE_CONFIG_FILENAME;
bool r = file_io_utils::load_file_to_string(filename, app_data_buff);
if (!r)
std::string res_body;
std::string rsp_code = tools::load_encrypted_file(filename, pwd.pass, res_body, APP_DATA_FILE_BINARY_SIGNATURE);
if (rsp_code != API_RETURN_CODE_OK)
{
LOG_PRINT_L1("gui secure config was not loaded from " << filename);
return "";
}
if (app_data_buff.size() < sizeof(app_data_file_binary_header))
{
LOG_ERROR("app_data_buff.size() < sizeof(app_data_file_binary_header) check failed while loading from " << filename);
view::api_response ar;
ar.error_code = API_RETURN_CODE_FAIL;
ar.error_code = rsp_code;
return MAKE_RESPONSE(ar);
}
crypto::chacha_crypt(app_data_buff, pwd.pass);
const app_data_file_binary_header* phdr = reinterpret_cast<const app_data_file_binary_header*>(app_data_buff.data());
if (phdr->m_signature != APP_DATA_FILE_BINARY_SIGNATURE)
{
LOG_ERROR("gui secure config: password missmatch while loading from " << filename);
view::api_response ar;
ar.error_code = API_RETURN_CODE_WRONG_PASSWORD;
return MAKE_RESPONSE(ar);
}
m_master_password = pwd.pass;
crypto::hash master_password_pre_hash = crypto::cn_fast_hash(m_master_password.c_str(), m_master_password.length());
crypto::hash master_password_hash = crypto::cn_fast_hash(&master_password_pre_hash, sizeof master_password_pre_hash);
LOG_PRINT_L0("gui secure config loaded ok from " << filename << ", pass hash: " << master_password_hash);
return app_data_buff.substr(sizeof(app_data_file_binary_header)).c_str();
return res_body.c_str();
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
}
@ -1267,40 +1277,6 @@ QString MainWindow::get_app_data()
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
}
QString MainWindow::store_secure_app_data(const QString& param)
{
TRY_ENTRY();
LOG_API_TIMING();
if (!tools::create_directories_if_necessary(m_backend.get_config_folder()))
{
view::api_response ar;
LOG_PRINT_L0("Failed to create data directory: " << m_backend.get_config_folder());
return MAKE_RESPONSE(ar);
}
std::string buff(sizeof(app_data_file_binary_header), 0);
app_data_file_binary_header* phdr = (app_data_file_binary_header*)buff.data();
phdr->m_signature = APP_DATA_FILE_BINARY_SIGNATURE;
phdr->m_cb_body = 0; // for future use
buff.append(param.toStdString());
crypto::chacha_crypt(buff, m_master_password);
bool r = file_io_utils::save_string_to_file(m_backend.get_config_folder() + "/" + GUI_SECURE_CONFIG_FILENAME, buff);
view::api_response ar;
if (r)
ar.error_code = API_RETURN_CODE_OK;
else
ar.error_code = API_RETURN_CODE_FAIL;
crypto::hash master_password_pre_hash = crypto::cn_fast_hash(m_master_password.c_str(), m_master_password.length());
crypto::hash master_password_hash = crypto::cn_fast_hash(&master_password_pre_hash, sizeof master_password_pre_hash);
LOG_PRINT_L0("store_secure_app_data, r = " << r << ", pass hash: " << master_password_hash);
return MAKE_RESPONSE(ar);
CATCH_ENTRY_FAIL_API_RESPONCE();
}
QString MainWindow::have_secure_app_data()
{

View file

@ -8,6 +8,7 @@
#include <QWebChannel>
#include "wallet/view_iface.h"
#ifndef Q_MOC_RUN
#include "wallet/wallets_manager.h"
#include "currency_core/offers_services_helpers.h"
@ -18,13 +19,7 @@ class QWebEngineView;
class QLineEdit;
QT_END_NAMESPACE
#pragma pack(push, 1)
struct app_data_file_binary_header
{
uint64_t m_signature;
uint64_t m_cb_body;
};
#pragma pack (pop)
#define APP_DATA_FILE_BINARY_SIGNATURE 0x1000111101101021LL

View file

@ -11,6 +11,8 @@
#include "string_tools.h"
#include "currency_core/currency_format_utils.h"
#include "wallets_manager.h"
#include "common/base58.h"
#include "common/config_encrypt_helper.h"
#define ANDROID_PACKAGE_NAME "com.zano_mobile"
#ifdef IOS_BUILD
@ -22,7 +24,9 @@
#endif
#define WALLETS_FOLDER_NAME "wallets"
#define APP_CONFIG_FOLDER "app_config"
#define APP_CONFIG_FILENAME "app_cfg.json"
#define APP_CONFIG_FILENAME "app_cfg.bin"
#define MOBILE_APP_DATA_FILE_BINARY_SIGNATURE 0x1000111201101011LL //Bender's nightmare
#define GENERAL_INTERNAL_ERRROR_INSTANCE "GENERAL_INTERNAL_ERROR: WALLET INSTNACE NOT FOUND"
#define GENERAL_INTERNAL_ERRROR_INIT "Failed to intialize library"
@ -155,20 +159,27 @@ namespace plain_wallet
return epee::serialization::store_t_to_json(ok_response);
}
std::string get_appconfig()
std::string get_appconfig(const std::string& encryption_key)
{
std::string res_str = "{}";
std::string res_str;
std::string app_config_config_path = get_app_config_folder() + APP_CONFIG_FILENAME;
epee::file_io_utils::load_file_to_string(app_config_config_path, res_str);
return res_str;
}
std::string set_appconfig(const std::string& conf_str)
{
std::string app_config_config_path = get_app_config_folder() + APP_CONFIG_FILENAME;
if (!epee::file_io_utils::save_string_to_file(app_config_config_path, conf_str))
std::string ret_code = tools::load_encrypted_file(app_config_config_path, encryption_key, res_str, MOBILE_APP_DATA_FILE_BINARY_SIGNATURE);
if (ret_code != API_RETURN_CODE_OK)
{
error_response err_result = AUTO_VAL_INIT(err_result);
err_result.error.code = API_RETURN_CODE_NOT_FOUND;
err_result.error.code = ret_code;
return epee::serialization::store_t_to_json(err_result);
}
return res_str;
}
std::string set_appconfig(const std::string& conf_str, const std::string& encryption_key)
{
std::string app_config_config_path = get_app_config_folder() + APP_CONFIG_FILENAME;
std::string ret_code = tools::store_encrypted_file(app_config_config_path, encryption_key, conf_str, MOBILE_APP_DATA_FILE_BINARY_SIGNATURE);
if (ret_code != API_RETURN_CODE_OK)
{
error_response err_result = AUTO_VAL_INIT(err_result);
err_result.error.code = ret_code;
return epee::serialization::store_t_to_json(err_result);
}
else
@ -177,7 +188,14 @@ namespace plain_wallet
ok_response.result.return_code = API_RETURN_CODE_OK;
return epee::serialization::store_t_to_json(ok_response);
}
}
std::string generate_random_key(uint64_t lenght)
{
std::string buff;
buff.resize(lenght);
crypto::generate_random_bytes(lenght, const_cast<char*>(buff.data()));
return tools::base58::encode(buff);
}
std::string get_logs_buffer()

View file

@ -15,8 +15,9 @@ namespace plain_wallet
std::string get_version();
std::string get_wallet_files();
std::string get_appconfig();
std::string set_appconfig(const std::string& conf_str);
std::string get_appconfig(const std::string& encryption_key);
std::string set_appconfig(const std::string& conf_str, const std::string& encryption_key);
std::string generate_random_key(uint64_t lenght);
std::string get_logs_buffer();
std::string truncate_log();

View file

@ -779,6 +779,7 @@ public:
#define API_RETURN_CODE_CORE_BUSY "CORE_BUSY"
#define API_RETURN_CODE_OVERFLOW "OVERFLOW"
#define API_RETURN_CODE_BUSY "BUSY"
#define API_RETURN_CODE_INVALID_FILE "INVALID_FILE"
#define API_MAX_ALIASES_COUNT 10000

View file

@ -461,8 +461,7 @@ bool core_concurrency_test(boost::program_options::variables_map& vm, size_t wth
test_protocol_handler protocol_handler(c, core_listener.get());
c.set_currency_protocol(&protocol_handler);
tools::db::db_backend_selector dbbs;
if (!c.init(vm, dbbs))
if (!c.init(vm))
{
LOG_ERROR("Failed to init core");
return false;
@ -528,8 +527,7 @@ bool core_concurrency_test(boost::program_options::variables_map& vm, size_t wth
test_protocol_handler protocol_handler(c, core_listener.get());
c.set_currency_protocol(&protocol_handler);
tools::db::db_backend_selector dbbs;
if (!c.init(vm, dbbs))
if (!c.init(vm))
{
LOG_ERROR("Failed to init core");
return false;

View file

@ -32,9 +32,18 @@ void run_plain_wallet_api_test()
LOG_PRINT_L0("Creating instance...");
std::string s = plain_wallet::init("195.201.107.230", "11211", 1);
std::string fres = plain_wallet::get_logs_buffer();
std::string fres2 = plain_wallet::truncate_log();
std::string fres3 = plain_wallet::get_logs_buffer();
std::string key = plain_wallet::generate_random_key(10);
std::string test_data = "1234567890 test test ";
std::string res = plain_wallet::set_appconfig(test_data, key);
std::string test_data2 = plain_wallet::get_appconfig(key);
if (test_data2 != test_data)
{
LOG_ERROR("Error");
}
return;
//std::string fres = plain_wallet::get_logs_buffer();
//std::string fres2 = plain_wallet::truncate_log();
//std::string fres3 = plain_wallet::get_logs_buffer();