mirror of
https://github.com/monero-project/monero.git
synced 2024-10-01 11:49:47 -04:00
builds, but doesn't link. other than that, electrum-style recovery implemented (but not tested\!)
This commit is contained in:
parent
8661f9a970
commit
d22e458c6c
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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;}
|
||||||
|
Loading…
Reference in New Issue
Block a user