40 #define ENCRYPTED_PAYMENT_ID_TAIL 0x8d
41 #define CHACHA8_KEY_TAIL 0x8c
55 return &
reinterpret_cast<unsigned char &
>(scalar);
58 return &
reinterpret_cast<const unsigned char &
>(scalar);
107 epee::mlocked<tools::scrubbed_arr<char,
sizeof(view_key) +
sizeof(spend_key) + 1>> data;
108 memcpy(data.data(), &view_key,
sizeof(view_key));
109 memcpy(data.data() +
sizeof(view_key), &spend_key,
sizeof(spend_key));
111 crypto::generate_chacha_key(data.data(),
sizeof(data),
key, kdf_rounds);
147 std::vector<crypto::public_key> pkeys;
148 pkeys.reserve(end - begin);
149 cryptonote::subaddress_index index = {account, begin};
153 CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, (const unsigned char*)keys.m_account_address.m_spend_public_key.data) == 0,
155 ge_p3_to_cached(&cached, &p3);
157 for (uint32_t idx = begin; idx < end; ++idx)
162 pkeys.push_back(keys.m_account_address.m_spend_public_key);
165 crypto::secret_key m = get_subaddress_secret_key(keys.m_view_secret_key, index);
168 ge_scalarmult_base(&p3, (const unsigned char*)m.data);
171 crypto::public_key D;
173 ge_add(&p1p1, &p3, &cached);
174 ge_p1p1_to_p3(&p3, &p1p1);
175 ge_p3_tobytes((unsigned char*)D.data, &p3);
182 cryptonote::account_public_address device_default::get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) {
184 return keys.m_account_address;
186 crypto::public_key D = get_subaddress_spend_public_key(keys, index);
189 crypto::public_key C = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(D), rct::sk2rct(keys.m_view_secret_key)));
192 cryptonote::account_public_address address;
193 address.m_view_public_key = C;
194 address.m_spend_public_key = D;
198 crypto::secret_key device_default::get_subaddress_secret_key(const crypto::secret_key &a, const cryptonote::subaddress_index &index) {
199 const char prefix[] = "SubAddr
";
200 char data[sizeof(prefix) + sizeof(crypto::secret_key) + 2 * sizeof(uint32_t)];
201 memcpy(data, prefix, sizeof(prefix));
202 memcpy(data + sizeof(prefix), &a, sizeof(crypto::secret_key));
203 uint32_t idx = SWAP32LE(index.major);
204 memcpy(data + sizeof(prefix) + sizeof(crypto::secret_key), &idx, sizeof(uint32_t));
205 idx = SWAP32LE(index.minor);
206 memcpy(data + sizeof(prefix) + sizeof(crypto::secret_key) + sizeof(uint32_t), &idx, sizeof(uint32_t));
207 crypto::secret_key m;
208 crypto::hash_to_scalar(data, sizeof(data), m);
212 // subaddress pub spend is D = B + mG where m is the subaddress secret key, B is the main wallet public spend key
213 // Alternatively write D = bG + mG === (b+m)G
214 // therefore priv spend d = b+m
215 crypto::secret_key device_default::get_subaddress_private_spendkey(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &subaddr_index){
216 crypto::secret_key subaddr_secret_key = get_subaddress_secret_key(keys.m_view_secret_key, subaddr_index);
217 crypto::secret_key subaddr_private_spendkey;
218 sc_secret_add(subaddr_private_spendkey, subaddr_secret_key, keys.m_spend_secret_key);
219 return subaddr_private_spendkey;
222 // subaddress pub view is C = aD where 'a' is the main wallet private view key
223 // Alternatively write C = a*dG === a*(b+m)G
224 // therefore priv view c = a(b+m)
225 crypto::secret_key device_default::get_subaddress_private_viewkey(const crypto::secret_key &main_wallet_sec_view, crypto::secret_key &subaddress_sec_spend){
226 crypto::secret_key subaddr_private_viewkey;
227 sc_mul(&subaddr_private_viewkey, &main_wallet_sec_view, &subaddress_sec_spend);
228 return subaddr_private_viewkey;
231 /* ======================================================================= */
232 /* DERIVATION & KEY */
233 /* ======================================================================= */
235 bool device_default::verify_keys(const crypto::secret_key &secret_key, const crypto::public_key &public_key) {
236 crypto::public_key calculated_pub;
237 bool r = crypto::secret_key_to_public_key(secret_key, calculated_pub);
238 return r && public_key == calculated_pub;
241 bool device_default::scalarmultKey(rct::key & aP, const rct::key &P, const rct::key &a) {
242 rct::scalarmultKey(aP, P,a);
246 bool device_default::scalarmultBase(rct::key &aG, const rct::key &a) {
247 rct::scalarmultBase(aG,a);
251 bool device_default::sc_secret_add(crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) {
256 crypto::secret_key device_default::generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key, bool recover) {
257 return crypto::generate_keys(pub, sec, recovery_key, recover);
260 bool device_default::generate_key_derivation(const crypto::public_key &key1, const crypto::secret_key &key2, crypto::key_derivation &derivation) {
261 return crypto::generate_key_derivation(key1, key2, derivation);
264 bool device_default::derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res){
265 crypto::derivation_to_scalar(derivation,output_index, res);
269 bool device_default::derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &base, crypto::secret_key &derived_key){
270 crypto::derive_secret_key(derivation, output_index, base, derived_key);
274 bool device_default::derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &base, crypto::public_key &derived_key){
275 return crypto::derive_public_key(derivation, output_index, base, derived_key);
278 bool device_default::secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) {
279 return crypto::secret_key_to_public_key(sec,pub);
282 bool device_default::generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image){
283 crypto::generate_key_image(pub, sec,image);
287 bool device_default::conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations){
291 /* ======================================================================= */
293 /* ======================================================================= */
294 void device_default::generate_tx_proof(const crypto::hash &prefix_hash,
295 const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
296 crypto::signature &sig) {
297 crypto::generate_tx_proof(prefix_hash, R, A, B, D, r, sig);
300 bool device_default::open_tx(crypto::secret_key &tx_key) {
301 cryptonote::keypair txkey = cryptonote::keypair::generate(*this);
306 bool device_default::generate_output_ephemeral_keys(const size_t tx_version,
307 const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key,
308 const cryptonote::tx_destination_entry &dst_entr, const boost::optional<cryptonote::account_public_address> &change_addr, const size_t output_index,
309 const bool &need_additional_txkeys, const std::vector<crypto::secret_key> &additional_tx_keys,
310 std::vector<crypto::public_key> &additional_tx_public_keys,
311 std::vector<rct::key> &amount_keys, crypto::public_key &out_eph_public_key) {
313 crypto::key_derivation derivation;
315 // make additional tx pubkey if necessary
316 cryptonote::keypair additional_txkey;
317 if (need_additional_txkeys)
319 additional_txkey.sec = additional_tx_keys[output_index];
320 if (dst_entr.is_subaddress)
321 additional_txkey.pub = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(dst_entr.addr.m_spend_public_key), rct::sk2rct(additional_txkey.sec)));
323 additional_txkey.pub = rct::rct2pk(rct::scalarmultBase(rct::sk2rct(additional_txkey.sec)));
327 if (change_addr && dst_entr.addr == *change_addr)
329 // sending change to yourself; derivation = a*R
330 r = generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation);
331 CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to
generate_key_derivation(
" << txkey_pub << ",
" << sender_account_keys.m_view_secret_key << ")
");
335 // sending to the recipient; derivation = r*A (or s*C in the subaddress scheme)
336 r = generate_key_derivation(dst_entr.addr.m_view_public_key, dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key, derivation);
337 CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to
generate_key_derivation(
" << dst_entr.addr.m_view_public_key << ",
" << (dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key) << ")
");
340 if (need_additional_txkeys)
342 additional_tx_public_keys.push_back(additional_txkey.pub);
347 crypto::secret_key scalar1;
348 derivation_to_scalar(derivation, output_index, scalar1);
349 amount_keys.push_back(rct::sk2rct(scalar1));
351 r = derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key);
352 CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to
derive_public_key(
" << derivation << ",
" << output_index << ",
"<< dst_entr.addr.m_spend_public_key << ")
");
357 bool device_default::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) {
358 crypto::key_derivation derivation;
360 char data[33]; /* A hash, and an extra byte */
362 if (!generate_key_derivation(public_key, secret_key, derivation))
365 memcpy(data, &derivation, 32);
366 data[32] = ENCRYPTED_PAYMENT_ID_TAIL;
367 cn_fast_hash(data, 33, hash);
369 for (size_t b = 0; b < 8; ++b)
370 payment_id.data[b] ^= hash.data[b];
375 rct::key device_default::genCommitmentMask(const rct::key &amount_key) {
376 return rct::genCommitmentMask(amount_key);
379 bool device_default::ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec, bool short_amount) {
380 rct::ecdhEncode(unmasked, sharedSec, short_amount);
384 bool device_default::ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec, bool short_amount) {
385 rct::ecdhDecode(masked, sharedSec, short_amount);
389 bool device_default::mlsag_prepare(const rct::key &H, const rct::key &xx,
390 rct::key &a, rct::key &aG, rct::key &aHP, rct::key &II) {
392 rct::scalarmultKey(aHP, H, a);
393 rct::scalarmultKey(II, H, xx);
396 bool device_default::mlsag_prepare(rct::key &a, rct::key &aG) {
400 bool device_default::mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) {
401 prehash = rct::cn_fast_hash(hashes);
406 bool device_default::mlsag_hash(const rct::keyV &toHash, rct::key &c_old) {
407 c_old = rct::hash_to_scalar(toHash);
411 bool device_default::mlsag_sign(const rct::key &c, const rct::keyV &xx, const rct::keyV &alpha, const size_t rows, const size_t dsRows, rct::keyV &ss ) {
412 CHECK_AND_ASSERT_THROW_MES(dsRows<=rows, "dsRows greater than
rows");
413 CHECK_AND_ASSERT_THROW_MES(xx.size() == rows, "xx size does not match
rows");
414 CHECK_AND_ASSERT_THROW_MES(alpha.size() == rows, "alpha size does not match
rows");
415 CHECK_AND_ASSERT_THROW_MES(ss.size() == rows, "ss size does not match
rows");
416 for (size_t j = 0; j < rows; j++) {
417 sc_mulsub(ss[j].bytes, c.bytes, xx[j].bytes, alpha[j].bytes);
422 bool device_default::close_tx() {
426 bool device_default::hash_to_scalar(boost::shared_ptr<crypto::rs_comm> buf, size_t length, crypto::ec_scalar &res) {
427 crypto::hash_to_scalar(buf.get(), length, res);
431 bool device_default::get_transaction_prefix_hash(const cryptonote::transaction_prefix& tx, crypto::hash& tx_prefix_hash) {
433 std::ostringstream s;
434 binary_archive<true> a(s);
435 ::serialization::serialize(a, const_cast<cryptonote::transaction_prefix&>(tx));
437 crypto::cn_fast_hash(s.str().data(), s.str().size(), tx_prefix_hash);
442 bool device_default::generate_ring_signature(const crypto::hash &prefix_hash, const crypto::key_image &image,
443 const std::vector<const crypto::public_key *> &pubs,
444 const crypto::secret_key &sec, std::size_t sec_index,
445 crypto::signature *sig){
446 crypto::generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sig);
450 bool device_default::generate_input_signature(const crypto::hash &prefix_hash, const uint32_t input_index, const crypto::secret_key sec_view, const crypto::secret_key sec_spend, crypto::signature& signature){
451 crypto::generate_input_signature(prefix_hash, input_index, sec_view, sec_spend, signature);
455 /* ---------------------------------------------------------- */
456 static device_default *default_core_device = NULL;
457 void register_all(std::map<std::string, std::unique_ptr<device>> ®istry) {
458 if (!default_core_device) {
459 default_core_device = new device_default();
460 default_core_device->set_name("default_core_device
");
463 registry.insert(std::make_pair("default", std::unique_ptr<device>(default_core_device)));
bool get_secret_keys(crypto::secret_key &viewkey, crypto::secret_key &spendkey) override
std::vector< crypto::public_key > get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) override
bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) override
bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) override
bool try_lock(void) override
void unlock(void) override
crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys &keys, const cryptonote::subaddress_index &index) override
bool disconnect() override
bool generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key, uint64_t kdf_rounds) override
bool get_public_address(cryptonote::account_public_address &pubkey) override
bool connect(void) override
bool set_mode(device_mode mode) override
crypto::secret_key get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index) override
const std::string get_name() const override
bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub) override
bool set_name(const std::string &name) override
virtual bool set_mode(device_mode mode)
int ge_frombytes_vartime(ge_p3 *, const unsigned char *)
void * memcpy(void *a, const void *b, size_t c)
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &result)
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
void addKeys(key &AB, const key &A, const key &B)
unsigned __int64 uint64_t
crypto::secret_key m_view_secret_key
crypto::secret_key m_spend_secret_key
account_public_address m_account_address
crypto::public_key m_spend_public_key