bridged__validate_components_for_login, and fixed up some ref passing

pull/29/head
Paul Shapiro 6 years ago
parent 4aaef3ddd9
commit 45b2d42366

@ -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<string> sec_spendKey_string,
optional<string> 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;
}

@ -77,13 +77,13 @@ namespace monero_wallet_utils
struct MnemonicDecodedSeed_RetVals: RetVals_base
{
optional<crypto::secret_key> optl__sec_seed = none;
optional<std::string> optl__sec_seed_string = none;
optional<std::string> optl__mnemonic_string = none;
optional<string> optl__sec_seed_string = none;
optional<string> 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<WalletDescription> 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<string> sec_spendKey_string,
optional<string> sec_seed_string,
cryptonote::network_type nettype,
WalletComponentsValidationResults &retVals
);
}

@ -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<string>("address_string"),
json_root.get<string>("sec_viewKey_string"),
json_root.get<string>("sec_spendKey_string"),
json_root.get<string>("seed_string"),
nettype_from_string(json_root.get<string>("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)

@ -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__

@ -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<string> err_string = ret_tree.get_optional<string>(ret_json_key__any__err_msg());
if (err_string != none) {
BOOST_REQUIRE_MESSAGE(false, *err_string);
}
optional<bool> isValid = ret_tree.get_optional<bool>(ret_json_key__isValid());
BOOST_REQUIRE(isValid == true);
cout << "bridged: validate_components_for_login: isValid: " << isValid << endl;
optional<bool> isInViewOnlyMode = ret_tree.get_optional<bool>(ret_json_key__isInViewOnlyMode());
BOOST_REQUIRE(isInViewOnlyMode == false);
cout << "bridged: validate_components_for_login: isInViewOnlyMode: " << isInViewOnlyMode << endl;
optional<string> pub_viewKey_string = ret_tree.get_optional<string>(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<string> pub_spendKey_string = ret_tree.get_optional<string>(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)

Loading…
Cancel
Save