diff --git a/src/crypto/one_out_of_many_proofs.cpp b/src/crypto/one_out_of_many_proofs.cpp index 7aed4519..77cc4006 100644 --- a/src/crypto/one_out_of_many_proofs.cpp +++ b/src/crypto/one_out_of_many_proofs.cpp @@ -9,7 +9,7 @@ //DISABLE_GCC_AND_CLANG_WARNING(unused-function) -#if 1 +#if 0 # define DBG_VAL_PRINT(x) std::cout << std::setw(30) << std::left << #x ": " << x << std::endl # define DBG_PRINT(x) std::cout << x << std::endl #else @@ -74,7 +74,7 @@ namespace crypto const size_t mn = m * n; CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(N <= N_max, 3); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(mn < mn_max, 4); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(mn <= mn_max, 4); scalar_mat_t a_mat(mn); // m x n matrix a_mat.zero(); @@ -124,7 +124,7 @@ namespace crypto for(size_t k = 0; k < m_bound; ++k) { scalar_t old = coeffs[k * N + i]; - coeffs[k * N + i] *= a_mat(j, l_digits[j]); + coeffs[k * N + i] *= a_mat(j, i_j); coeffs[k * N + i] += carry; carry = old; } @@ -135,7 +135,7 @@ namespace crypto else { for(size_t k = 0; k < m_bound; ++k) - coeffs[k * N + i] *= a_mat(j, l_digits[j]); + coeffs[k * N + i] *= a_mat(j, i_j); } } } @@ -183,7 +183,8 @@ namespace crypto hash_helper_t::hs_t hsc(1 + ring_size + 2 + m); hsc.add_hash(context_hash); - hsc.add_points_array(ring); + for(auto& ring_el : ring) + hsc.add_point(c_scalar_1div8 * ring_el); hsc.add_pub_key(result.A); hsc.add_pub_key(result.B); hsc.add_pub_keys_array(result.Pk); @@ -287,10 +288,13 @@ namespace crypto for(size_t i = 0; i < N; ++i) { p_vec[i] = c_scalar_1; + size_t i_tmp = i; for(size_t j = 0; j < m; ++j) { - const scalar_t& f_ji = (i == 0) ? f0[j] : sig.f[j * (n - 1) + i - 1]; - p_vec[i] *= f_ji; + size_t i_j = i_tmp % n; // j-th digit of i + i_tmp /= n; + const scalar_t& f_jij = (i_j == 0) ? f0[j] : sig.f[j * (n - 1) + i_j - 1]; + p_vec[i] *= f_jij; } } diff --git a/tests/functional_tests/crypto_tests_one_out_of_many_proofs.h b/tests/functional_tests/crypto_tests_one_out_of_many_proofs.h index 077a22fb..308088ba 100644 --- a/tests/functional_tests/crypto_tests_one_out_of_many_proofs.h +++ b/tests/functional_tests/crypto_tests_one_out_of_many_proofs.h @@ -66,13 +66,69 @@ struct BGE_proff_check_t -TEST(BGE_proof, basics) +TEST(BGE_proof, positive) { BGE_proff_check_t cc; - cc.prepare_random_data(1); - ASSERT_TRUE(cc.generate()); - ASSERT_TRUE(cc.verify()); - + + for(size_t N = 1; N <= 256; ++N) + { + cc.prepare_random_data(N); + ASSERT_TRUE(cc.generate()); + std::cout << "N = " << N << ", size = " << (cc.sig.Pk.size() + cc.sig.f.size() + 4) * 32 << " bytes" << ENDL; + ASSERT_TRUE(cc.verify()); + } + + return true; +} + +bool invalidate_BGE_proof(size_t index, BGE_proof& s) +{ + static point_t te{}; + static bool te_init = te.from_string(canonical_torsion_elements[0].string); + if (!te_init) + throw std::runtime_error("te_init"); + + switch(index) + { + case 0: s.A = (point_t(s.A) + te).to_public_key(); return true; + case 1: s.B = (point_t(s.B) + te).to_public_key(); return true; + case 2: s.Pk[0] = (point_t(s.Pk[0]) + te).to_public_key(); return true; + case 3: s.Pk.back() = (point_t(s.Pk.back()) + te).to_public_key(); return true; + case 4: s.f[0] = 0; return true; + case 5: s.f[0] = c_scalar_256m1; return true; + case 6: s.f.back() = 0; return true; + case 7: s.f.back() = c_scalar_256m1; return true; + case 8: s.y = 0; return true; + case 9: s.y = c_scalar_256m1; return true; + case 10: s.z = 0; return true; + case 11: s.z = c_scalar_256m1; return true; + default: + return false; + } +} + +TEST(BGE_proof, negative) +{ + BGE_proff_check_t cc; + + for(size_t N = 1; N <= 13; ++N) + { + cc.prepare_random_data(13); + ASSERT_TRUE(cc.generate()); + BGE_proff_check_t cc_good = cc; + ASSERT_TRUE(cc_good.verify()); + + for(size_t i = 0; true; ++i) + { + cc = cc_good; + if (!invalidate_BGE_proof(i, cc.sig)) + { + ASSERT_TRUE(i != 0); + break; + } + ASSERT_FALSE(cc.verify()); + } + } return true; }