Improve RPC JSON depth handling (#1072)

This commit is contained in:
Roy Keene 2018-08-18 13:46:17 -05:00
commit 62a8e677b3
5 changed files with 597 additions and 480 deletions

View file

@ -96,7 +96,7 @@ TEST (wallet, one_item_iteration)
rai::raw_key password;
wallet.wallet_key (password, transaction);
rai::raw_key key;
key.decrypt (rai::wallet_value (i->second).key, password, wallet.salt (transaction).owords[0]);
key.decrypt (rai::wallet_value (i->second).key, password, i->first.uint256 ().owords[0]);
ASSERT_EQ (key1.prv, key);
}
}
@ -124,7 +124,7 @@ TEST (wallet, two_item_iteration)
rai::raw_key password;
wallet.wallet_key (password, transaction);
rai::raw_key key;
key.decrypt (rai::wallet_value (i->second).key, password, wallet.salt (transaction).owords[0]);
key.decrypt (rai::wallet_value (i->second).key, password, i->first.uint256 ().owords[0]);
prvs.insert (key.data);
}
}
@ -658,7 +658,7 @@ TEST (wallet, insert_locked)
ASSERT_TRUE (wallet->insert_adhoc (rai::keypair ().prv).is_zero ());
}
TEST (wallet, version_1_2_upgrade)
TEST (wallet, version_1_upgrade)
{
rai::system system (24000, 1);
auto wallet (system.wallet (0));
@ -683,7 +683,7 @@ TEST (wallet, version_1_2_upgrade)
wallet->enter_password ("1");
ASSERT_TRUE (wallet->valid_password ());
ASSERT_EQ (2, wallet->store.version (rai::transaction (wallet->store.environment, nullptr, false)));
ASSERT_EQ (wallet->store.version_current, wallet->store.version (rai::transaction (wallet->store.environment, nullptr, false)));
rai::raw_key prv;
ASSERT_FALSE (wallet->store.fetch (rai::transaction (wallet->store.environment, nullptr, false), key.pub, prv));
ASSERT_EQ (key.prv, prv);
@ -702,7 +702,7 @@ TEST (wallet, version_1_2_upgrade)
}
wallet->enter_password ("1");
ASSERT_TRUE (wallet->valid_password ());
ASSERT_EQ (2, wallet->store.version (rai::transaction (wallet->store.environment, nullptr, false)));
ASSERT_EQ (wallet->store.version_current, wallet->store.version (rai::transaction (wallet->store.environment, nullptr, false)));
rai::raw_key prv2;
ASSERT_FALSE (wallet->store.fetch (rai::transaction (wallet->store.environment, nullptr, false), key.pub, prv2));
ASSERT_EQ (key.prv, prv2);
@ -798,7 +798,7 @@ TEST (wallet, insert_deterministic_locked)
ASSERT_TRUE (wallet->deterministic_insert ().is_zero ());
}
TEST (wallet, version_2_3_upgrade)
TEST (wallet, version_2_upgrade)
{
rai::system system (24000, 1);
auto wallet (system.wallet (0));
@ -818,12 +818,53 @@ TEST (wallet, version_2_3_upgrade)
wallet->store.attempt_password (transaction, "1");
}
rai::transaction transaction (wallet->store.environment, nullptr, false);
ASSERT_EQ (3, wallet->store.version (transaction));
ASSERT_EQ (wallet->store.version_current, wallet->store.version (transaction));
ASSERT_TRUE (wallet->store.exists (transaction, rai::wallet_store::deterministic_index_special));
ASSERT_TRUE (wallet->store.exists (transaction, rai::wallet_store::seed_special));
ASSERT_FALSE (wallet->deterministic_insert ().is_zero ());
}
TEST (wallet, version_3_upgrade)
{
rai::system system (24000, 1);
auto wallet (system.wallet (0));
wallet->store.rekey (rai::transaction (wallet->store.environment, nullptr, true), "1");
wallet->enter_password ("1");
ASSERT_TRUE (wallet->valid_password ());
ASSERT_EQ (wallet->store.version_current, wallet->store.version (rai::transaction (wallet->store.environment, nullptr, false)));
rai::keypair key;
rai::raw_key seed;
rai::uint256_union seed_ciphertext;
rai::random_pool.GenerateBlock (seed.data.bytes.data (), seed.data.bytes.size ());
{
rai::transaction transaction (wallet->store.environment, nullptr, true);
rai::raw_key password_l;
rai::wallet_value value (wallet->store.entry_get_raw (transaction, rai::wallet_store::wallet_key_special));
rai::raw_key kdf;
wallet->store.derive_key (kdf, transaction, "1");
password_l.decrypt (value.key, kdf, wallet->store.salt (transaction).owords[0]);
rai::uint256_union ciphertext;
ciphertext.encrypt (key.prv, password_l, wallet->store.salt (transaction).owords[0]);
wallet->store.entry_put_raw (transaction, key.pub, rai::wallet_value (ciphertext, 0));
seed_ciphertext.encrypt (seed, password_l, wallet->store.salt (transaction).owords[0]);
wallet->store.entry_put_raw (transaction, rai::wallet_store::seed_special, rai::wallet_value (seed_ciphertext, 0));
wallet->store.version_put (transaction, 3);
}
wallet->enter_password ("1");
ASSERT_TRUE (wallet->valid_password ());
ASSERT_EQ (wallet->store.version_current, wallet->store.version (rai::transaction (wallet->store.environment, nullptr, false)));
rai::raw_key prv;
ASSERT_FALSE (wallet->store.fetch (rai::transaction (wallet->store.environment, nullptr, false), key.pub, prv));
ASSERT_EQ (key.prv, prv);
{
rai::transaction transaction (wallet->store.environment, nullptr, false);
rai::raw_key seed_compare;
wallet->store.seed (seed_compare, transaction);
ASSERT_EQ (seed, seed_compare);
ASSERT_NE (seed_ciphertext, wallet->store.entry_get_raw (transaction, rai::wallet_store::seed_special).key);
}
}
TEST (wallet, no_work)
{
rai::system system (24000, 1);

View file

@ -53,7 +53,8 @@ address (boost::asio::ip::address_v6::loopback ()),
port (rai::rpc::rpc_port),
enable_control (false),
frontier_request_limit (16384),
chain_request_limit (16384)
chain_request_limit (16384),
max_json_depth (20)
{
}
@ -62,7 +63,8 @@ address (boost::asio::ip::address_v6::loopback ()),
port (rai::rpc::rpc_port),
enable_control (enable_control_a),
frontier_request_limit (16384),
chain_request_limit (16384)
chain_request_limit (16384),
max_json_depth (20)
{
}
@ -73,6 +75,7 @@ void rai::rpc_config::serialize_json (boost::property_tree::ptree & tree_a) cons
tree_a.put ("enable_control", enable_control);
tree_a.put ("frontier_request_limit", frontier_request_limit);
tree_a.put ("chain_request_limit", chain_request_limit);
tree_a.put ("max_json_depth", max_json_depth);
}
bool rai::rpc_config::deserialize_json (boost::property_tree::ptree const & tree_a)
@ -93,6 +96,7 @@ bool rai::rpc_config::deserialize_json (boost::property_tree::ptree const & tree
enable_control = tree_a.get<bool> ("enable_control");
auto frontier_request_limit_l (tree_a.get<std::string> ("frontier_request_limit"));
auto chain_request_limit_l (tree_a.get<std::string> ("chain_request_limit"));
max_json_depth = tree_a.get<uint8_t> ("max_json_depth", max_json_depth);
try
{
port = std::stoul (port_l);
@ -3522,460 +3526,481 @@ void rai::rpc_handler::process_request ()
{
try
{
std::stringstream istream (body);
boost::property_tree::read_json (istream, request);
std::string action (request.get<std::string> ("action"));
if (action == "password_enter")
{
password_enter ();
request.erase ("password");
reprocess_body (body, request);
}
else if (action == "password_change")
{
password_change ();
request.erase ("password");
reprocess_body (body, request);
}
else if (action == "wallet_unlock")
{
password_enter ();
request.erase ("password");
reprocess_body (body, request);
}
if (node.config.logging.log_rpc ())
{
BOOST_LOG (node.log) << boost::str (boost::format ("%1% ") % request_id) << body;
}
if (action == "account_balance")
{
account_balance ();
}
else if (action == "account_block_count")
{
account_block_count ();
}
else if (action == "account_count")
{
account_count ();
}
else if (action == "account_create")
{
account_create ();
}
else if (action == "account_get")
{
account_get ();
}
else if (action == "account_history")
{
account_history ();
}
else if (action == "account_info")
{
account_info ();
}
else if (action == "account_key")
{
account_key ();
}
else if (action == "account_list")
{
account_list ();
}
else if (action == "account_move")
{
account_move ();
}
else if (action == "account_remove")
{
account_remove ();
}
else if (action == "account_representative")
{
account_representative ();
}
else if (action == "account_representative_set")
{
account_representative_set ();
}
else if (action == "account_weight")
{
account_weight ();
}
else if (action == "accounts_balances")
{
accounts_balances ();
}
else if (action == "accounts_create")
{
accounts_create ();
}
else if (action == "accounts_frontiers")
{
accounts_frontiers ();
}
else if (action == "accounts_pending")
{
accounts_pending ();
}
else if (action == "available_supply")
{
available_supply ();
}
else if (action == "block")
{
block ();
}
else if (action == "block_confirm")
{
block_confirm ();
}
else if (action == "blocks")
{
blocks ();
}
else if (action == "blocks_info")
{
blocks_info ();
}
else if (action == "block_account")
{
block_account ();
}
else if (action == "block_count")
{
block_count ();
}
else if (action == "block_count_type")
{
block_count_type ();
}
else if (action == "block_create")
{
block_create ();
}
else if (action == "block_hash")
{
block_hash ();
}
else if (action == "successors")
{
chain (true);
}
else if (action == "bootstrap")
{
bootstrap ();
}
else if (action == "bootstrap_any")
{
bootstrap_any ();
}
else if (action == "chain")
{
chain ();
}
else if (action == "delegators")
{
delegators ();
}
else if (action == "delegators_count")
{
delegators_count ();
}
else if (action == "deterministic_key")
{
deterministic_key ();
}
else if (action == "confirmation_history")
{
confirmation_history ();
}
else if (action == "frontiers")
{
frontiers ();
}
else if (action == "frontier_count")
{
account_count ();
}
else if (action == "history")
{
request.put ("head", request.get<std::string> ("hash"));
account_history ();
}
else if (action == "keepalive")
{
keepalive ();
}
else if (action == "key_create")
{
key_create ();
}
else if (action == "key_expand")
{
key_expand ();
}
else if (action == "krai_from_raw")
{
mrai_from_raw (rai::kxrb_ratio);
}
else if (action == "krai_to_raw")
{
mrai_to_raw (rai::kxrb_ratio);
}
else if (action == "ledger")
{
ledger ();
}
else if (action == "mrai_from_raw")
{
mrai_from_raw ();
}
else if (action == "mrai_to_raw")
{
mrai_to_raw ();
}
else if (action == "password_change")
{
// Processed before logging
}
else if (action == "password_enter")
{
// Processed before logging
}
else if (action == "password_valid")
{
password_valid ();
}
else if (action == "payment_begin")
{
payment_begin ();
}
else if (action == "payment_init")
{
payment_init ();
}
else if (action == "payment_end")
{
payment_end ();
}
else if (action == "payment_wait")
{
payment_wait ();
}
else if (action == "peers")
{
peers ();
}
else if (action == "pending")
{
pending ();
}
else if (action == "pending_exists")
{
pending_exists ();
}
else if (action == "process")
{
process ();
}
else if (action == "rai_from_raw")
{
mrai_from_raw (rai::xrb_ratio);
}
else if (action == "rai_to_raw")
{
mrai_to_raw (rai::xrb_ratio);
}
else if (action == "receive")
{
receive ();
}
else if (action == "receive_minimum")
{
receive_minimum ();
}
else if (action == "receive_minimum_set")
{
receive_minimum_set ();
}
else if (action == "representatives")
{
representatives ();
}
else if (action == "representatives_online")
{
representatives_online ();
}
else if (action == "republish")
{
republish ();
}
else if (action == "search_pending")
{
search_pending ();
}
else if (action == "search_pending_all")
{
search_pending_all ();
}
else if (action == "send")
{
send ();
}
else if (action == "stats")
{
stats ();
}
else if (action == "stop")
{
stop ();
}
else if (action == "unchecked")
{
unchecked ();
}
else if (action == "unchecked_clear")
{
unchecked_clear ();
}
else if (action == "unchecked_get")
{
unchecked_get ();
}
else if (action == "unchecked_keys")
{
unchecked_keys ();
}
else if (action == "validate_account_number")
{
validate_account_number ();
}
else if (action == "version")
{
version ();
}
else if (action == "wallet_add")
{
wallet_add ();
}
else if (action == "wallet_add_watch")
{
wallet_add_watch ();
}
// Obsolete
else if (action == "wallet_balance_total")
{
wallet_info ();
}
else if (action == "wallet_balances")
{
wallet_balances ();
}
else if (action == "wallet_change_seed")
{
wallet_change_seed ();
}
else if (action == "wallet_contains")
{
wallet_contains ();
}
else if (action == "wallet_create")
{
wallet_create ();
}
else if (action == "wallet_destroy")
{
wallet_destroy ();
}
else if (action == "wallet_export")
{
wallet_export ();
}
else if (action == "wallet_frontiers")
{
wallet_frontiers ();
}
else if (action == "wallet_info")
{
wallet_info ();
}
else if (action == "wallet_key_valid")
{
wallet_key_valid ();
}
else if (action == "wallet_ledger")
{
wallet_ledger ();
}
else if (action == "wallet_lock")
{
wallet_lock ();
}
else if (action == "wallet_locked")
{
password_valid (true);
}
else if (action == "wallet_pending")
{
wallet_pending ();
}
else if (action == "wallet_representative")
{
wallet_representative ();
}
else if (action == "wallet_representative_set")
{
wallet_representative_set ();
}
else if (action == "wallet_republish")
{
wallet_republish ();
}
else if (action == "wallet_unlock")
{
// Processed before logging
}
else if (action == "wallet_work_get")
{
wallet_work_get ();
}
else if (action == "work_generate")
{
work_generate ();
}
else if (action == "work_cancel")
{
work_cancel ();
}
else if (action == "work_get")
{
work_get ();
}
else if (action == "work_set")
{
work_set ();
}
else if (action == "work_validate")
{
work_validate ();
}
else if (action == "work_peer_add")
{
work_peer_add ();
}
else if (action == "work_peers")
{
work_peers ();
}
else if (action == "work_peers_clear")
{
work_peers_clear ();
auto max_depth_exceeded (false);
auto max_depth_possible (0);
for (auto ch : body)
{
if (ch == '[' || ch == '{')
{
if (max_depth_possible >= rpc.config.max_json_depth)
{
max_depth_exceeded = true;
break;
}
++max_depth_possible;
}
}
if (max_depth_exceeded)
{
error_response (response, "Max JSON depth exceeded");
}
else
{
error_response (response, "Unknown command");
std::stringstream istream (body);
boost::property_tree::read_json (istream, request);
std::string action (request.get<std::string> ("action"));
if (action == "password_enter")
{
password_enter ();
request.erase ("password");
reprocess_body (body, request);
}
else if (action == "password_change")
{
password_change ();
request.erase ("password");
reprocess_body (body, request);
}
else if (action == "wallet_unlock")
{
password_enter ();
request.erase ("password");
reprocess_body (body, request);
}
if (node.config.logging.log_rpc ())
{
BOOST_LOG (node.log) << boost::str (boost::format ("%1% ") % request_id) << body;
}
if (action == "account_balance")
{
account_balance ();
}
else if (action == "account_block_count")
{
account_block_count ();
}
else if (action == "account_count")
{
account_count ();
}
else if (action == "account_create")
{
account_create ();
}
else if (action == "account_get")
{
account_get ();
}
else if (action == "account_history")
{
account_history ();
}
else if (action == "account_info")
{
account_info ();
}
else if (action == "account_key")
{
account_key ();
}
else if (action == "account_list")
{
account_list ();
}
else if (action == "account_move")
{
account_move ();
}
else if (action == "account_remove")
{
account_remove ();
}
else if (action == "account_representative")
{
account_representative ();
}
else if (action == "account_representative_set")
{
account_representative_set ();
}
else if (action == "account_weight")
{
account_weight ();
}
else if (action == "accounts_balances")
{
accounts_balances ();
}
else if (action == "accounts_create")
{
accounts_create ();
}
else if (action == "accounts_frontiers")
{
accounts_frontiers ();
}
else if (action == "accounts_pending")
{
accounts_pending ();
}
else if (action == "available_supply")
{
available_supply ();
}
else if (action == "block")
{
block ();
}
else if (action == "block_confirm")
{
block_confirm ();
}
else if (action == "blocks")
{
blocks ();
}
else if (action == "blocks_info")
{
blocks_info ();
}
else if (action == "block_account")
{
block_account ();
}
else if (action == "block_count")
{
block_count ();
}
else if (action == "block_count_type")
{
block_count_type ();
}
else if (action == "block_create")
{
block_create ();
}
else if (action == "block_hash")
{
block_hash ();
}
else if (action == "successors")
{
chain (true);
}
else if (action == "bootstrap")
{
bootstrap ();
}
else if (action == "bootstrap_any")
{
bootstrap_any ();
}
else if (action == "chain")
{
chain ();
}
else if (action == "delegators")
{
delegators ();
}
else if (action == "delegators_count")
{
delegators_count ();
}
else if (action == "deterministic_key")
{
deterministic_key ();
}
else if (action == "confirmation_history")
{
confirmation_history ();
}
else if (action == "frontiers")
{
frontiers ();
}
else if (action == "frontier_count")
{
account_count ();
}
else if (action == "history")
{
request.put ("head", request.get<std::string> ("hash"));
account_history ();
}
else if (action == "keepalive")
{
keepalive ();
}
else if (action == "key_create")
{
key_create ();
}
else if (action == "key_expand")
{
key_expand ();
}
else if (action == "krai_from_raw")
{
mrai_from_raw (rai::kxrb_ratio);
}
else if (action == "krai_to_raw")
{
mrai_to_raw (rai::kxrb_ratio);
}
else if (action == "ledger")
{
ledger ();
}
else if (action == "mrai_from_raw")
{
mrai_from_raw ();
}
else if (action == "mrai_to_raw")
{
mrai_to_raw ();
}
else if (action == "password_change")
{
// Processed before logging
}
else if (action == "password_enter")
{
// Processed before logging
}
else if (action == "password_valid")
{
password_valid ();
}
else if (action == "payment_begin")
{
payment_begin ();
}
else if (action == "payment_init")
{
payment_init ();
}
else if (action == "payment_end")
{
payment_end ();
}
else if (action == "payment_wait")
{
payment_wait ();
}
else if (action == "peers")
{
peers ();
}
else if (action == "pending")
{
pending ();
}
else if (action == "pending_exists")
{
pending_exists ();
}
else if (action == "process")
{
process ();
}
else if (action == "rai_from_raw")
{
mrai_from_raw (rai::xrb_ratio);
}
else if (action == "rai_to_raw")
{
mrai_to_raw (rai::xrb_ratio);
}
else if (action == "receive")
{
receive ();
}
else if (action == "receive_minimum")
{
receive_minimum ();
}
else if (action == "receive_minimum_set")
{
receive_minimum_set ();
}
else if (action == "representatives")
{
representatives ();
}
else if (action == "representatives_online")
{
representatives_online ();
}
else if (action == "republish")
{
republish ();
}
else if (action == "search_pending")
{
search_pending ();
}
else if (action == "search_pending_all")
{
search_pending_all ();
}
else if (action == "send")
{
send ();
}
else if (action == "stats")
{
stats ();
}
else if (action == "stop")
{
stop ();
}
else if (action == "unchecked")
{
unchecked ();
}
else if (action == "unchecked_clear")
{
unchecked_clear ();
}
else if (action == "unchecked_get")
{
unchecked_get ();
}
else if (action == "unchecked_keys")
{
unchecked_keys ();
}
else if (action == "validate_account_number")
{
validate_account_number ();
}
else if (action == "version")
{
version ();
}
else if (action == "wallet_add")
{
wallet_add ();
}
else if (action == "wallet_add_watch")
{
wallet_add_watch ();
}
// Obsolete
else if (action == "wallet_balance_total")
{
wallet_info ();
}
else if (action == "wallet_balances")
{
wallet_balances ();
}
else if (action == "wallet_change_seed")
{
wallet_change_seed ();
}
else if (action == "wallet_contains")
{
wallet_contains ();
}
else if (action == "wallet_create")
{
wallet_create ();
}
else if (action == "wallet_destroy")
{
wallet_destroy ();
}
else if (action == "wallet_export")
{
wallet_export ();
}
else if (action == "wallet_frontiers")
{
wallet_frontiers ();
}
else if (action == "wallet_info")
{
wallet_info ();
}
else if (action == "wallet_key_valid")
{
wallet_key_valid ();
}
else if (action == "wallet_ledger")
{
wallet_ledger ();
}
else if (action == "wallet_lock")
{
wallet_lock ();
}
else if (action == "wallet_locked")
{
password_valid (true);
}
else if (action == "wallet_pending")
{
wallet_pending ();
}
else if (action == "wallet_representative")
{
wallet_representative ();
}
else if (action == "wallet_representative_set")
{
wallet_representative_set ();
}
else if (action == "wallet_republish")
{
wallet_republish ();
}
else if (action == "wallet_unlock")
{
// Processed before logging
}
else if (action == "wallet_work_get")
{
wallet_work_get ();
}
else if (action == "work_generate")
{
work_generate ();
}
else if (action == "work_cancel")
{
work_cancel ();
}
else if (action == "work_get")
{
work_get ();
}
else if (action == "work_set")
{
work_set ();
}
else if (action == "work_validate")
{
work_validate ();
}
else if (action == "work_peer_add")
{
work_peer_add ();
}
else if (action == "work_peers")
{
work_peers ();
}
else if (action == "work_peers_clear")
{
work_peers_clear ();
}
else
{
error_response (response, "Unknown command");
}
}
}
catch (std::runtime_error const & err)

View file

@ -48,6 +48,7 @@ public:
uint64_t frontier_request_limit;
uint64_t chain_request_limit;
rpc_secure_config secure;
uint8_t max_json_depth;
};
enum class payment_status
{

View file

@ -40,7 +40,7 @@ void rai::wallet_store::seed (rai::raw_key & prv_a, MDB_txn * transaction_a)
rai::wallet_value value (entry_get_raw (transaction_a, rai::wallet_store::seed_special));
rai::raw_key password_l;
wallet_key (password_l, transaction_a);
prv_a.decrypt (value.key, password_l, salt (transaction_a).owords[0]);
prv_a.decrypt (value.key, password_l, salt (transaction_a).owords[seed_iv_index]);
}
void rai::wallet_store::seed_set (MDB_txn * transaction_a, rai::raw_key const & prv_a)
@ -48,7 +48,7 @@ void rai::wallet_store::seed_set (MDB_txn * transaction_a, rai::raw_key const &
rai::raw_key password_l;
wallet_key (password_l, transaction_a);
rai::uint256_union ciphertext;
ciphertext.encrypt (prv_a, password_l, salt (transaction_a).owords[0]);
ciphertext.encrypt (prv_a, password_l, salt (transaction_a).owords[seed_iv_index]);
entry_put_raw (transaction_a, rai::wallet_store::seed_special, rai::wallet_value (ciphertext, 0));
deterministic_clear (transaction_a);
}
@ -126,7 +126,7 @@ bool rai::wallet_store::valid_password (MDB_txn * transaction_a)
rai::raw_key wallet_key_l;
wallet_key (wallet_key_l, transaction_a);
rai::uint256_union check_l;
check_l.encrypt (zero, wallet_key_l, salt (transaction_a).owords[0]);
check_l.encrypt (zero, wallet_key_l, salt (transaction_a).owords[check_iv_index]);
bool ok = check (transaction_a) == check_l;
return ok;
}
@ -143,13 +143,18 @@ bool rai::wallet_store::attempt_password (MDB_txn * transaction_a, std::string c
}
if (!result)
{
if (version (transaction_a) == version_1)
switch (version (transaction_a))
{
upgrade_v1_v2 ();
}
if (version (transaction_a) == version_2)
{
upgrade_v2_v3 ();
case version_1:
upgrade_v1_v2 ();
case version_2:
upgrade_v2_v3 ();
case version_3:
upgrade_v3_v4 ();
case version_4:
break;
default:
assert (false);
}
}
return result;
@ -245,10 +250,6 @@ rai::mdb_val rai::wallet_value::val () const
return rai::mdb_val (sizeof (*this), const_cast<rai::wallet_value *> (this));
}
unsigned const rai::wallet_store::version_1 (1);
unsigned const rai::wallet_store::version_2 (2);
unsigned const rai::wallet_store::version_3 (3);
unsigned const rai::wallet_store::version_current (version_3);
// Wallet version number
rai::uint256_union const rai::wallet_store::version_special (0);
// Random number used to salt private key encryption
@ -264,6 +265,8 @@ rai::uint256_union const rai::wallet_store::seed_special (5);
// Current key index for deterministic keys
rai::uint256_union const rai::wallet_store::deterministic_index_special (6);
int const rai::wallet_store::special_count (7);
size_t const rai::wallet_store::check_iv_index (0);
size_t const rai::wallet_store::seed_iv_index (1);
rai::wallet_store::wallet_store (bool & init_a, rai::kdf & kdf_a, rai::transaction & transaction_a, rai::account representative_a, unsigned fanout_a, std::string const & wallet_a, std::string const & json_a) :
password (0, fanout_a),
@ -357,7 +360,7 @@ environment (transaction_a.environment)
wallet_key_enc.data = encrypted;
wallet_key_mem.value_set (wallet_key_enc);
rai::uint256_union check;
check.encrypt (zero, wallet_key, salt_l.owords[0]);
check.encrypt (zero, wallet_key, salt_l.owords[check_iv_index]);
entry_put_raw (transaction_a, rai::wallet_store::check_special, rai::wallet_value (check, 0));
entry_put_raw (transaction_a, rai::wallet_store::representative_special, rai::wallet_value (representative_a, 0));
rai::raw_key seed;
@ -413,7 +416,7 @@ rai::public_key rai::wallet_store::insert_adhoc (MDB_txn * transaction_a, rai::r
rai::raw_key password_l;
wallet_key (password_l, transaction_a);
rai::uint256_union ciphertext;
ciphertext.encrypt (prv, password_l, salt (transaction_a).owords[0]);
ciphertext.encrypt (prv, password_l, pub.owords[0].number ());
entry_put_raw (transaction_a, pub, rai::wallet_value (ciphertext, 0));
return pub;
}
@ -498,7 +501,7 @@ bool rai::wallet_store::fetch (MDB_txn * transaction_a, rai::public_key const &
// Ad-hoc keys
rai::raw_key password_l;
wallet_key (password_l, transaction_a);
prv.decrypt (value.key, password_l, salt (transaction_a).owords[0]);
prv.decrypt (value.key, password_l, pub.owords[0].number ());
break;
}
default:
@ -691,6 +694,49 @@ void rai::wallet_store::upgrade_v2_v3 ()
version_put (transaction, 3);
}
void rai::wallet_store::upgrade_v3_v4 ()
{
rai::transaction transaction (environment, nullptr, true);
assert (version (transaction) == 3);
version_put (transaction, 4);
assert (valid_password (transaction));
rai::raw_key seed;
rai::wallet_value value (entry_get_raw (transaction, rai::wallet_store::seed_special));
rai::raw_key password_l;
wallet_key (password_l, transaction);
seed.decrypt (value.key, password_l, salt (transaction).owords[0]);
rai::uint256_union ciphertext;
ciphertext.encrypt (seed, password_l, salt (transaction).owords[seed_iv_index]);
entry_put_raw (transaction, rai::wallet_store::seed_special, rai::wallet_value (ciphertext, 0));
for (auto i (begin (transaction)), n (end ()); i != n; ++i)
{
rai::wallet_value value (i->second);
if (!value.key.is_zero ())
{
switch (key_type (i->second))
{
case rai::key_type::adhoc:
{
rai::raw_key key;
if (fetch (transaction, i->first.uint256 (), key))
{
// Key failed to decrypt despite valid password
key.decrypt (value.key, password_l, salt (transaction).owords[0]);
rai::uint256_union new_key_ciphertext;
new_key_ciphertext.encrypt (key, password_l, i->first.uint256 ().owords[0].number ());
rai::wallet_value new_value (new_key_ciphertext, value.work);
mdb_cursor_put (i.cursor, i->first, new_value.val (), MDB_CURRENT);
}
}
case rai::key_type::deterministic:
break;
default:
assert (false);
}
}
}
}
void rai::kdf::phs (rai::raw_key & result_a, std::string const & password_a, rai::uint256_union const & salt_a)
{
std::lock_guard<std::mutex> lock (mutex);

View file

@ -96,12 +96,14 @@ public:
void version_put (MDB_txn *, unsigned);
void upgrade_v1_v2 ();
void upgrade_v2_v3 ();
void upgrade_v3_v4 ();
rai::fan password;
rai::fan wallet_key_mem;
static unsigned const version_1;
static unsigned const version_2;
static unsigned const version_3;
static unsigned const version_current;
static unsigned const version_1 = 1;
static unsigned const version_2 = 2;
static unsigned const version_3 = 3;
static unsigned const version_4 = 4;
unsigned const version_current = version_4;
static rai::uint256_union const version_special;
static rai::uint256_union const wallet_key_special;
static rai::uint256_union const salt_special;
@ -109,6 +111,8 @@ public:
static rai::uint256_union const representative_special;
static rai::uint256_union const seed_special;
static rai::uint256_union const deterministic_index_special;
static size_t const check_iv_index;
static size_t const seed_iv_index;
static int const special_count;
static unsigned const kdf_full_work = 64 * 1024;
static unsigned const kdf_test_work = 8;