mirror of
				https://git.wownero.com/wownero/wownero.git
				synced 2024-08-15 01:03:23 +00:00 
			
		
		
		
	bulletproofs: reject points not in the main subgroup
This commit is contained in:
		
							parent
							
								
									1569717718
								
							
						
					
					
						commit
						c429176248
					
				
					 6 changed files with 97 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -922,6 +922,19 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
 | 
			
		|||
  for (const Bulletproof *p: proofs)
 | 
			
		||||
  {
 | 
			
		||||
    const Bulletproof &proof = *p;
 | 
			
		||||
 | 
			
		||||
    // check subgroup
 | 
			
		||||
    for (const rct::key &k: proof.V)
 | 
			
		||||
      CHECK_AND_ASSERT_MES(rct::isInMainSubgroup(k), false, "Input point not in subgroup");
 | 
			
		||||
    for (const rct::key &k: proof.L)
 | 
			
		||||
      CHECK_AND_ASSERT_MES(rct::isInMainSubgroup(k), false, "Input point not in subgroup");
 | 
			
		||||
    for (const rct::key &k: proof.R)
 | 
			
		||||
      CHECK_AND_ASSERT_MES(rct::isInMainSubgroup(k), false, "Input point not in subgroup");
 | 
			
		||||
    CHECK_AND_ASSERT_MES(rct::isInMainSubgroup(proof.A), false, "Input point not in subgroup");
 | 
			
		||||
    CHECK_AND_ASSERT_MES(rct::isInMainSubgroup(proof.S), false, "Input point not in subgroup");
 | 
			
		||||
    CHECK_AND_ASSERT_MES(rct::isInMainSubgroup(proof.T1), false, "Input point not in subgroup");
 | 
			
		||||
    CHECK_AND_ASSERT_MES(rct::isInMainSubgroup(proof.T2), false, "Input point not in subgroup");
 | 
			
		||||
 | 
			
		||||
    CHECK_AND_ASSERT_MES(proof.V.size() >= 1, false, "V does not have at least one element");
 | 
			
		||||
    CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), false, "Mismatched L and R sizes");
 | 
			
		||||
    CHECK_AND_ASSERT_MES(proof.L.size() > 0, false, "Empty proof");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,6 +60,17 @@ namespace rct {
 | 
			
		|||
 | 
			
		||||
    //Various key generation functions
 | 
			
		||||
 | 
			
		||||
    bool toPointCheckOrder(ge_p3 *P, const unsigned char *data)
 | 
			
		||||
    {
 | 
			
		||||
        if (ge_frombytes_vartime(P, data))
 | 
			
		||||
            return false;
 | 
			
		||||
        ge_p2 R;
 | 
			
		||||
        ge_scalarmult(&R, curveOrder().bytes, P);
 | 
			
		||||
        key tmp;
 | 
			
		||||
        ge_tobytes(tmp.bytes, &R);
 | 
			
		||||
        return tmp == identity();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //generates a random scalar which can be used as a secret key or mask
 | 
			
		||||
    void skGen(key &sk) {
 | 
			
		||||
        random32_unbiased(sk.bytes);
 | 
			
		||||
| 
						 | 
				
			
			@ -200,6 +211,12 @@ namespace rct {
 | 
			
		|||
        return aP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //Computes aL where L is the curve order
 | 
			
		||||
    bool isInMainSubgroup(const key & a) {
 | 
			
		||||
        ge_p3 p3;
 | 
			
		||||
        return toPointCheckOrder(&p3, a.bytes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //Curve addition / subtractions
 | 
			
		||||
 | 
			
		||||
    //for curve points: AB = A + B
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -83,6 +83,7 @@ namespace rct {
 | 
			
		|||
    keyM keyMInit(size_t rows, size_t cols);
 | 
			
		||||
 | 
			
		||||
    //Various key generation functions        
 | 
			
		||||
    bool toPointCheckOrder(ge_p3 *P, const unsigned char *data);
 | 
			
		||||
 | 
			
		||||
    //generates a random scalar which can be used as a secret key or mask
 | 
			
		||||
    key skGen();
 | 
			
		||||
| 
						 | 
				
			
			@ -119,6 +120,8 @@ namespace rct {
 | 
			
		|||
    key scalarmultKey(const key &P, const key &a);
 | 
			
		||||
    //Computes aH where H= toPoint(cn_fast_hash(G)), G the basepoint
 | 
			
		||||
    key scalarmultH(const key & a);
 | 
			
		||||
    // checks a is in the main subgroup (ie, not a small one)
 | 
			
		||||
    bool isInMainSubgroup(const key & a);
 | 
			
		||||
 | 
			
		||||
    //Curve addition / subtractions
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,6 +51,7 @@ enum test_op
 | 
			
		|||
  op_addKeys2,
 | 
			
		||||
  op_addKeys3,
 | 
			
		||||
  op_addKeys3_2,
 | 
			
		||||
  op_isInMainSubgroup,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<test_op op>
 | 
			
		||||
| 
						 | 
				
			
			@ -102,6 +103,7 @@ public:
 | 
			
		|||
      case op_addKeys2: rct::addKeys2(key, scalar0, scalar1, point0); break;
 | 
			
		||||
      case op_addKeys3: rct::addKeys3(key, scalar0, point0, scalar1, precomp1); break;
 | 
			
		||||
      case op_addKeys3_2: rct::addKeys3(key, scalar0, precomp0, scalar1, precomp1); break;
 | 
			
		||||
      case op_isInMainSubgroup: rct::isInMainSubgroup(point0); break;
 | 
			
		||||
      default: return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -237,6 +237,7 @@ int main(int argc, char** argv)
 | 
			
		|||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys2);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys3);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys3_2);
 | 
			
		||||
  TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_isInMainSubgroup);
 | 
			
		||||
 | 
			
		||||
  TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 2);
 | 
			
		||||
  TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 4);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@
 | 
			
		|||
 | 
			
		||||
#include "gtest/gtest.h"
 | 
			
		||||
 | 
			
		||||
#include "string_tools.h"
 | 
			
		||||
#include "ringct/rctOps.h"
 | 
			
		||||
#include "ringct/rctSigs.h"
 | 
			
		||||
#include "ringct/bulletproofs.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -193,3 +194,63 @@ TEST(bulletproofs, invalid_gamma_ff)
 | 
			
		|||
  rct::Bulletproof proof = bulletproof_PROVE(invalid_amount, gamma);
 | 
			
		||||
  ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char * const torsion_elements[] =
 | 
			
		||||
{
 | 
			
		||||
  "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa",
 | 
			
		||||
  "0000000000000000000000000000000000000000000000000000000000000000",
 | 
			
		||||
  "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85",
 | 
			
		||||
  "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
 | 
			
		||||
  "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05",
 | 
			
		||||
  "0000000000000000000000000000000000000000000000000000000000000080",
 | 
			
		||||
  "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TEST(bulletproofs, invalid_torsion)
 | 
			
		||||
{
 | 
			
		||||
  rct::Bulletproof proof = bulletproof_PROVE(7329838943733, rct::skGen());
 | 
			
		||||
  ASSERT_TRUE(rct::bulletproof_VERIFY(proof));
 | 
			
		||||
  for (const auto &xs: torsion_elements)
 | 
			
		||||
  {
 | 
			
		||||
    rct::key x;
 | 
			
		||||
    ASSERT_TRUE(epee::string_tools::hex_to_pod(xs, x));
 | 
			
		||||
    ASSERT_FALSE(rct::isInMainSubgroup(x));
 | 
			
		||||
    for (auto &k: proof.V)
 | 
			
		||||
    {
 | 
			
		||||
      const rct::key org_k = k;
 | 
			
		||||
      rct::addKeys(k, org_k, x);
 | 
			
		||||
      ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
 | 
			
		||||
      k = org_k;
 | 
			
		||||
    }
 | 
			
		||||
    for (auto &k: proof.L)
 | 
			
		||||
    {
 | 
			
		||||
      const rct::key org_k = k;
 | 
			
		||||
      rct::addKeys(k, org_k, x);
 | 
			
		||||
      ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
 | 
			
		||||
      k = org_k;
 | 
			
		||||
    }
 | 
			
		||||
    for (auto &k: proof.R)
 | 
			
		||||
    {
 | 
			
		||||
      const rct::key org_k = k;
 | 
			
		||||
      rct::addKeys(k, org_k, x);
 | 
			
		||||
      ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
 | 
			
		||||
      k = org_k;
 | 
			
		||||
    }
 | 
			
		||||
    const rct::key org_A = proof.A;
 | 
			
		||||
    rct::addKeys(proof.A, org_A, x);
 | 
			
		||||
    ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
 | 
			
		||||
    proof.A = org_A;
 | 
			
		||||
    const rct::key org_S = proof.S;
 | 
			
		||||
    rct::addKeys(proof.S, org_S, x);
 | 
			
		||||
    ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
 | 
			
		||||
    proof.S = org_S;
 | 
			
		||||
    const rct::key org_T1 = proof.T1;
 | 
			
		||||
    rct::addKeys(proof.T1, org_T1, x);
 | 
			
		||||
    ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
 | 
			
		||||
    proof.T1 = org_T1;
 | 
			
		||||
    const rct::key org_T2 = proof.T2;
 | 
			
		||||
    rct::addKeys(proof.T2, org_T2, x);
 | 
			
		||||
    ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
 | 
			
		||||
    proof.T2 = org_T2;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue