From 45b2d42366cc5a068e917947dd8f69f44bacb638 Mon Sep 17 00:00:00 2001 From: Paul Shapiro Date: Sat, 18 Aug 2018 18:49:20 -0400 Subject: [PATCH] bridged__validate_components_for_login, and fixed up some ref passing --- src/monero_wallet_utils.cpp | 111 ++++++++++++++++++------------------ src/monero_wallet_utils.hpp | 32 +++++------ src/serial_bridge_index.cpp | 33 ++++++++++- src/serial_bridge_index.hpp | 6 +- test/test_all.cpp | 37 +++++++++++- 5 files changed, 141 insertions(+), 78 deletions(-) diff --git a/src/monero_wallet_utils.cpp b/src/monero_wallet_utils.cpp index 1315657..190d957 100644 --- a/src/monero_wallet_utils.cpp +++ b/src/monero_wallet_utils.cpp @@ -92,7 +92,7 @@ bool monero_wallet_utils::bytes_to_words( } // bool monero_wallet_utils::new_wallet( - std::string mnemonic_language, + const string &mnemonic_language, WalletDescriptionRetVals &retVals, cryptonote::network_type nettype ) { @@ -133,8 +133,8 @@ const uint32_t stable_32B_seed_mnemonic_word_count = 25; const uint32_t legacy_16B_seed_mnemonic_word_count = 13; bool monero_wallet_utils::decoded_seed( - std::string mnemonic_string, - std::string mnemonic_language, + string mnemonic_string, + string mnemonic_language, MnemonicDecodedSeed_RetVals &retVals ) { retVals = {}; @@ -235,8 +235,8 @@ SeedDecodedMnemonic_RetVals monero_wallet_utils::mnemonic_string_from_seed_hex_s } // bool monero_wallet_utils::wallet_with( - std::string mnemonic_string, - std::string mnemonic_language, + const string &mnemonic_string, + const string &mnemonic_language, WalletDescriptionRetVals &retVals, cryptonote::network_type nettype ) { @@ -272,34 +272,37 @@ bool monero_wallet_utils::wallet_with( return true; } -bool monero_wallet_utils::validate_wallet_components_with( - const WalletComponentsToValidate &inputs, - WalletComponentsValidationResults &outputs -) -{ // TODO: how can the err_strings be prepared for localization? - outputs = {}; +bool monero_wallet_utils::validate_wallet_components_with( // returns !did_error + const string &address_string, + const string &sec_viewKey_string, + optional sec_spendKey_string, + optional sec_seed_string, + cryptonote::network_type nettype, + WalletComponentsValidationResults &retVals +) { // TODO: how can the err_strings be prepared for localization? + retVals = {}; bool r = false; // // Address cryptonote::address_parse_info decoded_address_info; r = cryptonote::get_account_address_from_str( decoded_address_info, - inputs.nettype, - inputs.address_string + nettype, + address_string ); if (r == false) { - outputs.did_error = true; - outputs.err_string = "Invalid address"; + retVals.did_error = true; + retVals.err_string = "Invalid address"; // return false; } // // View key: crypto::secret_key sec_viewKey; - r = string_tools::hex_to_pod(inputs.sec_viewKey_string, sec_viewKey); + r = string_tools::hex_to_pod(sec_viewKey_string, sec_viewKey); if (r == false) { - outputs.did_error = true; - outputs.err_string = "Invalid view key"; + retVals.did_error = true; + retVals.err_string = "Invalid view key"; // return false; } @@ -307,29 +310,29 @@ bool monero_wallet_utils::validate_wallet_components_with( crypto::public_key expected_pub_viewKey; r = crypto::secret_key_to_public_key(sec_viewKey, expected_pub_viewKey); if (r == false) { - outputs.did_error = true; - outputs.err_string = "Invalid view key"; + retVals.did_error = true; + retVals.err_string = "Invalid view key"; // return false; } if (decoded_address_info.address.m_view_public_key != expected_pub_viewKey) { - outputs.did_error = true; - outputs.err_string = "View key does not match address"; + retVals.did_error = true; + retVals.err_string = "View key does not match address"; // return false; } // // View-only vs spend-key/seed - outputs.isInViewOnlyMode = true; // setting the ground state + retVals.isInViewOnlyMode = true; // setting the ground state // crypto::secret_key sec_spendKey; // may be initialized - if (inputs.optl__sec_spendKey_string) { + if (sec_spendKey_string != none) { // First check if spend key content actually exists before passing to valid_sec_key_from - so that a spend key decode error can be treated as a failure instead of detecting empty spend keys too - if ((*inputs.optl__sec_spendKey_string).empty() == false) { - r = string_tools::hex_to_pod(*inputs.optl__sec_spendKey_string, sec_spendKey); + if ((*sec_spendKey_string).empty() == false) { + r = string_tools::hex_to_pod(*sec_spendKey_string, sec_spendKey); if (r == false) { // this is an actual parse error exit condition - outputs.did_error = true; - outputs.err_string = "Invalid spend key"; + retVals.did_error = true; + retVals.err_string = "Invalid spend key"; // return false; } @@ -337,41 +340,41 @@ bool monero_wallet_utils::validate_wallet_components_with( crypto::public_key expected_pub_spendKey; r = crypto::secret_key_to_public_key(sec_spendKey, expected_pub_spendKey); if (r == false) { - outputs.did_error = true; - outputs.err_string = "Invalid spend key"; + retVals.did_error = true; + retVals.err_string = "Invalid spend key"; // return false; } if (decoded_address_info.address.m_spend_public_key != expected_pub_spendKey) { - outputs.did_error = true; - outputs.err_string = "Spend key does not match address"; + retVals.did_error = true; + retVals.err_string = "Spend key does not match address"; // return false; } - outputs.isInViewOnlyMode = false; + retVals.isInViewOnlyMode = false; } } - if (inputs.optl__sec_seed_string) { - if ((*inputs.optl__sec_seed_string).empty() == false) { - unsigned long sec_seed_string_length = (*inputs.optl__sec_seed_string).length(); + if (sec_seed_string != none) { + if ((*sec_seed_string).empty() == false) { + unsigned long sec_seed_string_length = (*sec_seed_string).length(); crypto::secret_key sec_seed; bool from_legacy16B_lw_seed = false; if (sec_seed_string_length == sec_seed_hex_string_length) { // normal seed from_legacy16B_lw_seed = false; // to be clear - bool r = string_tools::hex_to_pod((*inputs.optl__sec_seed_string), sec_seed); + bool r = string_tools::hex_to_pod((*sec_seed_string), sec_seed); if (!r) { - outputs.did_error = true; - outputs.err_string = "Invalid seed"; + retVals.did_error = true; + retVals.err_string = "Invalid seed"; // return false; } } else if (sec_seed_string_length == legacy16B__sec_seed_hex_string_length) { from_legacy16B_lw_seed = true; legacy16B_secret_key legacy16B_sec_seed; - bool r = string_tools::hex_to_pod((*inputs.optl__sec_seed_string), legacy16B_sec_seed); + bool r = string_tools::hex_to_pod((*sec_seed_string), legacy16B_sec_seed); if (!r) { - outputs.did_error = true; - outputs.err_string = "Invalid seed"; + retVals.did_error = true; + retVals.err_string = "Invalid seed"; // return false; } @@ -382,36 +385,36 @@ bool monero_wallet_utils::validate_wallet_components_with( const cryptonote::account_keys& expected_account_keys = expected_account.get_keys(); // TODO: assert sec_spendKey initialized? if (expected_account_keys.m_view_secret_key != sec_viewKey) { - outputs.did_error = true; - outputs.err_string = "Private view key does not match generated key"; + retVals.did_error = true; + retVals.err_string = "Private view key does not match generated key"; // return false; } if (expected_account_keys.m_spend_secret_key != sec_spendKey) { - outputs.did_error = true; - outputs.err_string = "Private spend key does not match generated key"; + retVals.did_error = true; + retVals.err_string = "Private spend key does not match generated key"; // return false; } if (expected_account_keys.m_account_address.m_view_public_key != decoded_address_info.address.m_view_public_key) { - outputs.did_error = true; - outputs.err_string = "Public view key does not match generated key"; + retVals.did_error = true; + retVals.err_string = "Public view key does not match generated key"; // return false; } if (expected_account_keys.m_account_address.m_spend_public_key != decoded_address_info.address.m_spend_public_key) { - outputs.did_error = true; - outputs.err_string = "Public spend key does not match generated key"; + retVals.did_error = true; + retVals.err_string = "Public spend key does not match generated key"; // return false; } // - outputs.isInViewOnlyMode = false; // TODO: should this ensure that sec_spendKey is not nil? spendKey should always be available if the seed is… + retVals.isInViewOnlyMode = false; // TODO: should this ensure that sec_spendKey is not nil? spendKey should always be available if the seed is… } } - outputs.pub_viewKey_string = string_tools::pod_to_hex(decoded_address_info.address.m_view_public_key); - outputs.pub_spendKey_string = string_tools::pod_to_hex(decoded_address_info.address.m_spend_public_key); - outputs.isValid = true; + retVals.pub_viewKey_string = string_tools::pod_to_hex(decoded_address_info.address.m_view_public_key); + retVals.pub_spendKey_string = string_tools::pod_to_hex(decoded_address_info.address.m_spend_public_key); + retVals.isValid = true; // return true; } diff --git a/src/monero_wallet_utils.hpp b/src/monero_wallet_utils.hpp index 0a0f0b9..5d59629 100644 --- a/src/monero_wallet_utils.hpp +++ b/src/monero_wallet_utils.hpp @@ -77,13 +77,13 @@ namespace monero_wallet_utils struct MnemonicDecodedSeed_RetVals: RetVals_base { optional optl__sec_seed = none; - optional optl__sec_seed_string = none; - optional optl__mnemonic_string = none; + optional optl__sec_seed_string = none; + optional optl__mnemonic_string = none; bool from_legacy16B_lw_seed = false; }; bool decoded_seed( string mnemonic_string, - string mnemonic_language_string, + string mnemonic_language, // MnemonicDecodedSeed_RetVals &retVals ); @@ -116,35 +116,31 @@ namespace monero_wallet_utils boost::optional optl__desc = boost::none; }; bool new_wallet( - std::string mnemonic_language, + const string &mnemonic_language, WalletDescriptionRetVals &retVals, cryptonote::network_type nettype = cryptonote::MAINNET ); bool wallet_with( - std::string mnemonic_string, - std::string mnemonic_language, + const string &mnemonic_string, + const string &mnemonic_language, WalletDescriptionRetVals &retVals, cryptonote::network_type nettype = cryptonote::MAINNET ); // - struct WalletComponentsToValidate - { - std::string address_string; // Required - std::string sec_viewKey_string; // Required - const std::string *optl__sec_spendKey_string; - const std::string *optl__sec_seed_string; - cryptonote::network_type nettype; - }; struct WalletComponentsValidationResults: RetVals_base { bool isValid; // this will naturally remain false if did_error=true - std::string pub_spendKey_string; - std::string pub_viewKey_string; + string pub_spendKey_string; + string pub_viewKey_string; bool isInViewOnlyMode; // !sec_seed && !sec_spendKey }; bool validate_wallet_components_with( // returns !did_error - const WalletComponentsToValidate &inputs, - WalletComponentsValidationResults &outputs + const string &address_string, + const string &sec_viewKey_string, + optional sec_spendKey_string, + optional sec_seed_string, + cryptonote::network_type nettype, + WalletComponentsValidationResults &retVals ); } diff --git a/src/serial_bridge_index.cpp b/src/serial_bridge_index.cpp index cce0527..f528886 100644 --- a/src/serial_bridge_index.cpp +++ b/src/serial_bridge_index.cpp @@ -316,9 +316,38 @@ string serial_bridge::seed_and_keys_from_mnemonic(const string &args_string) // return ret_ss.str(); } -string serial_bridge::verified_components_for_login(const string &args_string) +string serial_bridge::validate_components_for_login(const string &args_string) { - + boost::property_tree::ptree json_root; + if (!parsed_json_root(args_string, json_root)) { + // it will already have thrown an exception + return error_ret_json_from_message("Invalid JSON"); + } + monero_wallet_utils::WalletComponentsValidationResults retVals; + bool r = monero_wallet_utils::validate_wallet_components_with( // returns !did_error + json_root.get("address_string"), + json_root.get("sec_viewKey_string"), + json_root.get("sec_spendKey_string"), + json_root.get("seed_string"), + nettype_from_string(json_root.get("nettype_string")), + retVals + ); + bool did_error = retVals.did_error; + if (!r) { + THROW_WALLET_EXCEPTION_IF(!did_error, error::wallet_internal_error, "Illegal fail flag but !did_error"); + return error_ret_json_from_message(*retVals.err_string); + } + THROW_WALLET_EXCEPTION_IF(did_error, error::wallet_internal_error, "Illegal success flag but did_error"); + // + boost::property_tree::ptree root; + root.put(ret_json_key__isValid(), retVals.isValid); + root.put(ret_json_key__isInViewOnlyMode(), retVals.isInViewOnlyMode); + root.put(ret_json_key__pub_viewKey_string(), std::move(retVals.pub_viewKey_string)); + root.put(ret_json_key__pub_spendKey_string(), std::move(retVals.pub_spendKey_string)); + stringstream ret_ss; + boost::property_tree::write_json(ret_ss, root); + // + return ret_ss.str(); } // string serial_bridge::estimate_rct_size(const string &args_string) diff --git a/src/serial_bridge_index.hpp b/src/serial_bridge_index.hpp index 2952bc1..084857c 100644 --- a/src/serial_bridge_index.hpp +++ b/src/serial_bridge_index.hpp @@ -55,7 +55,7 @@ namespace serial_bridge string newly_created_wallet(const string &args_string); // TODO: maybe expose random scalar as arg string mnemonic_from_seed(const string &args_string); string seed_and_keys_from_mnemonic(const string &args_string); - string verified_components_for_login(const string &args_string); + string validate_components_for_login(const string &args_string); // string estimate_rct_size(const string &args_string); string calculate_fee(const string &args_string); @@ -86,8 +86,8 @@ namespace serial_bridge static inline string ret_json_key__pub_spendKey_string() { return "pub_spendKey_string"; } static inline string ret_json_key__sec_viewKey_string() { return "sec_viewKey_string"; } static inline string ret_json_key__sec_spendKey_string() { return "sec_spendKey_string"; } - - + static inline string ret_json_key__isValid() { return "isValid"; } + static inline string ret_json_key__isInViewOnlyMode() { return "isInViewOnlyMode"; } // JSON keys - Args // TODO: // static inline string args_json_key__ diff --git a/test/test_all.cpp b/test/test_all.cpp index a7965b5..f8af2df 100644 --- a/test/test_all.cpp +++ b/test/test_all.cpp @@ -731,8 +731,43 @@ BOOST_AUTO_TEST_CASE(bridged__seed_and_keys_from_mnemonic) BOOST_REQUIRE((*sec_spendKey_string).size() > 0); cout << "bridged: seed_and_keys_from_mnemonic: sec_spendKey_string: " << *sec_spendKey_string << endl; } -BOOST_AUTO_TEST_CASE(bridged__verified_components_for_login) + +BOOST_AUTO_TEST_CASE(bridged__validate_components_for_login) { + using namespace serial_bridge; + // + boost::property_tree::ptree root; + root.put("address_string", "43zxvpcj5Xv9SEkNXbMCG7LPQStHMpFCQCmkmR4u5nzjWwq5Xkv5VmGgYEsHXg4ja2FGRD5wMWbBVMijDTqmmVqm93wHGkg"); + root.put("sec_viewKey_string", "7bea1907940afdd480eff7c4bcadb478a0fbb626df9e3ed74ae801e18f53e104"); + root.put("sec_spendKey_string", "4e6d43cd03812b803c6f3206689f5fcc910005fc7e91d50d79b0776dbefcd803"); + root.put("seed_string", "9c973aa296b79bbf452781dd3d32ad7f"); + root.put("nettype_string", string_from_nettype(MAINNET)); + // + stringstream args_ss; + boost::property_tree::write_json(args_ss, root); + auto ret_string = serial_bridge::validate_components_for_login(args_ss.str()); + stringstream ret_stream; + ret_stream << ret_string; + boost::property_tree::ptree ret_tree; + boost::property_tree::read_json(ret_stream, ret_tree); + optional err_string = ret_tree.get_optional(ret_json_key__any__err_msg()); + if (err_string != none) { + BOOST_REQUIRE_MESSAGE(false, *err_string); + } + optional isValid = ret_tree.get_optional(ret_json_key__isValid()); + BOOST_REQUIRE(isValid == true); + cout << "bridged: validate_components_for_login: isValid: " << isValid << endl; + optional isInViewOnlyMode = ret_tree.get_optional(ret_json_key__isInViewOnlyMode()); + BOOST_REQUIRE(isInViewOnlyMode == false); + cout << "bridged: validate_components_for_login: isInViewOnlyMode: " << isInViewOnlyMode << endl; + optional pub_viewKey_string = ret_tree.get_optional(ret_json_key__pub_viewKey_string()); + BOOST_REQUIRE(pub_viewKey_string != none); + BOOST_REQUIRE((*pub_viewKey_string).size() > 0); + cout << "bridged: validate_components_for_login: pub_viewKey_string: " << *pub_viewKey_string << endl; + optional pub_spendKey_string = ret_tree.get_optional(ret_json_key__pub_spendKey_string()); + BOOST_REQUIRE(pub_spendKey_string != none); + BOOST_REQUIRE((*pub_spendKey_string).size() > 0); + cout << "bridged: validate_components_for_login: pub_spendKey_string: " << *pub_spendKey_string << endl; } BOOST_AUTO_TEST_CASE(bridged__estimate_rct_size)