mirror of
https://github.com/wownero/wownero.git
synced 2026-10-25 18:38:34 +01:00
ringct: make h2d fallible
One theoretically could have crafted a "long amount" (pre-v10) RingCT transaction with non-0 padding bytes in the decoded amount which fails receiver scanning, but passes third-party wallet proof checking.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2016-2024, Monero Research Labs
|
// Copyright (c) 2016-2026, Monero Research Labs
|
||||||
//
|
//
|
||||||
// Author: Shen Noether <shen.noether@gmx.com>
|
// Author: Shen Noether <shen.noether@gmx.com>
|
||||||
//
|
//
|
||||||
@@ -30,7 +30,11 @@
|
|||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include "misc_log_ex.h"
|
#include "misc_log_ex.h"
|
||||||
|
extern "C" {
|
||||||
|
#include "rctCryptoOps.h"
|
||||||
|
}
|
||||||
#include "rctOps.h"
|
#include "rctOps.h"
|
||||||
|
|
||||||
using namespace crypto;
|
using namespace crypto;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -340,7 +344,8 @@ namespace rct {
|
|||||||
|
|
||||||
//generates a random uint long long (for testing)
|
//generates a random uint long long (for testing)
|
||||||
xmr_amount randXmrAmount(xmr_amount upperlimit) {
|
xmr_amount randXmrAmount(xmr_amount upperlimit) {
|
||||||
return h2d(skGen()) % (upperlimit);
|
assert(upperlimit > 0);
|
||||||
|
return crypto::rand<xmr_amount>() % upperlimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Scalar multiplications of curve points
|
//Scalar multiplications of curve points
|
||||||
|
|||||||
+1
-10
@@ -1,5 +1,5 @@
|
|||||||
//#define DBG
|
//#define DBG
|
||||||
// Copyright (c) 2016-2024, Monero Research Labs
|
// Copyright (c) 2016-2026, Monero Research Labs
|
||||||
//
|
//
|
||||||
// Author: Shen Noether <shen.noether@gmx.com>
|
// Author: Shen Noether <shen.noether@gmx.com>
|
||||||
//
|
//
|
||||||
@@ -37,15 +37,6 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include "crypto/generic-ops.h"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "crypto/random.h"
|
|
||||||
#include "crypto/keccak.h"
|
|
||||||
#include "rctCryptoOps.h"
|
|
||||||
}
|
|
||||||
#include "crypto/crypto.h"
|
|
||||||
|
|
||||||
#include "rctTypes.h"
|
#include "rctTypes.h"
|
||||||
|
|
||||||
//Define this flag when debugging to get additional info on the console
|
//Define this flag when debugging to get additional info on the console
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2016-2024, Monero Research Labs
|
// Copyright (c) 2016-2026, Monero Research Labs
|
||||||
//
|
//
|
||||||
// Author: Shen Noether <shen.noether@gmx.com>
|
// Author: Shen Noether <shen.noether@gmx.com>
|
||||||
//
|
//
|
||||||
@@ -1573,7 +1573,10 @@ namespace rct {
|
|||||||
if (equalKeys(C, Ctmp) == false) {
|
if (equalKeys(C, Ctmp) == false) {
|
||||||
CHECK_AND_ASSERT_THROW_MES(false, "warning, amount decoded incorrectly, will be unable to spend");
|
CHECK_AND_ASSERT_THROW_MES(false, "warning, amount decoded incorrectly, will be unable to spend");
|
||||||
}
|
}
|
||||||
return h2d(amount);
|
rct::xmr_amount amount_8;
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(h2d(amount_8, amount),
|
||||||
|
"long decoded amount contains superfluous data");
|
||||||
|
return amount_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, hw::device &hwdev) {
|
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, hw::device &hwdev) {
|
||||||
@@ -1604,7 +1607,10 @@ namespace rct {
|
|||||||
if (equalKeys(C, Ctmp) == false) {
|
if (equalKeys(C, Ctmp) == false) {
|
||||||
CHECK_AND_ASSERT_THROW_MES(false, "warning, amount decoded incorrectly, will be unable to spend");
|
CHECK_AND_ASSERT_THROW_MES(false, "warning, amount decoded incorrectly, will be unable to spend");
|
||||||
}
|
}
|
||||||
return h2d(amount);
|
rct::xmr_amount amount_8;
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(h2d(amount_8, amount),
|
||||||
|
"long decoded amount contains superfluous data");
|
||||||
|
return amount_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, hw::device &hwdev) {
|
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, hw::device &hwdev) {
|
||||||
|
|||||||
+11
-7
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2016-2024, Monero Research Labs
|
// Copyright (c) 2016-2026, Monero Research Labs
|
||||||
//
|
//
|
||||||
// Author: Shen Noether <shen.noether@gmx.com>
|
// Author: Shen Noether <shen.noether@gmx.com>
|
||||||
//
|
//
|
||||||
@@ -140,14 +140,18 @@ namespace rct {
|
|||||||
|
|
||||||
//32 byte key to uint long long
|
//32 byte key to uint long long
|
||||||
// if the key holds a value > 2^64
|
// if the key holds a value > 2^64
|
||||||
// then the value in the first 8 bytes is returned
|
// then false is returned
|
||||||
xmr_amount h2d(const key & test) {
|
bool h2d(xmr_amount &amountd, const key & test) {
|
||||||
xmr_amount vali = 0;
|
amountd = 0;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (j = 7; j >= 0; j--) {
|
for (j = 8; j < 32; ++j) {
|
||||||
vali = (xmr_amount)(vali * 256 + (unsigned char)test.bytes[j]);
|
if (test.bytes[j])
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return vali;
|
for (j = 7; j >= 0; j--) {
|
||||||
|
amountd = (xmr_amount)(amountd * 256 + (unsigned char)test.bytes[j]);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//32 byte key to int[64]
|
//32 byte key to int[64]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2016-2024, Monero Research Labs
|
// Copyright (c) 2016-2026, Monero Research Labs
|
||||||
//
|
//
|
||||||
// Author: Shen Noether <shen.noether@gmx.com>
|
// Author: Shen Noether <shen.noether@gmx.com>
|
||||||
//
|
//
|
||||||
@@ -722,8 +722,8 @@ namespace rct {
|
|||||||
void d2b(bits amountb, xmr_amount val);
|
void d2b(bits amountb, xmr_amount val);
|
||||||
//32 byte key to uint long long
|
//32 byte key to uint long long
|
||||||
// if the key holds a value > 2^64
|
// if the key holds a value > 2^64
|
||||||
// then the value in the first 8 bytes is returned
|
// then false is returned
|
||||||
xmr_amount h2d(const key &test);
|
bool h2d(xmr_amount &amountd, const key &test);
|
||||||
//32 byte key to int[64]
|
//32 byte key to int[64]
|
||||||
void h2b(bits amountb2, const key & test);
|
void h2b(bits amountb2, const key & test);
|
||||||
//int[64] to 32 byte key
|
//int[64] to 32 byte key
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2017-2024, The Monero Project
|
// Copyright (c) 2017-2026, The Monero Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
@@ -438,7 +438,10 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
|
|||||||
rct::key C = tx.rct_signatures.outPk[n].mask;
|
rct::key C = tx.rct_signatures.outPk[n].mask;
|
||||||
rct::addKeys2(Ctmp, ecdh_info.mask, ecdh_info.amount, rct::H);
|
rct::addKeys2(Ctmp, ecdh_info.mask, ecdh_info.amount, rct::H);
|
||||||
CHECK_AND_ASSERT_MES(rct::equalKeys(C, Ctmp), false, "Failed to decode amount");
|
CHECK_AND_ASSERT_MES(rct::equalKeys(C, Ctmp), false, "Failed to decode amount");
|
||||||
amount += rct::h2d(ecdh_info.amount);
|
rct::xmr_amount this_amount;
|
||||||
|
CHECK_AND_ASSERT_MES(rct::h2d(this_amount, ecdh_info.amount),
|
||||||
|
false, "Decoded long amount contains superfluous data");
|
||||||
|
amount += this_amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CHECK_AND_ASSERT_MES(n_outs == 2, false, "Not exactly 2 outputs were received");
|
CHECK_AND_ASSERT_MES(n_outs == 2, false, "Not exactly 2 outputs were received");
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2014-2024, The Monero Project
|
// Copyright (c) 2014-2026, The Monero Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
@@ -974,11 +974,13 @@ static const xmr_amount test_amounts[]={0, 1, 2, 3, 4, 5, 10000, 100000000000000
|
|||||||
|
|
||||||
TEST(ringct, d2h)
|
TEST(ringct, d2h)
|
||||||
{
|
{
|
||||||
key k, P1;
|
key k = skGen();
|
||||||
skpkGen(k, P1);
|
memset(k.bytes + 8, 0, sizeof(k) - 8);
|
||||||
for (auto amount: test_amounts) {
|
for (auto amount: test_amounts) {
|
||||||
d2h(k, amount);
|
d2h(k, amount);
|
||||||
ASSERT_TRUE(amount == h2d(k));
|
xmr_amount h2d_amount;
|
||||||
|
ASSERT_TRUE(h2d(h2d_amount, k));
|
||||||
|
ASSERT_EQ(h2d_amount, amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user