From 82ee01699c2b910e44fd7362bd47d3a1cc9c26af Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 9 Jun 2019 13:02:16 +0000 Subject: Integrate CLSAGs into monero They are allowed from v12, and MLSAGs are rejected from v13. --- tests/unit_tests/ringct.cpp | 164 +++++++++++++++++++++++++++++++++++++ tests/unit_tests/serialization.cpp | 22 ++++- 2 files changed, 185 insertions(+), 1 deletion(-) (limited to 'tests/unit_tests') diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp index 807bab64a..75fe9ecfb 100644 --- a/tests/unit_tests/ringct.cpp +++ b/tests/unit_tests/ringct.cpp @@ -38,6 +38,7 @@ #include "ringct/rctSigs.h" #include "ringct/rctOps.h" #include "device/device.hpp" +#include "string_tools.h" using namespace std; using namespace crypto; @@ -137,6 +138,169 @@ TEST(ringct, MG_sigs) ASSERT_FALSE(MLSAG_Ver(message, P, IIccss, R)); } +TEST(ringct, CLSAG) +{ + const size_t ring_size = 11; + const size_t idx = 5; + keyV P, C; + key p, z; + const key message = identity(); + key backup; + clsag clsag; + + for (size_t i = 0; i < ring_size; ++i) + { + key Sk, Pk; + skpkGen(Sk, Pk); + P.push_back(Pk); + skpkGen(Sk, Pk); + C.push_back(Pk); + } + skpkGen(p, P[idx]); + skpkGen(z, C[idx]); + + // bad p at creation + clsag = CLSAG_Gen(zero(), P, p, C, z, idx); //, hw::get_device("default")); + ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag)); + + // bad index at creation + try + { + clsag = CLSAG_Gen(message, P, p, C, z, (idx + 1) % ring_size); //, hw::get_device("default")); + ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag)); + } + catch (...) { /* either exception, or failure to verify above */ } + + // bad z at creation + try + { + clsag = CLSAG_Gen(message, P, p, C, skGen(), idx); //, hw::get_device("default")); + ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag)); + } + catch (...) { /* either exception, or failure to verify above */ } + + // bad C at creation + backup = C[idx]; + C[idx] = scalarmultBase(skGen()); + try + { + clsag = CLSAG_Gen(message, P, p, C, z, idx); //, hw::get_device("default")); + ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag)); + } + catch (...) { /* either exception, or failure to verify above */ } + C[idx] = backup; + + // bad p at creation + try + { + clsag = CLSAG_Gen(message, P, skGen(), C, z, idx); //, hw::get_device("default")); + ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag)); + } + catch (...) { /* either exception, or failure to verify above */ } + + // bad P at creation + backup = P[idx]; + P[idx] = scalarmultBase(skGen()); + try + { + clsag = CLSAG_Gen(message, P, p, C, z, idx); //, hw::get_device("default")); + ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag)); + } + catch (...) { /* either exception, or failure to verify above */ } + P[idx] = backup; + + // good + clsag = CLSAG_Gen(message, P, p, C, z, idx); //, hw::get_device("default")); + ASSERT_TRUE(CLSAG_Ver(message, P, C, clsag)); + + // bad message at verification + ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag)); + + // bad real P at verification + backup = P[idx]; + P[idx] = scalarmultBase(skGen()); + ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag)); + P[idx] = backup; + + // bad fake P at verification + backup = P[(idx + 1) % ring_size]; + P[(idx + 1) % ring_size] = scalarmultBase(skGen()); + ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag)); + P[(idx + 1) % ring_size] = backup; + + // bad real C at verification + backup = C[idx]; + C[idx] = scalarmultBase(skGen()); + ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag)); + C[idx] = backup; + + // bad fake C at verification + backup = C[(idx + 1) % ring_size]; + C[(idx + 1) % ring_size] = scalarmultBase(skGen()); + ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag)); + C[(idx + 1) % ring_size] = backup; + + // empty s + auto sbackup = clsag.s; + clsag.s.clear(); + ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); + clsag.s = sbackup; + + // too few s elements + backup = clsag.s.back(); + clsag.s.pop_back(); + ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); + clsag.s.push_back(backup); + + // too many s elements + clsag.s.push_back(skGen()); + ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); + clsag.s.pop_back(); + + // bad s in clsag at verification + for (auto &s: clsag.s) + { + backup = s; + s = skGen(); + ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); + s = backup; + } + + // bad c1 in clsag at verification + backup = clsag.c1; + clsag.c1 = skGen(); + ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); + clsag.c1 = backup; + + // bad I in clsag at verification + backup = clsag.I; + clsag.I = scalarmultBase(skGen()); + ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); + clsag.I = backup; + + // bad D in clsag at verification + backup = clsag.D; + clsag.D = scalarmultBase(skGen()); + ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); + clsag.D = backup; + + // D not in main subgroup in clsag at verification + backup = clsag.D; + rct::key x; + ASSERT_TRUE(epee::string_tools::hex_to_pod("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", x)); + clsag.D = rct::addKeys(clsag.D, x); + ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); + clsag.D = backup; + + // swapped I and D in clsag at verification + std::swap(clsag.I, clsag.D); + ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); + std::swap(clsag.I, clsag.D); + + // check it's still good, in case we failed to restore + ASSERT_TRUE(CLSAG_Ver(message, P, C, clsag)); +} + TEST(ringct, range_proofs) { //Ring CT Stuff diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index e730f6867..7b8a291d0 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -477,6 +477,7 @@ TEST(Serialization, serializes_ringct_types) rct::ecdhTuple ecdh0, ecdh1; rct::boroSig boro0, boro1; rct::mgSig mg0, mg1; + rct::clsag clsag0, clsag1; rct::Bulletproof bp0, bp1; rct::rctSig s0, s1; cryptonote::transaction tx0, tx1; @@ -592,9 +593,11 @@ TEST(Serialization, serializes_ringct_types) rct::skpkGen(Sk, Pk); destinations.push_back(Pk); //compute rct data with mixin 3 - const rct::RCTConfig rct_config{ rct::RangeProofPaddedBulletproof, 0 }; + const rct::RCTConfig rct_config{ rct::RangeProofPaddedBulletproof, 2 }; s0 = rct::genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 0, 3, rct_config, hw::get_device("default")); + ASSERT_FALSE(s0.p.MGs.empty()); + ASSERT_TRUE(s0.p.CLSAGs.empty()); mg0 = s0.p.MGs[0]; ASSERT_TRUE(serialization::dump_binary(mg0, blob)); ASSERT_TRUE(serialization::parse_binary(blob, mg1)); @@ -614,6 +617,23 @@ TEST(Serialization, serializes_ringct_types) ASSERT_TRUE(serialization::parse_binary(blob, bp1)); bp1.V = bp0.V; // this is not saved, as it is reconstructed from other tx data ASSERT_EQ(bp0, bp1); + + const rct::RCTConfig rct_config_clsag{ rct::RangeProofPaddedBulletproof, 3 }; + s0 = rct::genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 0, 3, rct_config_clsag, hw::get_device("default")); + + ASSERT_FALSE(s0.p.CLSAGs.empty()); + ASSERT_TRUE(s0.p.MGs.empty()); + clsag0 = s0.p.CLSAGs[0]; + ASSERT_TRUE(serialization::dump_binary(clsag0, blob)); + ASSERT_TRUE(serialization::parse_binary(blob, clsag1)); + ASSERT_TRUE(clsag0.s.size() == clsag1.s.size()); + for (size_t n = 0; n < clsag0.s.size(); ++n) + { + ASSERT_TRUE(clsag0.s[n] == clsag1.s[n]); + } + ASSERT_TRUE(clsag0.c1 == clsag1.c1); + // I is not serialized, they are meant to be reconstructed + ASSERT_TRUE(clsag0.D == clsag1.D); } TEST(Serialization, portability_wallet) -- cgit v1.2.3