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
// FIXME: Why is this ifdef needed? Hopefully making it struct won't break things.
/*
#if defined(_MSC_VER)
#define POD_CLASS struct
#else
#define POD_CLASS class
#endif
*/
#define POD_CLASS struct

View file

@ -68,12 +68,27 @@ namespace crypto {
* 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);
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_p3_tobytes(&pub, &point);
return rng;
}
bool crypto_ops::check_key(const public_key &key) {

View file

@ -62,8 +62,8 @@ namespace crypto {
void operator=(const crypto_ops &);
~crypto_ops();
static void generate_keys(public_key &, secret_key &);
friend 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 secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover);
static 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 &);
@ -102,8 +102,8 @@ namespace crypto {
/* Generate a new key pair
*/
inline void generate_keys(public_key &pub, secret_key &sec) {
crypto_ops::generate_keys(pub, sec);
inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) {
return crypto_ops::generate_keys(pub, sec, recovery_key, recover);
}
/* 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
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 w1, w2, w3;
@ -55,12 +55,12 @@ namespace crypto
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)
{
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;
@ -78,13 +78,13 @@ namespace crypto
if (sizeof(src.data) % 4 != 0) return false;
// 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 val;
memcpy(val, src, 4);
memcpy(&val, &src.data, 4);
w1 = val % n;
w2 = ((val / n) + w1) % n;

View file

@ -10,6 +10,7 @@
#include "account.h"
#include "warnings.h"
#include "crypto/crypto.h"
#include "crypto/blake256.h"
#include "cryptonote_core/cryptonote_basic_impl.h"
#include "cryptonote_core/cryptonote_format_utils.h"
using namespace std;
@ -29,11 +30,17 @@ DISABLE_VS_WARNINGS(4244 4345)
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);
generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_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);
// 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);
return first;
}
//-----------------------------------------------------------------
const account_keys& account_base::get_keys() const

View file

@ -31,7 +31,7 @@ namespace cryptonote
{
public:
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;
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->callback(this);
crypto::secret_key recovery_val;
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);
}
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);
// convert rng value to electrum-style word list
std::string electrum_words;
crypto::ElectrumWords::bytes_to_words(recovery_val, electrum_words);
success_msg_writer() <<
"**********************************************************************\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" <<
"current session's state. Otherwise, you will possibly need to synchronize \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;
}

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);
}
//----------------------------------------------------------------------------------------------------
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();
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_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;
@ -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");
store();
return retval;
}
//----------------------------------------------------------------------------------------------------
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()
};
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 store();
cryptonote::account_base& get_account(){return m_account;}