diff options
author | Shen Noether <Shen.Noether@gmx.com> | 2016-11-17 23:17:21 +0000 |
---|---|---|
committer | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2016-12-04 21:54:11 +0000 |
commit | 76958fc75abc18c928474eea91ac05fd5e0fcb41 (patch) | |
tree | 8644fe15b761d9121c23e67d0cd553505f8a0c04 /src/ringct/rctSigs.cpp | |
parent | Merge pull request #1403 (diff) | |
download | monero-76958fc75abc18c928474eea91ac05fd5e0fcb41.tar.xz |
ringct: switch to Borromean signatures
Diffstat (limited to 'src/ringct/rctSigs.cpp')
-rw-r--r-- | src/ringct/rctSigs.cpp | 145 |
1 files changed, 59 insertions, 86 deletions
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index b773be1e5..fb67c77c4 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -40,94 +40,67 @@ using namespace crypto; using namespace std; namespace rct { - //Schnorr Non-linkable - //Gen Gives a signature (L1, s1, s2) proving that the sender knows "x" such that xG = one of P1 or P2 - //Ver Verifies that signer knows an "x" such that xG = one of P1 or P2 - //These are called in the below ASNL sig generation - - void GenSchnorrNonLinkable(key & L1, key & s1, key & s2, const key & x, const key & P1, const key & P2, unsigned int index) { - key c1, c2, L2; - key a = skGen(); - if (index == 0) { - scalarmultBase(L1, a); - hash_to_scalar(c2, L1); - skGen(s2); - addKeys2(L2, s2, c2, P2); - hash_to_scalar(c1, L2); - //s1 = a - x * c1 - sc_mulsub(s1.bytes, x.bytes, c1.bytes, a.bytes); - } - else if (index == 1) { - scalarmultBase(L2, a); - hash_to_scalar(c1, L2); - skGen(s1); - addKeys2(L1, s1, c1, P1); - hash_to_scalar(c2, L1); - sc_mulsub(s2.bytes, x.bytes, c2.bytes, a.bytes); - } - else { - throw std::runtime_error("GenSchnorrNonLinkable: invalid index (should be 0 or 1)"); + namespace { + struct verRangeWrapper_ { + void operator()(const key & C, const rangeSig & as, bool &result) const { + result = verRange(C, as); } - } + }; + constexpr const verRangeWrapper_ verRangeWrapper{}; - //Schnorr Non-linkable - //Gen Gives a signature (L1, s1, s2) proving that the sender knows "x" such that xG = one of P1 or P2 - //Ver Verifies that signer knows an "x" such that xG = one of P1 or P2 - //These are called in the below ASNL sig generation - bool VerSchnorrNonLinkable(const key & P1, const key & P2, const key & L1, const key & s1, const key & s2) { - key c2, L2, c1, L1p; - hash_to_scalar(c2, L1); - addKeys2(L2, s2, c2, P2); - hash_to_scalar(c1, L2); - addKeys2(L1p, s1, c1, P1); - - return equalKeys(L1, L1p); + struct verRctMGSimpleWrapper_ { + void operator()(const key &message, const mgSig &mg, const ctkeyV & pubs, const key & C, bool &result) const { + result = verRctMGSimple(message, mg, pubs, C); + } + }; + constexpr const verRctMGSimpleWrapper_ verRctMGSimpleWrapper{}; } - //Aggregate Schnorr Non-linkable Ring Signature (ASNL) - // c.f. http://eprint.iacr.org/2015/1098 section 5. - // These are used in range proofs (alternatively Borromean could be used) - // Gen gives a signature which proves the signer knows, for each i, - // an x[i] such that x[i]G = one of P1[i] or P2[i] - // Ver Verifies the signer knows a key for one of P1[i], P2[i] at each i - asnlSig GenASNL(key64 x, key64 P1, key64 P2, bits indices) { - DP("Generating Aggregate Schnorr Non-linkable Ring Signature\n"); - key64 s1; - int j = 0; - asnlSig rv; - rv.s = zero(); - for (j = 0; j < ATOMS; j++) { - GenSchnorrNonLinkable(rv.L1[j], s1[j], rv.s2[j], x[j], P1[j], P2[j], indices[j]); - sc_add(rv.s.bytes, rv.s.bytes, s1[j].bytes); + //Borromean (c.f. gmax/andytoshi's paper) + boroSig genBorromean(const key64 x, const key64 P1, const key64 P2, const bits indices) { + key64 L[2], c[2], s[2], alpha, P[2]; + int naught = 0, prime = 0, ii = 0, jj=0; + for (ii = 0 ; ii < 64 ; ii++) { + naught = indices[ii]; prime = (indices[ii] + 1) % 2; + copy(P[0][ii], P1[ii]); //could probably user pointers + copy(P[1][ii], P2[ii]); + skGen(alpha[ii]); + scalarmultBase(L[naught][ii], alpha[ii]); + c[prime][ii] = hash_to_scalar(L[naught][ii]); + skGen(s[prime][ii]); + addKeys2(L[prime][ii], s[prime][ii], c[prime][ii], P[prime][ii]); + } + boroSig bb; + bb.ee = cn_fast_hash(L[1]); //or L[1].. + key LL, cc; + for (jj = 0 ; jj < 64 ; jj++) { + naught = indices[jj]; prime = (indices[jj] + 1) % 2; + if (!indices[jj]) { + sc_mulsub(bb.s0[jj].bytes, x[jj].bytes, bb.ee.bytes, alpha[jj].bytes); + copy(bb.s1[jj], s[1][jj]); + } else { + copy(bb.s0[jj], s[0][jj]); + addKeys2(LL, bb.s0[jj], bb.ee, P[0][jj]); //different L0 + cc = hash_to_scalar(LL); + sc_mulsub(bb.s1[jj].bytes, x[jj].bytes, cc.bytes, alpha[jj].bytes); + } } - return rv; - } - - //Aggregate Schnorr Non-linkable Ring Signature (ASNL) - // c.f. http://eprint.iacr.org/2015/1098 section 5. - // These are used in range proofs (alternatively Borromean could be used) - // Gen gives a signature which proves the signer knows, for each i, - // an x[i] such that x[i]G = one of P1[i] or P2[i] - // Ver Verifies the signer knows a key for one of P1[i], P2[i] at each i - bool VerASNL(const key64 P1, const key64 P2, const asnlSig &as) { - PERF_TIMER(VerASNL); - DP("Verifying Aggregate Schnorr Non-linkable Ring Signature\n"); - key LHS = identity(); - key RHS = scalarmultBase(as.s); - key c2, L2, c1; - int j = 0; - for (j = 0; j < ATOMS; j++) { - hash_to_scalar(c2, as.L1[j]); - addKeys2(L2, as.s2[j], c2, P2[j]); - addKeys(LHS, LHS, as.L1[j]); - hash_to_scalar(c1, L2); - addKeys(RHS, RHS, scalarmultKey(P1[j], c1)); - } - key cc; - sc_sub(cc.bytes, LHS.bytes, RHS.bytes); - return sc_isnonzero(cc.bytes) == 0; + return bb; } + //see above. + bool verifyBorromean(const boroSig &bb, const key64 P1, const key64 P2) { + key64 Lv1, chash; key LL; + int ii = 0; + for (ii = 0 ; ii < 64 ; ii++) { + addKeys2(LL, bb.s0[ii], bb.ee, P1[ii]); + chash[ii] = hash_to_scalar(LL); + addKeys2(Lv1[ii], bb.s1[ii], chash[ii], P2[ii]); + } + key eeComputed = cn_fast_hash(Lv1); //hash function fine + return equalKeys(eeComputed, bb.ee); + } + //Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures) //These are aka MG signatutes in earlier drafts of the ring ct paper // c.f. http://eprint.iacr.org/2015/1098 section 2. @@ -323,7 +296,7 @@ namespace rct { sc_add(mask.bytes, mask.bytes, ai[i].bytes); addKeys(C, C, sig.Ci[i]); } - sig.asig = GenASNL(ai, sig.Ci, CiH, b); + sig.asig = genBorromean(ai, sig.Ci, CiH, b); return sig; } @@ -345,7 +318,7 @@ namespace rct { } if (!equalKeys(C, Ctmp)) return false; - if (!VerASNL(as.Ci, CiH, as.asig)) + if (!verifyBorromean(as.asig, as.Ci, CiH)) return false; return true; } @@ -371,10 +344,10 @@ namespace rct { for (auto r: rv.p.rangeSigs) { for (size_t n = 0; n < 64; ++n) - kv.push_back(r.asig.L1[n]); + kv.push_back(r.asig.s0[n]); for (size_t n = 0; n < 64; ++n) - kv.push_back(r.asig.s2[n]); - kv.push_back(r.asig.s); + kv.push_back(r.asig.s1[n]); + kv.push_back(r.asig.ee); for (size_t n = 0; n < 64; ++n) kv.push_back(r.Ci[n]); } |