mirror of
https://github.com/monero-project/monero.git
synced 2025-03-30 14:48:08 -04:00
add magic
This commit is contained in:
parent
418adb7857
commit
54dab2e121
@ -56,6 +56,8 @@ using namespace epee;
|
||||
#include "rpc/core_rpc_server_commands_defs.h"
|
||||
#include "daemonizer/daemonizer.h"
|
||||
|
||||
#define KEY_IMAGE_EXPORT_FILE_MAGIC "Monero key image export\003"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.rpc"
|
||||
|
||||
@ -2951,102 +2953,150 @@ namespace tools
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_export_encrypted_key_images(const wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
/bool wallet_rpc_server::on_export_encrypted_key_images(const wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_EXPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
try
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = m_wallet->export_key_images(req.all);
|
||||
res.offset = ski.first;
|
||||
|
||||
std::string data;
|
||||
const cryptonote::account_public_address &keys = m_wallet->get_account().get_keys().m_account_address;
|
||||
|
||||
data.reserve(4 + sizeof(crypto::public_key) * 2 + ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)));
|
||||
|
||||
data.resize(4);
|
||||
data[0] = res.offset & 0xff;
|
||||
data[1] = (res.offset >> 8) & 0xff;
|
||||
data[2] = (res.offset >> 16) & 0xff;
|
||||
data[3] = (res.offset >> 24) & 0xff;
|
||||
|
||||
data += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key));
|
||||
data += std::string((const char *)&keys.m_view_public_key, sizeof(crypto::public_key));
|
||||
|
||||
for (const auto &item : ski.second)
|
||||
{
|
||||
data += std::string((const char *)&item.first, sizeof(crypto::key_image));
|
||||
data += std::string((const char *)&item.second, sizeof(crypto::signature));
|
||||
}
|
||||
|
||||
std::string ciphertext = m_wallet->encrypt_with_view_secret_key(data);
|
||||
|
||||
std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC));
|
||||
res.encrypted_key_images_blob = epee::string_tools::buff_to_hex_nodelimer(magic + ciphertext);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}/------------------------------------------------------------------------------------------------------------------------------
|
||||
/bool wallet_rpc_server::on_import_encrypted_key_images(const wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
if (m_restricted)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_DENIED;
|
||||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
if (!m_wallet->is_trusted_daemon())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "This command requires a trusted daemon.";
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
std::string data;
|
||||
if (!epee::string_tools::parse_hexstr_to_binbuff(req.encrypted_key_images_blob, data))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
|
||||
er.message = "Failed to parse encrypted key images blob";
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t magiclen = strlen(KEY_IMAGE_EXPORT_FILE_MAGIC);
|
||||
if (data.size() < magiclen || memcmp(data.data(), KEY_IMAGE_EXPORT_FILE_MAGIC, magiclen))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
|
||||
er.message = "Bad key image export file magic in blob";
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = m_wallet->export_key_images(req.all);
|
||||
res.offset = ski.first;
|
||||
|
||||
// Serialize the key images and signatures into a single blob
|
||||
std::string data;
|
||||
data.reserve(ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)));
|
||||
for (const auto &item : ski.second)
|
||||
{
|
||||
data += std::string((const char *)&item.first, sizeof(crypto::key_image));
|
||||
data += std::string((const char *)&item.second, sizeof(crypto::signature));
|
||||
}
|
||||
|
||||
// Encrypt the serialized data
|
||||
std::string ciphertext = m_wallet->encrypt_with_view_secret_key(data);
|
||||
|
||||
// Encode the encrypted data as hex
|
||||
res.encrypted_key_images_blob = epee::string_tools::buff_to_hex_nodelimer(ciphertext);
|
||||
data = m_wallet->decrypt_with_view_secret_key(std::string(data, magiclen));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
|
||||
er.message = "Failed to decrypt blob";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
const size_t headerlen = 4 + 2 * sizeof(crypto::public_key);
|
||||
if (data.size() < headerlen)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
|
||||
er.message = "Bad data size from file";
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t offset = (uint8_t)data[0] | (((uint8_t)data[1]) << 8) | (((uint8_t)data[2]) << 16) | (((uint8_t)data[3]) << 24);
|
||||
if (offset > m_wallet->get_num_transfer_details())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
|
||||
er.message = "Offset larger than known outputs";
|
||||
return false;
|
||||
}
|
||||
|
||||
const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data[4];
|
||||
const crypto::public_key &public_view_key = *(const crypto::public_key*)&data[4 + sizeof(crypto::public_key)];
|
||||
const cryptonote::account_public_address &keys = m_wallet->get_account().get_keys().m_account_address;
|
||||
if (public_spend_key != keys.m_spend_public_key || public_view_key != keys.m_view_public_key)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
|
||||
er.message = "Key images from different account";
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t record_size = sizeof(crypto::key_image) + sizeof(crypto::signature);
|
||||
if ((data.size() - headerlen) % record_size)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
|
||||
er.message = "Bad data size from file";
|
||||
return false;
|
||||
}
|
||||
size_t nki = (data.size() - headerlen) / record_size;
|
||||
|
||||
std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
|
||||
ski.reserve(nki);
|
||||
for (size_t n = 0; n < nki; ++n)
|
||||
{
|
||||
crypto::key_image key_image = *reinterpret_cast<const crypto::key_image*>(&data[headerlen + n * record_size]);
|
||||
crypto::signature signature = *reinterpret_cast<const crypto::signature*>(&data[headerlen + n * record_size + sizeof(crypto::key_image)]);
|
||||
|
||||
ski.push_back(std::make_pair(key_image, signature));
|
||||
}
|
||||
|
||||
uint64_t spent = 0, unspent = 0;
|
||||
uint64_t height = m_wallet->import_key_images(ski, offset, spent, unspent);
|
||||
res.height = height;
|
||||
res.spent = spent;
|
||||
res.unspent = unspent;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_import_encrypted_key_images(const wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_IMPORT_ENCRYPTED_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
if (m_restricted)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_DENIED;
|
||||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
if (!m_wallet->is_trusted_daemon())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "This command requires a trusted daemon.";
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
// Decode the hex-encoded encrypted blob
|
||||
std::string ciphertext;
|
||||
if (!epee::string_tools::parse_hexstr_to_binbuff(req.encrypted_key_images_blob, ciphertext))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
|
||||
er.message = "Failed to parse encrypted key images blob";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decrypt the ciphertext
|
||||
std::string decrypted_data = m_wallet->decrypt_with_view_secret_key(ciphertext);
|
||||
|
||||
// Deserialize the decrypted data into key images and signatures
|
||||
std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
|
||||
const size_t record_size = sizeof(crypto::key_image) + sizeof(crypto::signature);
|
||||
if (decrypted_data.size() % record_size != 0)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE;
|
||||
er.message = "Decrypted data size is not a multiple of the record size";
|
||||
return false;
|
||||
}
|
||||
size_t num_records = decrypted_data.size() / record_size;
|
||||
ski.reserve(num_records);
|
||||
for (size_t i = 0; i < num_records; ++i)
|
||||
{
|
||||
crypto::key_image ki;
|
||||
crypto::signature sig;
|
||||
memcpy(&ki, &decrypted_data[i * record_size], sizeof(crypto::key_image));
|
||||
memcpy(&sig, &decrypted_data[i * record_size + sizeof(crypto::key_image)], sizeof(crypto::signature));
|
||||
ski.emplace_back(ki, sig);
|
||||
}
|
||||
|
||||
uint64_t spent = 0, unspent = 0;
|
||||
uint64_t height = m_wallet->import_key_images(ski, req.offset, spent, unspent);
|
||||
res.height = height;
|
||||
res.spent = spent;
|
||||
res.unspent = unspent;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}/------------------------------------------------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_make_uri(const wallet_rpc::COMMAND_RPC_MAKE_URI::request& req, wallet_rpc::COMMAND_RPC_MAKE_URI::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user