aboutsummaryrefslogtreecommitdiff
path: root/tests/unit_tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit_tests')
-rw-r--r--tests/unit_tests/multiexp.cpp62
-rw-r--r--tests/unit_tests/ringct.cpp162
-rw-r--r--tests/unit_tests/serialization.cpp22
3 files changed, 245 insertions, 1 deletions
diff --git a/tests/unit_tests/multiexp.cpp b/tests/unit_tests/multiexp.cpp
index f12dd6b49..722c568da 100644
--- a/tests/unit_tests/multiexp.cpp
+++ b/tests/unit_tests/multiexp.cpp
@@ -252,3 +252,65 @@ TEST(multiexp, pippenger_cached)
ASSERT_TRUE(basic(data) == pippenger(data, cache));
}
}
+
+TEST(multiexp, scalarmult_triple)
+{
+ std::vector<rct::MultiexpData> data;
+ ge_p2 p2;
+ rct::key res;
+ ge_p3 Gp3;
+
+ ge_frombytes_vartime(&Gp3, rct::G.bytes);
+
+ static const rct::key scalars[] = {
+ rct::Z,
+ rct::I,
+ rct::L,
+ rct::EIGHT,
+ rct::INV_EIGHT,
+ };
+ static const ge_p3 points[] = {
+ ge_p3_identity,
+ ge_p3_H,
+ Gp3,
+ };
+ ge_dsmp ppre[sizeof(points) / sizeof(points[0])];
+
+ for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); ++i)
+ ge_dsm_precomp(ppre[i], &points[i]);
+
+ data.resize(3);
+ for (const rct::key &x: scalars)
+ {
+ data[0].scalar = x;
+ for (const rct::key &y: scalars)
+ {
+ data[1].scalar = y;
+ for (const rct::key &z: scalars)
+ {
+ data[2].scalar = z;
+ for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); ++i)
+ {
+ data[1].point = points[i];
+ for (size_t j = 0; j < sizeof(points) / sizeof(points[0]); ++j)
+ {
+ data[0].point = Gp3;
+ data[2].point = points[j];
+
+ ge_triple_scalarmult_base_vartime(&p2, data[0].scalar.bytes, data[1].scalar.bytes, ppre[i], data[2].scalar.bytes, ppre[j]);
+ ge_tobytes(res.bytes, &p2);
+ ASSERT_TRUE(basic(data) == res);
+
+ for (size_t k = 0; k < sizeof(points) / sizeof(points[0]); ++k)
+ {
+ data[0].point = points[k];
+ ge_triple_scalarmult_precomp_vartime(&p2, data[0].scalar.bytes, ppre[k], data[1].scalar.bytes, ppre[i], data[2].scalar.bytes, ppre[j]);
+ ge_tobytes(res.bytes, &p2);
+ ASSERT_TRUE(basic(data) == res);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp
index 807bab64a..2388d647b 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,167 @@ TEST(ringct, MG_sigs)
ASSERT_FALSE(MLSAG_Ver(message, P, IIccss, R));
}
+TEST(ringct, CLSAG)
+{
+ const size_t N = 11;
+ const size_t idx = 5;
+ ctkeyV pubs;
+ key p, t, t2, u;
+ const key message = identity();
+ ctkey backup;
+ clsag clsag;
+
+ for (size_t i = 0; i < N; ++i)
+ {
+ key sk;
+ ctkey tmp;
+
+ skpkGen(sk, tmp.dest);
+ skpkGen(sk, tmp.mask);
+
+ pubs.push_back(tmp);
+ }
+
+ // Set P[idx]
+ skpkGen(p, pubs[idx].dest);
+
+ // Set C[idx]
+ t = skGen();
+ u = skGen();
+ addKeys2(pubs[idx].mask,t,u,H);
+
+ // Set commitment offset
+ key Cout;
+ t2 = skGen();
+ addKeys2(Cout,t2,u,H);
+
+ // Prepare generation inputs
+ ctkey insk;
+ insk.dest = p;
+ insk.mask = t;
+
+ // bad message
+ clsag = rct::proveRctCLSAGSimple(zero(),pubs,insk,t2,Cout,NULL,NULL,NULL,idx,hw::get_device("default"));
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+
+ // bad index at creation
+ try
+ {
+ clsag = rct::proveRctCLSAGSimple(message,pubs,insk,t2,Cout,NULL,NULL,NULL,(idx + 1) % N,hw::get_device("default"));
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ }
+ catch (...) { /* either exception, or failure to verify above */ }
+
+ // bad z at creation
+ try
+ {
+ ctkey insk2;
+ insk2.dest = insk.dest;
+ insk2.mask = skGen();
+ clsag = rct::proveRctCLSAGSimple(message,pubs,insk2,t2,Cout,NULL,NULL,NULL,idx,hw::get_device("default"));
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ }
+ catch (...) { /* either exception, or failure to verify above */ }
+
+ // bad C at creation
+ backup = pubs[idx];
+ pubs[idx].mask = scalarmultBase(skGen());
+ try
+ {
+ clsag = rct::proveRctCLSAGSimple(message,pubs,insk,t2,Cout,NULL,NULL,NULL,idx,hw::get_device("default"));
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ }
+ catch (...) { /* either exception, or failure to verify above */ }
+ pubs[idx] = backup;
+
+ // bad p at creation
+ try
+ {
+ ctkey insk2;
+ insk2.dest = skGen();
+ insk2.mask = insk.mask;
+ clsag = rct::proveRctCLSAGSimple(message,pubs,insk2,t2,Cout,NULL,NULL,NULL,idx,hw::get_device("default"));
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ }
+ catch (...) { /* either exception, or failure to verify above */ }
+
+ // bad P at creation
+ backup = pubs[idx];
+ pubs[idx].dest = scalarmultBase(skGen());
+ try
+ {
+ clsag = rct::proveRctCLSAGSimple(message,pubs,insk,t2,Cout,NULL,NULL,NULL,idx,hw::get_device("default"));
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ }
+ catch (...) { /* either exception, or failure to verify above */ }
+ pubs[idx] = backup;
+
+ // Test correct signature
+ clsag = rct::proveRctCLSAGSimple(message,pubs,insk,t2,Cout,NULL,NULL,NULL,idx,hw::get_device("default"));
+ ASSERT_TRUE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+
+ // empty s
+ auto sbackup = clsag.s;
+ clsag.s.clear();
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ clsag.s = sbackup;
+
+ // too few s elements
+ key backup_key;
+ backup_key = clsag.s.back();
+ clsag.s.pop_back();
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ clsag.s.push_back(backup_key);
+
+ // too many s elements
+ clsag.s.push_back(skGen());
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ clsag.s.pop_back();
+
+ // bad s in clsag at verification
+ for (auto &s: clsag.s)
+ {
+ backup_key = s;
+ s = skGen();
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ s = backup_key;
+ }
+
+ // bad c1 in clsag at verification
+ backup_key = clsag.c1;
+ clsag.c1 = skGen();
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ clsag.c1 = backup_key;
+
+ // bad I in clsag at verification
+ backup_key = clsag.I;
+ clsag.I = scalarmultBase(skGen());
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ clsag.I = backup_key;
+
+ // bad D in clsag at verification
+ backup_key = clsag.D;
+ clsag.D = scalarmultBase(skGen());
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ clsag.D = backup_key;
+
+ // D not in main subgroup in clsag at verification
+ backup_key = clsag.D;
+ rct::key x;
+ ASSERT_TRUE(epee::string_tools::hex_to_pod("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", x));
+ clsag.D = rct::addKeys(clsag.D, x);
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ clsag.D = backup_key;
+
+ // swapped I and D in clsag at verification
+ std::swap(clsag.I, clsag.D);
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ std::swap(clsag.I, clsag.D);
+
+ // check it's still good, in case we failed to restore
+ ASSERT_TRUE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+}
+
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)