builds, but doesn't link. other than that, electrum-style recovery implemented (but not tested\!)

This commit is contained in:
Thomas Winget 2014-06-06 14:18:11 -04:00
parent 8661f9a970
commit d22e458c6c
9 changed files with 56 additions and 19 deletions

View File

@ -4,8 +4,14 @@
#pragma once #pragma once
// FIXME: Why is this ifdef needed? Hopefully making it struct won't break things.
/*
#if defined(_MSC_VER) #if defined(_MSC_VER)
#define POD_CLASS struct #define POD_CLASS struct
#else #else
#define POD_CLASS class #define POD_CLASS class
#endif #endif
*/
#define POD_CLASS struct

View File

@ -68,12 +68,27 @@ namespace crypto {
* TODO: allow specifiying random value (for wallet recovery) * TODO: allow specifiying random value (for wallet recovery)
* *
*/ */
void crypto_ops::generate_keys(public_key &pub, secret_key &sec) { secret_key crypto_ops::generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover) {
lock_guard<mutex> lock(random_lock); lock_guard<mutex> lock(random_lock);
ge_p3 point; ge_p3 point;
random_scalar(sec);
secret_key rng;
if (recover)
{
rng = recovery_key;
}
else
{
random_scalar(rng);
}
sec = rng;
sc_reduce32(&sec); // reduce in case second round of keys (sendkeys)
ge_scalarmult_base(&point, &sec); ge_scalarmult_base(&point, &sec);
ge_p3_tobytes(&pub, &point); ge_p3_tobytes(&pub, &point);
return rng;
} }
bool crypto_ops::check_key(const public_key &key) { bool crypto_ops::check_key(const public_key &key) {

View File

@ -62,8 +62,8 @@ namespace crypto {
void operator=(const crypto_ops &); void operator=(const crypto_ops &);
~crypto_ops(); ~crypto_ops();
static void generate_keys(public_key &, secret_key &); static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false);
friend void generate_keys(public_key &, secret_key &); friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover);
static bool check_key(const public_key &); static bool check_key(const public_key &);
friend bool check_key(const public_key &); friend bool check_key(const public_key &);
static bool secret_key_to_public_key(const secret_key &, public_key &); static bool secret_key_to_public_key(const secret_key &, public_key &);
@ -102,8 +102,8 @@ namespace crypto {
/* Generate a new key pair /* Generate a new key pair
*/ */
inline void generate_keys(public_key &pub, secret_key &sec) { inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) {
crypto_ops::generate_keys(pub, sec); return crypto_ops::generate_keys(pub, sec, recovery_key, recover);
} }
/* Check a public key. Returns true if it is valid, false otherwise. /* Check a public key. Returns true if it is valid, false otherwise.

View File

@ -36,7 +36,7 @@ namespace crypto
// error on non-compliant word list // error on non-compliant word list
if (wlist.size() != 12 && wlist.size() != 24) return false; if (wlist.size() != 12 && wlist.size() != 24) return false;
for (int i=0; i < wlist.size() / 3; i++) for (unsigned int i=0; i < wlist.size() / 3; i++)
{ {
uint32_t val; uint32_t val;
uint32_t w1, w2, w3; uint32_t w1, w2, w3;
@ -55,12 +55,12 @@ namespace crypto
val = w1 + n * ((w2 - w1) % n) + n * n * ((w3 - w2) % n); val = w1 + n * ((w2 - w1) % n) + n * n * ((w3 - w2) % n);
memcpy(dst.data + i * 4, val, 4); // copy 4 bytes to position memcpy(&dst.data + i * 4, &val, 4); // copy 4 bytes to position
} }
if (wlist.size() == 12) if (wlist.size() == 12)
{ {
memcpy(dst.data, dst.data + 16, 16); // if electrum 12-word seed, duplicate memcpy(&dst.data, &dst.data + 16, 16); // if electrum 12-word seed, duplicate
} }
return true; return true;
@ -78,13 +78,13 @@ namespace crypto
if (sizeof(src.data) % 4 != 0) return false; if (sizeof(src.data) % 4 != 0) return false;
// 8 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626 // 8 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626
for (int i=0; i < sizeof(src.data)/4; i++, words += ' ') for (unsigned int i=0; i < sizeof(src.data)/4; i++, words += ' ')
{ {
uint32_t w1, w2, w3; uint32_t w1, w2, w3;
uint32_t val; uint32_t val;
memcpy(val, src, 4); memcpy(&val, &src.data, 4);
w1 = val % n; w1 = val % n;
w2 = ((val / n) + w1) % n; w2 = ((val / n) + w1) % n;

View File

@ -10,6 +10,7 @@
#include "account.h" #include "account.h"
#include "warnings.h" #include "warnings.h"
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "crypto/blake256.h"
#include "cryptonote_core/cryptonote_basic_impl.h" #include "cryptonote_core/cryptonote_basic_impl.h"
#include "cryptonote_core/cryptonote_format_utils.h" #include "cryptonote_core/cryptonote_format_utils.h"
using namespace std; using namespace std;
@ -29,11 +30,17 @@ DISABLE_VS_WARNINGS(4244 4345)
m_keys = account_keys(); m_keys = account_keys();
} }
//----------------------------------------------------------------- //-----------------------------------------------------------------
void account_base::generate(const crypto::secret_key& recovery_key, bool recover) crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover)
{ {
generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key); crypto::secret_key first = generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key, recovery_key, recover);
generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key);
// rng for generating second set of keys is hash of first rng. means only one set of electrum-style words needed for recovery
crypto::secret_key second;
blake256_hash((uint8_t *)&second, (uint8_t *)&first, sizeof(crypto::secret_key));
generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key, second, true);
m_creation_timestamp = time(NULL); m_creation_timestamp = time(NULL);
return first;
} }
//----------------------------------------------------------------- //-----------------------------------------------------------------
const account_keys& account_base::get_keys() const const account_keys& account_base::get_keys() const

View File

@ -31,7 +31,7 @@ namespace cryptonote
{ {
public: public:
account_base(); account_base();
void generate(const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false); crypto::secret_key generate(const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false);
const account_keys& get_keys() const; const account_keys& get_keys() const;
std::string get_public_address_str(); std::string get_public_address_str();

View File

@ -360,9 +360,11 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
m_wallet.reset(new tools::wallet2()); m_wallet.reset(new tools::wallet2());
m_wallet->callback(this); m_wallet->callback(this);
crypto::secret_key recovery_val;
try try
{ {
m_wallet->generate(wallet_file, password, recovery_key, recover); recovery_val = m_wallet->generate(wallet_file, password, recovery_key, recover);
message_writer(epee::log_space::console_color_white, true) << "Generated new wallet: " << m_wallet->get_account().get_public_address_str() << std::endl << "view key: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key); message_writer(epee::log_space::console_color_white, true) << "Generated new wallet: " << m_wallet->get_account().get_public_address_str() << std::endl << "view key: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key);
} }
catch (const std::exception& e) catch (const std::exception& e)
@ -373,6 +375,10 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
m_wallet->init(m_daemon_address); m_wallet->init(m_daemon_address);
// convert rng value to electrum-style word list
std::string electrum_words;
crypto::ElectrumWords::bytes_to_words(recovery_val, electrum_words);
success_msg_writer() << success_msg_writer() <<
"**********************************************************************\n" << "**********************************************************************\n" <<
"Your wallet has been generated.\n" << "Your wallet has been generated.\n" <<
@ -381,6 +387,8 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
"Always use \"exit\" command when closing simplewallet to save\n" << "Always use \"exit\" command when closing simplewallet to save\n" <<
"current session's state. Otherwise, you will possibly need to synchronize \n" << "current session's state. Otherwise, you will possibly need to synchronize \n" <<
"your wallet again. Your wallet key is NOT under risk anyway.\n" << "your wallet again. Your wallet key is NOT under risk anyway.\n" <<
"\nYour wallet can be recovered using the following electrum-style word list:\n" <<
electrum_words << "\n" <<
"**********************************************************************"; "**********************************************************************";
return true; return true;
} }

View File

@ -436,7 +436,7 @@ void wallet2::load_keys(const std::string& keys_file_name, const std::string& pa
THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password); THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password);
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
void wallet2::generate(const std::string& wallet_, const std::string& password, const crypto::secret_key& recovery_param, bool recover) crypto::secret_key wallet2::generate(const std::string& wallet_, const std::string& password, const crypto::secret_key& recovery_param, bool recover)
{ {
clear(); clear();
prepare_file_names(wallet_); prepare_file_names(wallet_);
@ -445,7 +445,7 @@ void wallet2::generate(const std::string& wallet_, const std::string& password,
THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file); THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file);
THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file); THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file);
m_account.generate(recovery_param, recover); crypto::secret_key retval = m_account.generate(recovery_param, recover);
m_account_public_address = m_account.get_keys().m_account_address; m_account_public_address = m_account.get_keys().m_account_address;
@ -456,6 +456,7 @@ void wallet2::generate(const std::string& wallet_, const std::string& password,
if(!r) LOG_PRINT_RED_L0("String with address text not saved"); if(!r) LOG_PRINT_RED_L0("String with address text not saved");
store(); store();
return retval;
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
void wallet2::wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exists) void wallet2::wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exists)

View File

@ -97,7 +97,7 @@ namespace tools
END_SERIALIZE() END_SERIALIZE()
}; };
void generate(const std::string& wallet, const std::string& password, const crypto::secret_key& recovery_param = crypto::secret_key(), bool recover = false); crypto::secret_key generate(const std::string& wallet, const std::string& password, const crypto::secret_key& recovery_param = crypto::secret_key(), bool recover = false);
void load(const std::string& wallet, const std::string& password); void load(const std::string& wallet, const std::string& password);
void store(); void store();
cryptonote::account_base& get_account(){return m_account;} cryptonote::account_base& get_account(){return m_account;}