Added checks for tx keys

This commit is contained in:
SChernykh 2021-08-31 17:23:20 +02:00
parent 0558cdb9cc
commit 780afd84a2
9 changed files with 66 additions and 16 deletions

View file

@ -628,7 +628,9 @@ bool BlockTemplate::create_miner_tx(const MinerData& data, const std::vector<Min
} }
else { else {
hash eph_public_key; hash eph_public_key;
shares[i].m_wallet->get_eph_public_key(m_txkeySec, i, eph_public_key); if (!shares[i].m_wallet->get_eph_public_key(m_txkeySec, i, eph_public_key)) {
LOGERR(1, "get_eph_public_key failed at index " << i);
}
m_minerTx.insert(m_minerTx.end(), eph_public_key.h, eph_public_key.h + HASH_SIZE); m_minerTx.insert(m_minerTx.end(), eph_public_key.h, eph_public_key.h + HASH_SIZE);
m_poolBlockTemplate->m_outputs.emplace_back(m_rewards[i], eph_public_key); m_poolBlockTemplate->m_outputs.emplace_back(m_rewards[i], eph_public_key);
} }

View file

@ -84,10 +84,7 @@ void generate_keys(hash& pub, hash& sec)
static constexpr uint8_t limit[32] = { 0xe3, 0x6a, 0x67, 0x72, 0x8b, 0xce, 0x13, 0x29, 0x8f, 0x30, 0x82, 0x8c, 0x0b, 0xa4, 0x10, 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0 }; static constexpr uint8_t limit[32] = { 0xe3, 0x6a, 0x67, 0x72, 0x8b, 0xce, 0x13, 0x29, 0x8f, 0x30, 0x82, 0x8c, 0x0b, 0xa4, 0x10, 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0 };
do { do {
randomBytes(sec.h); do { randomBytes(sec.h); } while (!less32(sec.h, limit));
if (!less32(sec.h, limit)) {
continue;
}
sc_reduce32(sec.h); sc_reduce32(sec.h);
} while (!sc_isnonzero(sec.h)); } while (!sc_isnonzero(sec.h));
@ -96,6 +93,22 @@ void generate_keys(hash& pub, hash& sec)
ge_p3_tobytes(pub.h, &point); ge_p3_tobytes(pub.h, &point);
} }
bool check_keys(const hash& pub, const hash& sec)
{
// From ge_scalarmult_base's comment: "preconditions a[31] <= 127"
if (sec.h[HASH_SIZE - 1] > 127) {
return false;
}
ge_p3 point;
ge_scalarmult_base(&point, sec.h);
hash pub_check;
ge_p3_tobytes(pub_check.h, &point);
return pub == pub_check;
}
bool generate_key_derivation(const hash& key1, const hash& key2, hash& derivation) bool generate_key_derivation(const hash& key1, const hash& key2, hash& derivation)
{ {
ge_p3 point; ge_p3 point;

View file

@ -20,6 +20,7 @@
namespace p2pool { namespace p2pool {
void generate_keys(hash& pub, hash& sec); void generate_keys(hash& pub, hash& sec);
bool check_keys(const hash& pub, const hash& sec);
bool generate_key_derivation(const hash& key1, const hash& key2, hash& derivation); bool generate_key_derivation(const hash& key1, const hash& key2, hash& derivation);
bool derive_public_key(const hash& derivation, size_t output_index, const hash& base, hash& derived_key); bool derive_public_key(const hash& derivation, size_t output_index, const hash& base, hash& derived_key);

View file

@ -721,7 +721,7 @@ bool P2PServer::P2PClient::on_connect()
// server->m_clientsListLock is already locked here // server->m_clientsListLock is already locked here
for (P2PClient* client = static_cast<P2PClient*>(server->m_connectedClientsList->m_next); client != server->m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) { for (P2PClient* client = static_cast<P2PClient*>(server->m_connectedClientsList->m_next); client != server->m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
if ((client != this) && (client->m_addr == m_addr)) { if ((client != this) && (client->m_addr == m_addr)) {
LOGWARN(5, "peer " << static_cast<char*>(m_addrString) << " is already connected as " << static_cast<char*>(client->m_addrString)); LOGINFO(5, "peer " << static_cast<char*>(m_addrString) << " is already connected as " << static_cast<char*>(client->m_addrString));
return false; return false;
} }
} }

View file

@ -20,6 +20,7 @@
#include "keccak.h" #include "keccak.h"
#include "side_chain.h" #include "side_chain.h"
#include "pow_hash.h" #include "pow_hash.h"
#include "crypto.h"
static constexpr char log_category_prefix[] = "PoolBlock "; static constexpr char log_category_prefix[] = "PoolBlock ";

View file

@ -233,9 +233,16 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, SideChain& sidechai
hash view_pub_key; hash view_pub_key;
READ_BUF(spend_pub_key.h, HASH_SIZE); READ_BUF(spend_pub_key.h, HASH_SIZE);
READ_BUF(view_pub_key.h, HASH_SIZE); READ_BUF(view_pub_key.h, HASH_SIZE);
m_minerWallet.assign(spend_pub_key, view_pub_key); if (!m_minerWallet.assign(spend_pub_key, view_pub_key, sidechain.network_type())) {
return __LINE__;
}
READ_BUF(m_txkeySec.h, HASH_SIZE); READ_BUF(m_txkeySec.h, HASH_SIZE);
if (!check_keys(m_txkeyPub, m_txkeySec)) {
return __LINE__;
}
READ_BUF(m_parent.h, HASH_SIZE); READ_BUF(m_parent.h, HASH_SIZE);
uint64_t num_uncles; uint64_t num_uncles;

View file

@ -550,7 +550,9 @@ bool SideChain::get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::v
blob.emplace_back(TXOUT_TO_KEY); blob.emplace_back(TXOUT_TO_KEY);
shares[i].m_wallet->get_eph_public_key(block->m_txkeySec, i, eph_public_key); if (!shares[i].m_wallet->get_eph_public_key(block->m_txkeySec, i, eph_public_key)) {
LOGWARN(6, "get_eph_public_key failed at index " << i);
}
blob.insert(blob.end(), eph_public_key.h, eph_public_key.h + HASH_SIZE); blob.insert(blob.end(), eph_public_key.h, eph_public_key.h + HASH_SIZE);
block->m_outputs.emplace_back(rewards[i], eph_public_key); block->m_outputs.emplace_back(rewards[i], eph_public_key);
@ -1146,7 +1148,14 @@ void SideChain::verify(PoolBlock* block)
} }
hash eph_public_key; hash eph_public_key;
shares[i].m_wallet->get_eph_public_key(block->m_txkeySec, i, eph_public_key); if (!shares[i].m_wallet->get_eph_public_key(block->m_txkeySec, i, eph_public_key)) {
LOGWARN(3, "block at height = " << block->m_sidechainHeight <<
", id = " << block->m_sidechainId <<
", mainchain height = " << block->m_txinGenHeight <<
" failed to eph_public_key at index " << i);
block->m_invalid = true;
return;
}
if (eph_public_key != block->m_outputs[i].m_ephPublicKey) { if (eph_public_key != block->m_outputs[i].m_ephPublicKey) {
LOGWARN(3, "block at height = " << block->m_sidechainHeight << LOGWARN(3, "block at height = " << block->m_sidechainHeight <<

View file

@ -24,6 +24,10 @@
#include "crypto.h" #include "crypto.h"
#include <array> #include <array>
extern "C" {
#include "crypto-ops.h"
}
static constexpr char log_category_prefix[] = "Wallet "; static constexpr char log_category_prefix[] = "Wallet ";
namespace { namespace {
@ -189,8 +193,13 @@ bool Wallet::decode(const char* address)
return valid(); return valid();
} }
void Wallet::assign(const hash& spend_pub_key, const hash& view_pub_key) bool Wallet::assign(const hash& spend_pub_key, const hash& view_pub_key, NetworkType type)
{ {
ge_p3 point;
if ((ge_frombytes_vartime(&point, spend_pub_key.h) != 0) || (ge_frombytes_vartime(&point, view_pub_key.h) != 0)) {
return false;
}
MutexLock lock(m_lock); MutexLock lock(m_lock);
m_prefix = 0; m_prefix = 0;
@ -198,15 +207,17 @@ void Wallet::assign(const hash& spend_pub_key, const hash& view_pub_key)
m_viewPublicKey = view_pub_key; m_viewPublicKey = view_pub_key;
m_checksum = 0; m_checksum = 0;
m_type = NetworkType::Mainnet; m_type = type;
m_txkeySec = {}; m_txkeySec = {};
m_outputIndex = std::numeric_limits<size_t>::max(); m_outputIndex = std::numeric_limits<size_t>::max();
m_derivation = {}; m_derivation = {};
m_ephPublicKey = {}; m_ephPublicKey = {};
return true;
} }
void Wallet::get_eph_public_key(const hash& txkey_sec, size_t output_index, hash& eph_public_key) bool Wallet::get_eph_public_key(const hash& txkey_sec, size_t output_index, hash& eph_public_key)
{ {
MutexLock lock(m_lock); MutexLock lock(m_lock);
@ -217,7 +228,9 @@ void Wallet::get_eph_public_key(const hash& txkey_sec, size_t output_index, hash
derivation = m_derivation; derivation = m_derivation;
} }
else { else {
generate_key_derivation(m_viewPublicKey, txkey_sec, derivation); if (!generate_key_derivation(m_viewPublicKey, txkey_sec, derivation)) {
return false;
}
m_derivation = derivation; m_derivation = derivation;
m_txkeySec = txkey_sec; m_txkeySec = txkey_sec;
derivation_changed = true; derivation_changed = true;
@ -227,10 +240,14 @@ void Wallet::get_eph_public_key(const hash& txkey_sec, size_t output_index, hash
eph_public_key = m_ephPublicKey; eph_public_key = m_ephPublicKey;
} }
else { else {
derive_public_key(derivation, output_index, m_spendPublicKey, eph_public_key); if (!derive_public_key(derivation, output_index, m_spendPublicKey, eph_public_key)) {
return false;
}
m_outputIndex = output_index; m_outputIndex = output_index;
m_ephPublicKey = eph_public_key; m_ephPublicKey = eph_public_key;
} }
return true;
} }
} // namespace p2pool } // namespace p2pool

View file

@ -34,12 +34,12 @@ public:
FORCEINLINE NetworkType type() const { return m_type; } FORCEINLINE NetworkType type() const { return m_type; }
bool decode(const char* address); bool decode(const char* address);
void assign(const hash& spend_pub_key, const hash& view_pub_key); bool assign(const hash& spend_pub_key, const hash& view_pub_key, NetworkType type);
FORCEINLINE const hash& spend_public_key() const { return m_spendPublicKey; } FORCEINLINE const hash& spend_public_key() const { return m_spendPublicKey; }
FORCEINLINE const hash& view_public_key() const { return m_viewPublicKey; } FORCEINLINE const hash& view_public_key() const { return m_viewPublicKey; }
void get_eph_public_key(const hash& txkey_sec, size_t output_index, hash& eph_public_key); bool get_eph_public_key(const hash& txkey_sec, size_t output_index, hash& eph_public_key);
FORCEINLINE bool operator<(const Wallet& w) const { return m_spendPublicKey < w.m_spendPublicKey; } FORCEINLINE bool operator<(const Wallet& w) const { return m_spendPublicKey < w.m_spendPublicKey; }
FORCEINLINE bool operator==(const Wallet& w) const { return m_spendPublicKey == w.m_spendPublicKey; } FORCEINLINE bool operator==(const Wallet& w) const { return m_spendPublicKey == w.m_spendPublicKey; }