diff options
Diffstat (limited to 'src/ringct/rctSigs.cpp')
-rw-r--r-- | src/ringct/rctSigs.cpp | 134 |
1 files changed, 75 insertions, 59 deletions
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index d031f6c79..ca38f13dd 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -237,7 +237,7 @@ namespace rct { // Gen creates a signature which proves that for some column in the keymatrix "pk" // the signer knows a secret key for each row in that column // Ver verifies that the MG sig was created correctly - bool MLSAG_Ver(key message, const keyM & pk, const mgSig & rv, const keyV &II, size_t dsRows) { + bool MLSAG_Ver(key message, const keyM & pk, const mgSig & rv, size_t dsRows) { size_t cols = pk.size(); CHECK_AND_ASSERT_MES(cols >= 2, false, "Error! What is c if cols = 1!"); @@ -246,7 +246,7 @@ namespace rct { for (size_t i = 1; i < cols; ++i) { CHECK_AND_ASSERT_MES(pk[i].size() == rows, false, "pk is not rectangular"); } - CHECK_AND_ASSERT_MES(II.size() == dsRows, false, "Bad II size"); + CHECK_AND_ASSERT_MES(rv.II.size() == dsRows, false, "Bad II size"); CHECK_AND_ASSERT_MES(rv.ss.size() == cols, false, "Bad rv.ss size"); for (size_t i = 0; i < cols; ++i) { CHECK_AND_ASSERT_MES(rv.ss[i].size() == rows, false, "rv.ss is not rectangular"); @@ -258,7 +258,7 @@ namespace rct { key c_old = copy(rv.cc); vector<geDsmp> Ip(dsRows); for (i = 0 ; i < dsRows ; i++) { - precomp(Ip[i].k, II[i]); + precomp(Ip[i].k, rv.II[i]); } size_t ndsRows = 3 * dsRows; //non Double Spendable Rows (see identity chains paper keyV toHash(1 + 3 * dsRows + 2 * (rows - dsRows)); @@ -341,6 +341,43 @@ namespace rct { return (reb && rab); } + key get_pre_mlsag_hash(const rctSig &rv) + { + keyV kv; + kv.push_back(d2h(rv.type)); + kv.push_back(rv.message); + for (auto r: rv.rangeSigs) + { + for (size_t n = 0; n < 64; ++n) + kv.push_back(r.asig.L1[n]); + for (size_t n = 0; n < 64; ++n) + kv.push_back(r.asig.s2[n]); + kv.push_back(r.asig.s); + for (size_t n = 0; n < 64; ++n) + kv.push_back(r.Ci[n]); + } + // no MG/MGs, that's what will sign all this + // no mixRing, it's part of the vin already + for (auto o: rv.pseudoOuts) + { + kv.push_back(o); + } + for (auto i: rv.ecdhInfo) + { + kv.push_back(i.mask); + kv.push_back(i.amount); + // no senderPk, unused here + } + for (auto o: rv.outPk) + { + kv.push_back(o.dest); + kv.push_back(o.mask); + } + kv.push_back(d2h(rv.txnFee)); + + return cn_fast_hash(kv); + } + //Ring-ct MG sigs //Prove: // c.f. http://eprint.iacr.org/2015/1098 section 4. definition 10. @@ -393,10 +430,7 @@ namespace rct { for (size_t j = 0; j < outPk.size(); j++) { sc_sub(sk[rows].bytes, sk[rows].bytes, outSk[j].mask.bytes); //subtract output masks in last row.. } - ctkeyV signed_data = outPk; - signed_data.push_back(ctkey({message, identity()})); - key msg = cn_fast_hash(signed_data); - return MLSAG_Gen(msg, M, sk, index, rows); + return MLSAG_Gen(message, M, sk, index, rows); } @@ -435,7 +469,7 @@ namespace rct { // this shows that sum inputs = sum outputs //Ver: // verifies the above sig is created corretly - bool verRctMG(mgSig mg, const keyV &II, const ctkeyM & pubs, const ctkeyV & outPk, key txnFeeKey, const key &message) { + bool verRctMG(mgSig mg, const ctkeyM & pubs, const ctkeyV & outPk, key txnFeeKey, const key &message) { //setup vars size_t cols = pubs.size(); CHECK_AND_ASSERT_MES(cols >= 1, false, "Empty pubs"); @@ -466,19 +500,14 @@ namespace rct { //subtract txn fee output in last row subKeys(M[i][rows], M[i][rows], txnFeeKey); } - ctkeyV signed_data = outPk; - signed_data.push_back(ctkey({message, identity()})); - key msg = cn_fast_hash(signed_data); - DP("message:"); - DP(msg); - return MLSAG_Ver(msg, M, mg, II, rows); + return MLSAG_Ver(message, M, mg, rows); } //Ring-ct Simple MG sigs //Ver: //This does a simplified version, assuming only post Rct //inputs - bool verRctMGSimple(const key &message, const mgSig &mg, const keyV &II, const ctkeyV & pubs, const key & C) { + bool verRctMGSimple(const key &message, const mgSig &mg, const ctkeyV & pubs, const key & C) { //setup vars size_t rows = 1; size_t cols = pubs.size(); @@ -492,7 +521,7 @@ namespace rct { subKeys(M[i][1], pubs[i].mask, C); } //DP(C); - return MLSAG_Ver(message, M, mg, II, rows); + return MLSAG_Ver(message, M, mg, rows); } //These functions get keys from blockchain @@ -599,8 +628,7 @@ namespace rct { key txnFeeKey = scalarmultH(d2h(rv.txnFee)); rv.mixRing = mixRing; - rv.message = message; - rv.MG = proveRctMG(message, rv.mixRing, inSk, outSk, rv.outPk, index, txnFeeKey); + rv.MG = proveRctMG(get_pre_mlsag_hash(rv), rv.mixRing, inSk, outSk, rv.outPk, index, txnFeeKey); return rv; } @@ -626,7 +654,6 @@ namespace rct { rctSig rv; rv.type = RCTTypeSimple; - rv.message = message; rv.outPk.resize(destinations.size()); rv.rangeSigs.resize(destinations.size()); rv.ecdhInfo.resize(destinations.size()); @@ -661,18 +688,21 @@ namespace rct { rv.pseudoOuts.resize(inamounts.size()); rv.MGs.resize(inamounts.size()); key sumpouts = zero(); //sum pseudoOut masks - key a; + keyV a(inamounts.size()); for (i = 0 ; i < inamounts.size() - 1; i++) { - skGen(a); - sc_add(sumpouts.bytes, a.bytes, sumpouts.bytes); - genC(rv.pseudoOuts[i], a, inamounts[i]); - rv.MGs[i] = proveRctMGSimple(message, rv.mixRing[i], inSk[i], a, rv.pseudoOuts[i], index[i]); + skGen(a[i]); + sc_add(sumpouts.bytes, a[i].bytes, sumpouts.bytes); + genC(rv.pseudoOuts[i], a[i], inamounts[i]); } rv.mixRing = mixRing; - sc_sub(a.bytes, sumout.bytes, sumpouts.bytes); - genC(rv.pseudoOuts[i], a, inamounts[i]); + sc_sub(a[i].bytes, sumout.bytes, sumpouts.bytes); + genC(rv.pseudoOuts[i], a[i], inamounts[i]); DP(rv.pseudoOuts[i]); - rv.MGs[i] = proveRctMGSimple(message, rv.mixRing[i], inSk[i], a, rv.pseudoOuts[i], index[i]); + + key full_message = get_pre_mlsag_hash(rv); + for (i = 0 ; i < inamounts.size(); i++) { + rv.MGs[i] = proveRctMGSimple(full_message, rv.mixRing[i], inSk[i], a[i], rv.pseudoOuts[i], index[i]); + } return rv; } @@ -699,10 +729,10 @@ 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 - bool verRct(const rctSig & rv, const ctkeyM &mixRing, const keyV &II, const ctkeyV &outPk, const key &message) { + bool verRct(const rctSig & rv) { CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "verRct called on non-full rctSig"); - CHECK_AND_ASSERT_MES(outPk.size() == rv.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.rangeSigs"); - CHECK_AND_ASSERT_MES(outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo"); + CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.rangeSigs"); + CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo"); // some rct ops can throw try @@ -711,14 +741,14 @@ namespace rct { bool rvb = true; bool tmp; DP("range proofs verified?"); - for (i = 0; i < outPk.size(); i++) { - tmp = verRange(outPk[i].mask, rv.rangeSigs[i]); + for (i = 0; i < rv.outPk.size(); i++) { + tmp = verRange(rv.outPk[i].mask, rv.rangeSigs[i]); DP(tmp); rvb = (rvb && tmp); } //compute txn fee key txnFeeKey = scalarmultH(d2h(rv.txnFee)); - bool mgVerd = verRctMG(rv.MG, II, mixRing, outPk, txnFeeKey, message); + bool mgVerd = verRctMG(rv.MG, rv.mixRing, rv.outPk, txnFeeKey, get_pre_mlsag_hash(rv)); DP("mg sig verified?"); DP(mgVerd); @@ -729,45 +759,35 @@ namespace rct { return false; } } - bool verRct(const rctSig & rv) { - return verRct(rv, rv.mixRing, rv.MG.II, rv.outPk, rv.message); - } - + //ver RingCT simple //assumes only post-rct style inputs (at least for max anonymity) - bool verRctSimple(const rctSig & rv, const ctkeyM &mixRing, const std::vector<keyV> *II, const ctkeyV &outPk, const key &message) { + bool verRctSimple(const rctSig & rv) { size_t i = 0; bool rvb = true; - + CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "verRctSimple called on non simple rctSig"); - CHECK_AND_ASSERT_MES(outPk.size() == rv.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.rangeSigs"); - CHECK_AND_ASSERT_MES(outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo"); + CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.rangeSigs"); + CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo"); CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.MGs.size(), false, "Mismatched sizes of rv.pseudoOuts and rv.MGs"); - CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == mixRing.size(), false, "Mismatched sizes of rv.pseudoOuts and mixRing"); - CHECK_AND_ASSERT_MES(!II || II->size() == mixRing.size(), false, "Mismatched II/mixRing size"); - if (II) - { - for (size_t n = 0; n < II->size(); ++n) - { - CHECK_AND_ASSERT_MES((*II)[n].size() == 1, false, "Bad II size"); - } - } + CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.pseudoOuts and mixRing"); key sumOutpks = identity(); - for (i = 0; i < outPk.size(); i++) { - if (!verRange(outPk[i].mask, rv.rangeSigs[i])) { + for (i = 0; i < rv.outPk.size(); i++) { + if (!verRange(rv.outPk[i].mask, rv.rangeSigs[i])) { return false; } - addKeys(sumOutpks, sumOutpks, outPk[i].mask); + addKeys(sumOutpks, sumOutpks, rv.outPk[i].mask); } DP(sumOutpks); key txnFeeKey = scalarmultH(d2h(rv.txnFee)); addKeys(sumOutpks, txnFeeKey, sumOutpks); bool tmpb = false; + key message = get_pre_mlsag_hash(rv); key sumPseudoOuts = identity(); - for (i = 0 ; i < mixRing.size() ; i++) { - tmpb = verRctMGSimple(message, rv.MGs[i], II ? (*II)[i] : rv.MGs[i].II, mixRing[i], rv.pseudoOuts[i]); + for (i = 0 ; i < rv.mixRing.size() ; i++) { + tmpb = verRctMGSimple(message, rv.MGs[i], rv.mixRing[i], rv.pseudoOuts[i]); addKeys(sumPseudoOuts, sumPseudoOuts, rv.pseudoOuts[i]); DP(tmpb); if (!tmpb) { @@ -788,10 +808,6 @@ namespace rct { return (rvb && mgVerd); } - bool verRctSimple(const rctSig & rv) { - return verRctSimple(rv, rv.mixRing, NULL, rv.outPk, rv.message); - } - //RingCT protocol //genRct: // creates an rctSig with all data necessary to verify the rangeProofs and that the signer owns one of the |