Check that E' points are actually in G2 by ensuring they are of order r.
This commit is contained in:
parent
9f7bc6cba5
commit
c4fce3fc81
|
@ -22,6 +22,67 @@ typedef libsnark::default_r1cs_ppzksnark_pp::Fqe_type curve_Fq2;
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "utilstrencodings.h"
|
#include "utilstrencodings.h"
|
||||||
|
|
||||||
|
TEST(proofs, g2_subgroup_check)
|
||||||
|
{
|
||||||
|
// all G2 elements are order r
|
||||||
|
ASSERT_TRUE(libsnark::alt_bn128_modulus_r * curve_G2::random_element() == curve_G2::zero());
|
||||||
|
|
||||||
|
// but that doesn't mean all elements that satisfy the curve equation are in G2...
|
||||||
|
curve_G2 p = curve_G2::one();
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// This will construct an order r(2q-r) point with high probability
|
||||||
|
p.X = curve_Fq2::random_element();
|
||||||
|
try {
|
||||||
|
p.Y = ((p.X.squared() * p.X) + libsnark::alt_bn128_twist_coeff_b).sqrt();
|
||||||
|
break;
|
||||||
|
} catch(...) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_TRUE(p.is_well_formed()); // it's on the curve
|
||||||
|
ASSERT_TRUE(libsnark::alt_bn128_modulus_r * p != curve_G2::zero()); // but not the order r subgroup..
|
||||||
|
|
||||||
|
{
|
||||||
|
// libsnark unfortunately doesn't check, and the pairing will complete
|
||||||
|
auto e = curve_Fr("149");
|
||||||
|
auto a = curve_pp::reduced_pairing(curve_G1::one(), p);
|
||||||
|
auto b = curve_pp::reduced_pairing(e * curve_G1::one(), p);
|
||||||
|
|
||||||
|
// though it will not preserve bilinearity
|
||||||
|
ASSERT_TRUE((a^e) != b);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// so, our decompression API should not allow you to decompress G2 elements of that form!
|
||||||
|
CompressedG2 badp(p);
|
||||||
|
try {
|
||||||
|
auto newp = badp.to_libsnark_g2<curve_G2>();
|
||||||
|
FAIL() << "Expected std::runtime_error";
|
||||||
|
} catch (std::runtime_error const & err) {
|
||||||
|
EXPECT_EQ(err.what(), std::string("point is not in G2"));
|
||||||
|
} catch(...) {
|
||||||
|
FAIL() << "Expected std::runtime_error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// educational purposes: showing that E'(Fp2) is of order r(2q-r),
|
||||||
|
// by multiplying our random point in E' by (2q-r) = (q + q - r) to
|
||||||
|
// get an element in G2
|
||||||
|
{
|
||||||
|
auto p1 = libsnark::alt_bn128_modulus_q * p;
|
||||||
|
p1 = p1 + p1;
|
||||||
|
p1 = p1 - (libsnark::alt_bn128_modulus_r * p);
|
||||||
|
|
||||||
|
ASSERT_TRUE(p1.is_well_formed());
|
||||||
|
ASSERT_TRUE(libsnark::alt_bn128_modulus_r * p1 == curve_G2::zero());
|
||||||
|
|
||||||
|
CompressedG2 goodp(p1);
|
||||||
|
auto newp = goodp.to_libsnark_g2<curve_G2>();
|
||||||
|
|
||||||
|
ASSERT_TRUE(newp == p1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST(proofs, sqrt_zero)
|
TEST(proofs, sqrt_zero)
|
||||||
{
|
{
|
||||||
ASSERT_TRUE(curve_Fq::zero() == curve_Fq::zero().sqrt());
|
ASSERT_TRUE(curve_Fq::zero() == curve_Fq::zero().sqrt());
|
||||||
|
|
|
@ -163,6 +163,10 @@ curve_G2 CompressedG2::to_libsnark_g2() const
|
||||||
|
|
||||||
assert(r.is_well_formed());
|
assert(r.is_well_formed());
|
||||||
|
|
||||||
|
if (alt_bn128_modulus_r * r != curve_G2::zero()) {
|
||||||
|
throw std::runtime_error("point is not in G2");
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue