Electroneum
Loading...
Searching...
No Matches
account.cpp
Go to the documentation of this file.
1// Copyrights(c) 2017-2021, The Electroneum Project
2// Copyrights(c) 2014-2019, The Monero Project
3//
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without modification, are
7// permitted provided that the following conditions are met:
8//
9// 1. Redistributions of source code must retain the above copyright notice, this list of
10// conditions and the following disclaimer.
11//
12// 2. Redistributions in binary form must reproduce the above copyright notice, this list
13// of conditions and the following disclaimer in the documentation and/or other
14// materials provided with the distribution.
15//
16// 3. Neither the name of the copyright holder nor the names of its contributors may be
17// used to endorse or promote products derived from this software without specific
18// prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31
32#include <fstream>
33
34#include "include_base_utils.h"
35#include "account.h"
36#include "warnings.h"
37#include "crypto/crypto.h"
38extern "C"
39{
40#include "crypto/keccak.h"
41}
44
45#undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
46#define ELECTRONEUM_DEFAULT_LOG_CATEGORY "account"
47
48#define KEYS_ENCRYPTION_SALT 'k'
49
50
51using namespace std;
52
53DISABLE_VS_WARNINGS(4244 4345)
54
55 namespace cryptonote
56{
57
58 //-----------------------------------------------------------------
60 return *m_device;
61 }
62 //-----------------------------------------------------------------
64 m_device = &hwdev;
65 MCDEBUG("device", "account_keys::set_device device type: "<<typeid(hwdev).name());
66 }
67 //-----------------------------------------------------------------
68 static void derive_key(const crypto::chacha_key &base_key, crypto::chacha_key &key)
69 {
70 static_assert(sizeof(base_key) == sizeof(crypto::hash), "chacha key and hash should be the same size");
71 epee::mlocked<tools::scrubbed_arr<char, sizeof(base_key)+1>> data;
72 memcpy(data.data(), &base_key, sizeof(base_key));
73 data[sizeof(base_key)] = KEYS_ENCRYPTION_SALT;
74 crypto::generate_chacha_key(data.data(), sizeof(data), key, 1);
75 }
76 //-----------------------------------------------------------------
77 static epee::wipeable_string get_key_stream(const crypto::chacha_key &base_key, const crypto::chacha_iv &iv, size_t bytes)
78 {
79 // derive a new key
80 crypto::chacha_key key;
81 derive_key(base_key, key);
82
83 // chacha
84 epee::wipeable_string buffer0(std::string(bytes, '\0'));
85 epee::wipeable_string buffer1 = buffer0;
86 crypto::chacha20(buffer0.data(), buffer0.size(), key, iv, buffer1.data());
87 return buffer1;
88 }
89 //-----------------------------------------------------------------
90 void account_keys::xor_with_key_stream(const crypto::chacha_key &key)
91 {
92 // encrypt a large enough byte stream with chacha20
93 epee::wipeable_string key_stream = get_key_stream(key, m_encryption_iv, sizeof(crypto::secret_key) * (2 + m_multisig_keys.size()));
94 const char *ptr = key_stream.data();
95 for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
96 m_spend_secret_key.data[i] ^= *ptr++;
97 for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
98 m_view_secret_key.data[i] ^= *ptr++;
99 for (crypto::secret_key &k: m_multisig_keys)
100 {
101 for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
102 k.data[i] ^= *ptr++;
103 }
104 }
105 //-----------------------------------------------------------------
106 void account_keys::encrypt(const crypto::chacha_key &key)
107 {
109 xor_with_key_stream(key);
110 }
111 //-----------------------------------------------------------------
112 void account_keys::decrypt(const crypto::chacha_key &key)
113 {
114 xor_with_key_stream(key);
115 }
116 //-----------------------------------------------------------------
117 void account_keys::encrypt_viewkey(const crypto::chacha_key &key)
118 {
119 // encrypt a large enough byte stream with chacha20
120 epee::wipeable_string key_stream = get_key_stream(key, m_encryption_iv, sizeof(crypto::secret_key) * 2);
121 const char *ptr = key_stream.data();
122 ptr += sizeof(crypto::secret_key);
123 for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
124 m_view_secret_key.data[i] ^= *ptr++;
125 }
126 //-----------------------------------------------------------------
127 void account_keys::decrypt_viewkey(const crypto::chacha_key &key)
128 {
130 }
131 //-----------------------------------------------------------------
133 {
134 set_null();
135 }
136 //-----------------------------------------------------------------
137 void account_base::set_null()
138 {
139 m_keys = account_keys();
140 m_creation_timestamp = 0;
141 }
142 //-----------------------------------------------------------------
144 {
145 try{
146 m_keys.get_device().disconnect();
147 } catch (const std::exception &e){
148 MERROR("Device disconnect exception: " << e.what());
149 }
150 }
151 //-----------------------------------------------------------------
153 {
154 m_keys.m_spend_secret_key = crypto::secret_key();
155 m_keys.m_multisig_keys.clear();
156 }
157 //-----------------------------------------------------------------
158 crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover, bool two_random)
159 {
160 crypto::secret_key first = generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key, recovery_key, recover);
161
162 // rng for generating second set of keys is hash of first rng. means only one set of electrum-style words needed for recovery
163 crypto::secret_key second;
164 keccak((uint8_t *)&m_keys.m_spend_secret_key, sizeof(crypto::secret_key), (uint8_t *)&second, sizeof(crypto::secret_key));
165
166 generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key, second, two_random ? false : true);
167
168 struct tm timestamp = {0};
169 timestamp.tm_year = 2014 - 1900; // year 2014
170 timestamp.tm_mon = 6 - 1; // month june
171 timestamp.tm_mday = 8; // 8th of june
172 timestamp.tm_hour = 0;
173 timestamp.tm_min = 0;
174 timestamp.tm_sec = 0;
175
176 if (recover)
177 {
178 m_creation_timestamp = mktime(&timestamp);
179 if (m_creation_timestamp == (uint64_t)-1) // failure
180 m_creation_timestamp = 0; // lowest value
181 }
182 else
183 {
184 m_creation_timestamp = time(NULL);
185 }
186 return first;
187 }
188 //-----------------------------------------------------------------
190 {
191 m_keys.m_account_address = address;
192 m_keys.m_spend_secret_key = spendkey;
193 m_keys.m_view_secret_key = viewkey;
194
195 struct tm timestamp = {0};
196 timestamp.tm_year = 2014 - 1900; // year 2014
197 timestamp.tm_mon = 4 - 1; // month april
198 timestamp.tm_mday = 15; // 15th of april
199 timestamp.tm_hour = 0;
200 timestamp.tm_min = 0;
201 timestamp.tm_sec = 0;
202
203 m_creation_timestamp = mktime(&timestamp);
204 if (m_creation_timestamp == (uint64_t)-1) // failure
205 m_creation_timestamp = 0; // lowest value
206 }
207
208 //-----------------------------------------------------------------
209 void account_base::create_from_device(const std::string &device_name)
210 {
211 hw::device &hwdev = hw::get_device(device_name);
212 hwdev.set_name(device_name);
213 create_from_device(hwdev);
214 }
215
217 {
218 m_keys.set_device(hwdev);
219 MCDEBUG("device", "device type: "<<typeid(hwdev).name());
220 CHECK_AND_ASSERT_THROW_MES(hwdev.init(), "Device init failed");
221 CHECK_AND_ASSERT_THROW_MES(hwdev.connect(), "Device connect failed");
222 try {
223 CHECK_AND_ASSERT_THROW_MES(hwdev.get_public_address(m_keys.m_account_address), "Cannot get a device address");
224 CHECK_AND_ASSERT_THROW_MES(hwdev.get_secret_keys(m_keys.m_view_secret_key, m_keys.m_spend_secret_key), "Cannot get device secret");
225 } catch (const std::exception &e){
226 hwdev.disconnect();
227 throw;
228 }
229 struct tm timestamp = {0};
230 timestamp.tm_year = 2014 - 1900; // year 2014
231 timestamp.tm_mon = 4 - 1; // month april
232 timestamp.tm_mday = 15; // 15th of april
233 timestamp.tm_hour = 0;
234 timestamp.tm_min = 0;
235 timestamp.tm_sec = 0;
236
237 m_creation_timestamp = mktime(&timestamp);
238 if (m_creation_timestamp == (uint64_t)-1) // failure
239 m_creation_timestamp = 0; // lowest value
240 }
241
242 //-----------------------------------------------------------------
244 {
246 memset(&unwrap(unwrap(fake)), 0, sizeof(fake));
247 create_from_keys(address, fake, viewkey);
248 }
249 //-----------------------------------------------------------------
250 bool account_base::make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector<crypto::secret_key> &multisig_keys)
251 {
252 m_keys.m_account_address.m_spend_public_key = spend_public_key;
253 m_keys.m_view_secret_key = view_secret_key;
254 m_keys.m_spend_secret_key = spend_secret_key;
255 m_keys.m_multisig_keys = multisig_keys;
256 return crypto::secret_key_to_public_key(view_secret_key, m_keys.m_account_address.m_view_public_key);
257 }
258 //-----------------------------------------------------------------
260 {
261 m_keys.m_account_address.m_spend_public_key = spend_public_key;
262 }
263 //-----------------------------------------------------------------
265 {
266 return m_keys;
267 }
268 //-----------------------------------------------------------------
270 {
271 //TODO: change this code into base 58
272 return get_account_address_as_str(nettype, false, m_keys.m_account_address);
273 }
274 //-----------------------------------------------------------------
276 {
277 //TODO: change this code into base 58
278 return get_account_integrated_address_as_str(nettype, m_keys.m_account_address, payment_id);
279 }
280 //-----------------------------------------------------------------
281}
time_t time
void finalize_multisig(const crypto::public_key &spend_public_key)
Definition account.cpp:259
std::string get_public_address_str(network_type nettype) const
Definition account.cpp:269
bool make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector< crypto::secret_key > &multisig_keys)
Definition account.cpp:250
void create_from_viewkey(const cryptonote::account_public_address &address, const crypto::secret_key &viewkey)
Definition account.cpp:243
crypto::secret_key generate(const crypto::secret_key &recovery_key=crypto::secret_key(), bool recover=false, bool two_random=false)
Definition account.cpp:158
void create_from_keys(const cryptonote::account_public_address &address, const crypto::secret_key &spendkey, const crypto::secret_key &viewkey)
Definition account.cpp:189
void create_from_device(const std::string &device_name)
Definition account.cpp:209
const account_keys & get_keys() const
Definition account.cpp:264
std::string get_public_integrated_address_str(const crypto::hash8 &payment_id, network_type nettype) const
Definition account.cpp:275
const char * data() const noexcept
virtual bool connect(void)=0
virtual bool disconnect(void)=0
virtual bool init(void)=0
virtual bool get_secret_keys(crypto::secret_key &viewkey, crypto::secret_key &spendkey)=0
virtual bool set_name(const std::string &name)=0
virtual bool get_public_address(cryptonote::account_public_address &pubkey)=0
void * memcpy(void *a, const void *b, size_t c)
const char * key
void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen)
#define MERROR(x)
Definition misc_log_ex.h:73
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
#define MCDEBUG(cat, x)
Definition misc_log_ex.h:54
std::enable_if< std::is_pod< T >::value, T >::type rand()
Definition crypto.h:216
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition crypto.h:82
POD_CLASS hash8
Definition hash.h:53
POD_CLASS public_key
Definition crypto.h:79
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition crypto.h:262
POD_CLASS hash
Definition hash.h:50
Holds cryptonote related classes and helpers.
Definition ban.cpp:40
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
std::string get_account_integrated_address_as_str(network_type nettype, account_public_address const &adr, crypto::hash8 const &payment_id)
device & get_device(const std::string &device_descriptor)
Definition device.cpp:95
STL namespace.
#define KEYS_ENCRYPTION_SALT
Definition account.cpp:48
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
crypto::secret_key m_view_secret_key
Definition account.h:45
hw::device & get_device() const
Definition account.cpp:59
crypto::chacha_iv m_encryption_iv
Definition account.h:48
hw::device * m_device
Definition account.h:47
void encrypt_viewkey(const crypto::chacha_key &key)
Definition account.cpp:117
void set_device(hw::device &hwdev)
Definition account.cpp:63
void decrypt_viewkey(const crypto::chacha_key &key)
Definition account.cpp:127
void decrypt(const crypto::chacha_key &key)
Definition account.cpp:112
void encrypt(const crypto::chacha_key &key)
Definition account.cpp:106
const char * address
Definition multisig.cpp:37
const char * spendkey
Definition multisig.cpp:38
#define DISABLE_VS_WARNINGS(w)
Definition warnings.h:18