forked from lthn/blockchain
crypto::generic_schnorr_sig + test
This commit is contained in:
parent
5127c77ebf
commit
dd1631461d
2 changed files with 139 additions and 3 deletions
|
|
@ -64,21 +64,107 @@ namespace crypto
|
|||
scalar_t y1;
|
||||
};
|
||||
|
||||
enum generator_tag { generator_tag_void = 0, generator_tag_G = 1, generator_tag_H = 2, generator_tag_H2 = 3, generator_tag_X = 4, generator_tag_U = 5 };
|
||||
enum generator_tag { gt_void = 0, gt_G = 1, gt_H = 2, gt_H2 = 3, gt_X = 4, gt_U = 5 };
|
||||
|
||||
template<generator_tag gen0 = generator_tag_H, generator_tag gen1 = generator_tag_G>
|
||||
template<generator_tag gen0 = gt_H, generator_tag gen1 = gt_G>
|
||||
bool generate_linear_composition_proof(const hash& m, const public_key& A, const scalar_t& secret_a, const scalar_t& secret_b, linear_composition_proof& result, uint8_t* p_err = nullptr)
|
||||
{
|
||||
// consider embedding generators' tags into random entropy to distinguish proofs made with different generators during verification
|
||||
return false;
|
||||
}
|
||||
|
||||
template<generator_tag gen0 = generator_tag_H, generator_tag gen1 = generator_tag_G>
|
||||
template<generator_tag gen0 = gt_H, generator_tag gen1 = gt_G>
|
||||
bool verify_linear_composition_proof(const hash& m, const public_key& A, const linear_composition_proof& sig, uint8_t* p_err = nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
struct generic_schnorr_sig
|
||||
{
|
||||
scalar_t c;
|
||||
scalar_t y;
|
||||
};
|
||||
|
||||
template<generator_tag gen>
|
||||
inline bool generate_schnorr_sig(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result);
|
||||
|
||||
template<>
|
||||
inline bool generate_schnorr_sig<gt_G>(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (A != secret_a * c_point_G)
|
||||
return false;
|
||||
#endif
|
||||
scalar_t r = scalar_t::random();
|
||||
point_t R = r * c_point_G;
|
||||
hash_helper_t::hs_t hsc(3);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_point(A);
|
||||
hsc.add_point(R);
|
||||
result.c = hsc.calc_hash();
|
||||
result.y.assign_mulsub(result.c, secret_a, r); // y = r - c * secret_a
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool generate_schnorr_sig<gt_X>(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (A != secret_a * c_point_X)
|
||||
return false;
|
||||
#endif
|
||||
scalar_t r = scalar_t::random();
|
||||
point_t R = r * c_point_X;
|
||||
hash_helper_t::hs_t hsc(3);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_point(A);
|
||||
hsc.add_point(R);
|
||||
result.c = hsc.calc_hash();
|
||||
result.y.assign_mulsub(result.c, secret_a, r); // y = r - c * secret_a
|
||||
return true;
|
||||
}
|
||||
|
||||
template<generator_tag gen>
|
||||
inline bool verify_schnorr_sig(const hash& m, const public_key& A, const generic_schnorr_sig& sig) noexcept;
|
||||
|
||||
template<>
|
||||
inline bool verify_schnorr_sig<gt_G>(const hash& m, const public_key& A, const generic_schnorr_sig& sig) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!sig.c.is_reduced() || !sig.y.is_reduced())
|
||||
return false;
|
||||
hash_helper_t::hs_t hsc(3);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_pub_key(A);
|
||||
hsc.add_point(point_t(A).mul_plus_G(sig.c, sig.y)); // sig.y * G + sig.c * A
|
||||
return sig.c == hsc.calc_hash();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool verify_schnorr_sig<gt_X>(const hash& m, const public_key& A, const generic_schnorr_sig& sig) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!sig.c.is_reduced() || !sig.y.is_reduced())
|
||||
return false;
|
||||
hash_helper_t::hs_t hsc(3);
|
||||
hsc.add_hash(m);
|
||||
hsc.add_pub_key(A);
|
||||
hsc.add_point(sig.y * c_point_X + sig.c * point_t(A));
|
||||
return sig.c == hsc.calc_hash();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: improve this proof using random weightning factor
|
||||
|
|
|
|||
|
|
@ -1460,6 +1460,56 @@ TEST(crypto, sc_set_bit_clear_bit)
|
|||
}
|
||||
|
||||
|
||||
TEST(crypto, schnorr_sig)
|
||||
{
|
||||
public_key invalid_pk = parse_tpod_from_hex_string<public_key>("0000000000000000000000000000000000000000000000000000000000000001");
|
||||
ASSERT_FALSE(check_key(invalid_pk));
|
||||
|
||||
hash m = *(crypto::hash*)(&scalar_t::random());
|
||||
for(size_t i = 0; i < 1000; ++i)
|
||||
{
|
||||
generic_schnorr_sig ss{};
|
||||
scalar_t a = scalar_t::random();
|
||||
point_t A_pt = a * c_point_G;
|
||||
public_key A = A_pt.to_public_key();
|
||||
ASSERT_FALSE(generate_schnorr_sig<gt_X>(m, A_pt, a, ss));
|
||||
ASSERT_TRUE(generate_schnorr_sig<gt_G>(m, A_pt, a, ss));
|
||||
ASSERT_FALSE(verify_schnorr_sig<gt_X>(m, A, ss));
|
||||
ASSERT_TRUE(verify_schnorr_sig<gt_G>(m, A, ss));
|
||||
|
||||
A_pt = a * c_point_X;
|
||||
A = A_pt.to_public_key();
|
||||
ASSERT_FALSE(generate_schnorr_sig<gt_G>(m, A_pt, a, ss));
|
||||
ASSERT_TRUE(generate_schnorr_sig<gt_X>(m, A_pt, a, ss));
|
||||
ASSERT_FALSE(verify_schnorr_sig<gt_G>(m, A, ss));
|
||||
ASSERT_TRUE(verify_schnorr_sig<gt_X>(m, A, ss));
|
||||
|
||||
ASSERT_FALSE(verify_schnorr_sig<gt_X>(currency::null_hash, A, ss));
|
||||
ASSERT_FALSE(verify_schnorr_sig<gt_X>(m, invalid_pk, ss));
|
||||
|
||||
generic_schnorr_sig bad_ss = ss;
|
||||
bad_ss.c = c_scalar_Pm1;
|
||||
ASSERT_FALSE(bad_ss.c.is_reduced());
|
||||
ASSERT_FALSE(verify_schnorr_sig<gt_X>(m, A, bad_ss));
|
||||
bad_ss = ss;
|
||||
bad_ss.y = c_scalar_Pm1;
|
||||
ASSERT_FALSE(bad_ss.y.is_reduced());
|
||||
ASSERT_FALSE(verify_schnorr_sig<gt_X>(m, A, bad_ss));
|
||||
|
||||
bad_ss = ss;
|
||||
|
||||
mp::uint256_t c_mp = bad_ss.c.as_boost_mp_type<mp::uint256_t>();
|
||||
c_mp += c_scalar_L.as_boost_mp_type<mp::uint256_t>();
|
||||
memcpy(bad_ss.c.data(), c_mp.backend().limbs(), sizeof(scalar_t));
|
||||
ASSERT_FALSE(bad_ss.c.is_reduced());
|
||||
scalar_t tmp(bad_ss.c);
|
||||
tmp.reduce();
|
||||
ASSERT_EQ(tmp, ss.c);
|
||||
ASSERT_FALSE(verify_schnorr_sig<gt_X>(m, A, bad_ss));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// test's runner
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue