aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/common/pod-class.h6
-rw-r--r--src/crypto/crypto.cpp19
-rw-r--r--src/crypto/crypto.h8
-rw-r--r--src/crypto/electrum-words.cpp10
-rw-r--r--src/cryptonote_core/account.cpp13
-rw-r--r--src/cryptonote_core/account.h2
-rw-r--r--src/simplewallet/simplewallet.cpp10
-rw-r--r--src/wallet/wallet2.cpp5
-rw-r--r--src/wallet/wallet2.h2
9 files changed, 56 insertions, 19 deletions
diff --git a/src/common/pod-class.h b/src/common/pod-class.h
index c07edb208..10d680484 100644
--- a/src/common/pod-class.h
+++ b/src/common/pod-class.h
@@ -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
diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp
index 31fc31d5b..98a17a3e4 100644
--- a/src/crypto/crypto.cpp
+++ b/src/crypto/crypto.cpp
@@ -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) {
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index 61641fbcf..024713df1 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -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.
diff --git a/src/crypto/electrum-words.cpp b/src/crypto/electrum-words.cpp
index b4580e01f..048aa403f 100644
--- a/src/crypto/electrum-words.cpp
+++ b/src/crypto/electrum-words.cpp
@@ -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;
diff --git a/src/cryptonote_core/account.cpp b/src/cryptonote_core/account.cpp
index 9a96de2f0..bd47c8ba4 100644
--- a/src/cryptonote_core/account.cpp
+++ b/src/cryptonote_core/account.cpp
@@ -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
diff --git a/src/cryptonote_core/account.h b/src/cryptonote_core/account.h
index 745da0897..f07d4dd79 100644
--- a/src/cryptonote_core/account.h
+++ b/src/cryptonote_core/account.h
@@ -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();
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 3cea02bf1..261c150e9 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -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;
}
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index b0c341615..59e1b0fa4 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -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)
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 85ed344c3..f54045b3a 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -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;}