diff options
author | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2019-01-08 16:05:18 +0000 |
---|---|---|
committer | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2019-01-22 23:17:39 +0000 |
commit | 7d375981584e5ddac4ea6ad8879e2211d465b79d (patch) | |
tree | 82341e77219309514ab8bc12d6c3bd65b60a2293 /src/ringct | |
parent | ringct: encode 8 byte amount, saving 24 bytes per output (diff) | |
download | monero-7d375981584e5ddac4ea6ad8879e2211d465b79d.tar.xz |
ringct: the commitment mask is now deterministic
saves space in the tx and is safe
Found by knaccc
Diffstat (limited to 'src/ringct')
-rw-r--r-- | src/ringct/rctOps.cpp | 56 | ||||
-rw-r--r-- | src/ringct/rctOps.h | 5 | ||||
-rw-r--r-- | src/ringct/rctSigs.cpp | 13 | ||||
-rw-r--r-- | src/ringct/rctTypes.h | 3 |
4 files changed, 51 insertions, 26 deletions
diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp index b28aa4fe6..e39ba16fd 100644 --- a/src/ringct/rctOps.cpp +++ b/src/ringct/rctOps.cpp @@ -672,36 +672,56 @@ namespace rct { // where C= aG + bH static key ecdhHash(const key &k) { - char data[38]; - rct::key hash; - memcpy(data, "amount", 6); - memcpy(data + 6, &k, sizeof(k)); - cn_fast_hash(hash, data, sizeof(data)); - return hash; + char data[38]; + rct::key hash; + memcpy(data, "amount", 6); + memcpy(data + 6, &k, sizeof(k)); + cn_fast_hash(hash, data, sizeof(data)); + return hash; } static void xor8(key &v, const key &k) { - for (int i = 0; i < 8; ++i) - v.bytes[i] ^= k.bytes[i]; + for (int i = 0; i < 8; ++i) + v.bytes[i] ^= k.bytes[i]; + } + key genCommitmentMask(const key &sk) + { + char data[15 + sizeof(key)]; + memcpy(data, "commitment_mask", 15); + memcpy(data + 15, &sk, sizeof(sk)); + key scalar; + hash_to_scalar(scalar, data, sizeof(data)); + return scalar; } - void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec, bool short_amount) { - key sharedSec1 = hash_to_scalar(sharedSec); - key sharedSec2 = hash_to_scalar(sharedSec1); + + void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec, bool v2) { //encode - sc_add(unmasked.mask.bytes, unmasked.mask.bytes, sharedSec1.bytes); - if (short_amount) + if (v2) + { + unmasked.mask = zero(); xor8(unmasked.amount, ecdhHash(sharedSec)); + } else + { + key sharedSec1 = hash_to_scalar(sharedSec); + key sharedSec2 = hash_to_scalar(sharedSec1); + sc_add(unmasked.mask.bytes, unmasked.mask.bytes, sharedSec1.bytes); sc_add(unmasked.amount.bytes, unmasked.amount.bytes, sharedSec2.bytes); + } } - void ecdhDecode(ecdhTuple & masked, const key & sharedSec, bool short_amount) { - key sharedSec1 = hash_to_scalar(sharedSec); - key sharedSec2 = hash_to_scalar(sharedSec1); + void ecdhDecode(ecdhTuple & masked, const key & sharedSec, bool v2) { //decode - sc_sub(masked.mask.bytes, masked.mask.bytes, sharedSec1.bytes); - if (short_amount) + if (v2) + { + masked.mask = genCommitmentMask(sharedSec); xor8(masked.amount, ecdhHash(sharedSec)); + } else + { + key sharedSec1 = hash_to_scalar(sharedSec); + key sharedSec2 = hash_to_scalar(sharedSec1); + sc_sub(masked.mask.bytes, masked.mask.bytes, sharedSec1.bytes); sc_sub(masked.amount.bytes, masked.amount.bytes, sharedSec2.bytes); + } } } diff --git a/src/ringct/rctOps.h b/src/ringct/rctOps.h index 01cdd6fd7..dd6d87593 100644 --- a/src/ringct/rctOps.h +++ b/src/ringct/rctOps.h @@ -182,7 +182,8 @@ namespace rct { //Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a // where C= aG + bH - void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec, bool short_amount); - void ecdhDecode(ecdhTuple & masked, const key & sharedSec, bool short_amount); + key genCommitmentMask(const key &sk); + void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec, bool v2); + void ecdhDecode(ecdhTuple & masked, const key & sharedSec, bool v2); } #endif /* RCTOPS_H */ diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index 6687c91cd..81bec487c 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -79,9 +79,12 @@ namespace } namespace rct { - Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts) + Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts, epee::span<const key> sk) { - masks = rct::skvGen(amounts.size()); + CHECK_AND_ASSERT_THROW_MES(amounts.size() == sk.size(), "Invalid amounts/sk sizes"); + masks.resize(amounts.size()); + for (size_t i = 0; i < masks.size(); ++i) + masks[i] = genCommitmentMask(sk[i]); Bulletproof proof = bulletproof_PROVE(amounts, masks); CHECK_AND_ASSERT_THROW_MES(proof.V.size() == amounts.size(), "V does not have the expected size"); C = proof.V; @@ -803,7 +806,8 @@ namespace rct { } else { - rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts)); + const epee::span<const key> keys{&amount_keys[0], amount_keys.size()}; + rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts, keys)); #ifdef DBG CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof"); #endif @@ -831,7 +835,8 @@ namespace rct { } else { - rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts)); + const epee::span<const key> keys{&amount_keys[amounts_proved], batch_size}; + rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts, keys)); #ifdef DBG CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof"); #endif diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index 54fca1d05..a02c338e9 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -128,7 +128,7 @@ namespace rct { key senderPk; BEGIN_SERIALIZE_OBJECT() - FIELD(mask) + FIELD(mask) // not saved from v2 BPs FIELD(amount) // FIELD(senderPk) // not serialized, as we do not use it in monero currently END_SERIALIZE() @@ -286,7 +286,6 @@ namespace rct { if (type == RCTTypeBulletproof2) { ar.begin_object(); - FIELD_N("mask", ecdhInfo[i].mask); if (!typename Archive<W>::is_saving()) memset(ecdhInfo[i].amount.bytes, 0, sizeof(ecdhInfo[i].amount.bytes)); crypto::hash8 &amount = (crypto::hash8&)ecdhInfo[i].amount; |