aboutsummaryrefslogtreecommitdiff
path: root/src/ringct
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2016-07-24 17:53:34 +0100
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2016-08-28 21:29:46 +0100
commit9b70856ccb97943249f6e76b19f8abce5cd7aabe (patch)
treee4717e7723dfc3aab14e3fdc85d9294efbd4b1eb /src/ringct
parentrct: do not serialize public keys in outPk (diff)
downloadmonero-9b70856ccb97943249f6e76b19f8abce5cd7aabe.tar.xz
rct: make the amount key derivable by a third party with the tx key
Scheme design from luigi1114.
Diffstat (limited to 'src/ringct')
-rw-r--r--src/ringct/rctOps.cpp20
-rw-r--r--src/ringct/rctOps.h2
-rw-r--r--src/ringct/rctSigs.cpp40
-rw-r--r--src/ringct/rctSigs.h12
-rw-r--r--src/ringct/rctTypes.h2
5 files changed, 52 insertions, 24 deletions
diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp
index 06267fd8e..b8a0d26ad 100644
--- a/src/ringct/rctOps.cpp
+++ b/src/ringct/rctOps.cpp
@@ -741,22 +741,28 @@ void fe_mul(fe h,const fe f,const fe g)
//Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a
// where C= aG + bH
+ void ecdhEncodeFromSharedSecret(ecdhTuple & unmasked, const key & sharedSec1) {
+ key sharedSec2 = hash_to_scalar(sharedSec1);
+ //encode
+ sc_add(unmasked.mask.bytes, unmasked.mask.bytes, sharedSec1.bytes);
+ sc_add(unmasked.amount.bytes, unmasked.amount.bytes, sharedSec2.bytes);
+ }
void ecdhEncode(ecdhTuple & unmasked, const key & receiverPk) {
key esk;
//compute shared secret
skpkGen(esk, unmasked.senderPk);
key sharedSec1 = hash_to_scalar(scalarmultKey(receiverPk, esk));
+ ecdhEncodeFromSharedSecret(unmasked, sharedSec1);
+ }
+ void ecdhDecodeFromSharedSecret(ecdhTuple & masked, const key & sharedSec1) {
key sharedSec2 = hash_to_scalar(sharedSec1);
- //encode
- sc_add(unmasked.mask.bytes, unmasked.mask.bytes, sharedSec1.bytes);
- sc_add(unmasked.amount.bytes, unmasked.amount.bytes, sharedSec2.bytes);
+ //decode
+ sc_sub(masked.mask.bytes, masked.mask.bytes, sharedSec1.bytes);
+ sc_sub(masked.amount.bytes, masked.amount.bytes, sharedSec2.bytes);
}
void ecdhDecode(ecdhTuple & masked, const key & receiverSk) {
//compute shared secret
key sharedSec1 = hash_to_scalar(scalarmultKey(masked.senderPk, receiverSk));
- key sharedSec2 = hash_to_scalar(sharedSec1);
- //encode
- sc_sub(masked.mask.bytes, masked.mask.bytes, sharedSec1.bytes);
- sc_sub(masked.amount.bytes, masked.amount.bytes, sharedSec2.bytes);
+ ecdhDecodeFromSharedSecret(masked, sharedSec1);
}
}
diff --git a/src/ringct/rctOps.h b/src/ringct/rctOps.h
index 6438a1f03..225c5abb9 100644
--- a/src/ringct/rctOps.h
+++ b/src/ringct/rctOps.h
@@ -165,7 +165,9 @@ namespace rct {
//Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a
// where C= aG + bH
+ void ecdhEncodeFromSharedSecret(ecdhTuple & unmasked, const key & sharedSec1);
void ecdhEncode(ecdhTuple & unmasked, const key & receiverPk);
+ void ecdhDecodeFromSharedSecret(ecdhTuple & masked, const key & sharedSec1);
void ecdhDecode(ecdhTuple & masked, const key & receiverSk);
}
#endif /* RCTOPS_H */
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp
index fa9c833dd..0d4fbee1a 100644
--- a/src/ringct/rctSigs.cpp
+++ b/src/ringct/rctSigs.cpp
@@ -535,7 +535,7 @@ namespace rct {
// must know the destination private key to find the correct amount, else will return a random number
// Note: For txn fees, the last index in the amounts vector should contain that
// Thus the amounts vector will be "one" longer than the destinations vectort
- rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & amounts, const ctkeyM &mixRing, unsigned int index, ctkeyV &outSk) {
+ rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & amounts, const ctkeyM &mixRing, const keyV &amount_keys, unsigned int index, ctkeyV &outSk) {
CHECK_AND_ASSERT_THROW_MES(amounts.size() == destinations.size() || amounts.size() == destinations.size() + 1, "Different number of amounts/destinations");
CHECK_AND_ASSERT_THROW_MES(index < mixRing.size(), "Bad index into mixRing");
for (size_t n = 0; n < mixRing.size(); ++n) {
@@ -563,7 +563,7 @@ namespace rct {
//mask amount and mask
rv.ecdhInfo[i].mask = copy(outSk[i].mask);
rv.ecdhInfo[i].amount = d2h(amounts[i]);
- ecdhEncode(rv.ecdhInfo[i], destinations[i]);
+ ecdhEncodeFromSharedSecret(rv.ecdhInfo[i], amount_keys[i]);
}
@@ -584,17 +584,17 @@ namespace rct {
return rv;
}
- rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> & amounts, const int mixin) {
+ rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> & amounts, const keyV &amount_keys, const int mixin) {
unsigned int index;
ctkeyM mixRing;
ctkeyV outSk;
tie(mixRing, index) = populateFromBlockchain(inPk, mixin);
- return genRct(message, inSk, destinations, amounts, mixRing, index, outSk);
+ return genRct(message, inSk, destinations, amounts, mixRing, amount_keys, index, outSk);
}
//RCT simple
//for post-rct only
- rctSig genRctSimple(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> &inamounts, const vector<xmr_amount> &outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const std::vector<unsigned int> & index, ctkeyV &outSk) {
+ rctSig genRctSimple(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> &inamounts, const vector<xmr_amount> &outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const keyV &amount_keys, const std::vector<unsigned int> & index, ctkeyV &outSk) {
CHECK_AND_ASSERT_THROW_MES(inamounts.size() > 0, "Empty inamounts");
CHECK_AND_ASSERT_THROW_MES(inamounts.size() == inSk.size(), "Different number of inamounts/inSk");
CHECK_AND_ASSERT_THROW_MES(outamounts.size() == destinations.size(), "Different number of amounts/destinations");
@@ -630,7 +630,7 @@ namespace rct {
//mask amount and mask
rv.ecdhInfo[i].mask = copy(outSk[i].mask);
rv.ecdhInfo[i].amount = d2h(outamounts[i]);
- ecdhEncode(rv.ecdhInfo[i], destinations[i]);
+ ecdhEncodeFromSharedSecret(rv.ecdhInfo[i], amount_keys[i]);
}
//set txn fee
@@ -656,7 +656,7 @@ namespace rct {
return rv;
}
- rctSig genRctSimple(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> &inamounts, const vector<xmr_amount> &outamounts, xmr_amount txnFee, unsigned int mixin) {
+ rctSig genRctSimple(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> &inamounts, const vector<xmr_amount> &outamounts, const keyV &amount_keys, xmr_amount txnFee, unsigned int mixin) {
std::vector<unsigned int> index;
index.resize(inPk.size());
ctkeyM mixRing;
@@ -666,7 +666,7 @@ namespace rct {
mixRing[i].resize(mixin+1);
index[i] = populateFromBlockchainSimple(mixRing[i], inPk[i], mixin);
}
- return genRctSimple(message, inSk, destinations, inamounts, outamounts, txnFee, mixRing, index, outSk);
+ return genRctSimple(message, inSk, destinations, inamounts, outamounts, txnFee, mixRing, amount_keys, index, outSk);
}
//RingCT protocol
@@ -782,7 +782,7 @@ namespace rct {
//decodeRct: (c.f. http://eprint.iacr.org/2015/1098 section 5.1.1)
// uses the attached ecdh info to find the amounts represented by each output commitment
// must know the destination private key to find the correct amount, else will return a random number
- xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask) {
+ static xmr_amount decodeRctMain(const rctSig & rv, const key & sk, unsigned int i, key & mask, void (*decode)(ecdhTuple&, const key&)) {
CHECK_AND_ASSERT_MES(!rv.simple, false, "decodeRct called on simple rctSig");
CHECK_AND_ASSERT_THROW_MES(rv.rangeSigs.size() > 0, "Empty rv.rangeSigs");
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.rangeSigs");
@@ -790,7 +790,7 @@ namespace rct {
//mask amount and mask
ecdhTuple ecdh_info = rv.ecdhInfo[i];
- ecdhDecode(ecdh_info, sk);
+ (*decode)(ecdh_info, sk);
mask = ecdh_info.mask;
key amount = ecdh_info.amount;
key C = rv.outPk[i].mask;
@@ -806,12 +806,20 @@ namespace rct {
return h2d(amount);
}
+ xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask) {
+ return decodeRctMain(rv, sk, i, mask, &ecdhDecode);
+ }
+
+ xmr_amount decodeRctFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key & mask) {
+ return decodeRctMain(rv, sk, i, mask, &ecdhDecodeFromSharedSecret);
+ }
+
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i) {
key mask;
return decodeRct(rv, sk, i, mask);
}
- xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask) {
+ static xmr_amount decodeRctSimpleMain(const rctSig & rv, const key & sk, unsigned int i, key &mask, void (*decode)(ecdhTuple &ecdh, const key&)) {
CHECK_AND_ASSERT_MES(rv.simple, false, "decodeRct called on non simple rctSig");
CHECK_AND_ASSERT_THROW_MES(rv.rangeSigs.size() > 0, "Empty rv.rangeSigs");
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.rangeSigs");
@@ -819,7 +827,7 @@ namespace rct {
//mask amount and mask
ecdhTuple ecdh_info = rv.ecdhInfo[i];
- ecdhDecode(ecdh_info, sk);
+ (*decode)(ecdh_info, sk);
mask = ecdh_info.mask;
key amount = ecdh_info.amount;
key C = rv.outPk[i].mask;
@@ -835,6 +843,14 @@ namespace rct {
return h2d(amount);
}
+ xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask) {
+ return decodeRctSimpleMain(rv, sk, i, mask, &ecdhDecode);
+ }
+
+ xmr_amount decodeRctSimpleFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key &mask) {
+ return decodeRctSimpleMain(rv, sk, i, mask, &ecdhDecodeFromSharedSecret);
+ }
+
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i) {
key mask;
return decodeRctSimple(rv, sk, i, mask);
diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h
index 2064962c3..d150e7180 100644
--- a/src/ringct/rctSigs.h
+++ b/src/ringct/rctSigs.h
@@ -135,18 +135,20 @@ namespace rct {
//decodeRct: (c.f. http://eprint.iacr.org/2015/1098 section 5.1.1)
// uses the attached ecdh info to find the amounts represented by each output commitment
// must know the destination private key to find the correct amount, else will return a random number
- rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & amounts, const ctkeyM &mixRing, unsigned int index, ctkeyV &outSk);
- rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> & amounts, const int mixin);
- rctSig genRctSimple(const key & message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> & inamounts, const vector<xmr_amount> & outamounts, xmr_amount txnFee, unsigned int mixin);
- rctSig genRctSimple(const key & message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & inamounts, const vector<xmr_amount> & outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const std::vector<unsigned int> & index, ctkeyV &outSk);
+ rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & amounts, const ctkeyM &mixRing, const keyV &amount_keys, unsigned int index, ctkeyV &outSk);
+ rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> & amounts, const keyV &amount_keys, const int mixin);
+ rctSig genRctSimple(const key & message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> & inamounts, const vector<xmr_amount> & outamounts, const keyV &amount_keys, xmr_amount txnFee, unsigned int mixin);
+ rctSig genRctSimple(const key & message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & inamounts, const vector<xmr_amount> & outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const keyV &amount_keys, const std::vector<unsigned int> & index, ctkeyV &outSk);
bool verRct(const rctSig & rv);
bool verRct(const rctSig & rv, const ctkeyM &mixRing, const keyV &II, const ctkeyV &outPk, const key &message);
bool verRctSimple(const rctSig & rv);
bool verRctSimple(const rctSig & rv, const ctkeyM &mixRing, const std::vector<keyV> *II, const ctkeyV &outPk, const key &message);
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask);
+ xmr_amount decodeRctFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key & mask);
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i);
- xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i);
+ xmr_amount decodeRctSimpleFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key & mask);
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key & mask);
+ xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i);
}
#endif /* RCTSIGS_H */
diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h
index 7e31f679d..d36d3f1b1 100644
--- a/src/ringct/rctTypes.h
+++ b/src/ringct/rctTypes.h
@@ -341,6 +341,8 @@ namespace rct {
namespace cryptonote {
static inline bool operator==(const crypto::public_key &k0, const rct::key &k1) { return !memcmp(&k0, &k1, 32); }
static inline bool operator!=(const crypto::public_key &k0, const rct::key &k1) { return memcmp(&k0, &k1, 32); }
+ static inline bool operator==(const crypto::secret_key &k0, const rct::key &k1) { return !memcmp(&k0, &k1, 32); }
+ static inline bool operator!=(const crypto::secret_key &k0, const rct::key &k1) { return memcmp(&k0, &k1, 32); }
}
template<typename T> std::ostream &print256(std::ostream &o, const T &v);