Pairing works now! Yay!!!

This commit is contained in:
vub 2016-12-24 20:01:01 -05:00
parent 4b3e13de37
commit 78f3c227fe
4 changed files with 66 additions and 12 deletions

View File

@ -2,15 +2,23 @@ from bn128_field_elements import field_modulus, FQ, FQ2, FQ12
curve_order = 21888242871839275222246405745257275088548364400416034343698204186575808495617
# Curve order should be prime
assert pow(2, curve_order, curve_order) == 2
# Curve order should be a factor of field_modulus**12 - 1
assert (field_modulus ** 12 - 1) % curve_order == 0
# Curve is y**2 = x**3 + 3
b = FQ(3)
b2 = FQ2([3, 0])
b12 = FQ12([3] + [0] * 11) / FQ12([0] * 6 + [1] + [0] * 5)
# Twisted curve over FQ**2
b2 = FQ2([3, 0]) / FQ2([0, 1])
# Extension curve over FQ**12; same b value as over FQ
b12 = FQ12([3] + [0] * 11)
# Generator for curve over FQ
G1 = (FQ(1), FQ(2))
# Second element corresponds to modsqrt(67) * i in our quadratic field representation
G2 = (FQ2([4, 0]), FQ2([16893045765507297706785249332518927989146279141265438554111591828131739815230L, 16469166999615883226695964867118064280147127342783597836693979910667010785192]))
# Generator for twisted curve over FQ2
G2 = (FQ2([16260673061341949275257563295988632869519996389676903622179081103440260644990L, 11559732032986387107991004021392285783925812861821192530917403151452391805634L]),
FQ2([15530828784031078730107954109694902500959150953518636601196686752670329677317L, 4082367875863433681332203403145435568316851327593401208105741076214120093531L]))
# Check that a point is on the curve defined by y**2 == x**3 + b
def is_on_curve(pt, b):
@ -68,18 +76,27 @@ assert multiply(G1, curve_order) is None
assert add(add(double(G2), G2), G2) == double(double(G2))
assert double(G2) != G2
assert add(multiply(G2, 9), multiply(G2, 5)) == add(multiply(G2, 12), multiply(G2, 2))
assert multiply(G2, curve_order) is None
assert multiply(G2, 2 * field_modulus - curve_order) is not None
assert is_on_curve(multiply(G2, 9), b2)
# "Twist" a point in E(FQ2) into a point in E(FQ12)
w = FQ12([0, 1] + [0] * 10)
# Convert P => -P
def neg(pt):
if pt is None:
return None
x, y = pt
return (x, -y)
def twist(pt):
if pt is None:
return None
x, y = pt
nx = FQ12([x.coeffs[0]] + [0] * 5 + [x.coeffs[1]] + [0] * 5)
ny = FQ12([y.coeffs[0]] + [0] * 5 + [y.coeffs[1]] + [0] * 5)
return (nx / w **2, ny / w**3)
return (nx * w **2, ny * w**3)
# Check that the twist creates a point that is on the curve
assert is_on_curve(twist(G2), b12)
@ -90,3 +107,5 @@ G12 = twist(G2)
assert add(add(double(G12), G12), G12) == double(double(G12))
assert double(G12) != G12
assert add(multiply(G12, 9), multiply(G12, 5)) == add(multiply(G12, 12), multiply(G12, 2))
assert is_on_curve(multiply(G12, 9), b12)
assert multiply(G12, curve_order) is None

View File

@ -7,9 +7,9 @@ field_modulus = 2188824287183927522224640574525727508869631115729782366268903789
assert pow(2, field_modulus, field_modulus) == 2
# The modulus of the polynomial in this representation of FQ2
FQ2_modulus_coeffs = [82, 18] # Implied + [1]
FQ2_modulus_coeffs = [82, -18] # Implied + [1]
# And in FQ12
FQ12_modulus_coeffs = [82, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0] # Implied + [1]
FQ12_modulus_coeffs = [82, 0, 0, 0, 0, 0, -18, 0, 0, 0, 0, 0] # Implied + [1]
# Extended euclidean algorithm to find modular inverses for
# integers
@ -237,6 +237,15 @@ assert one / f + x / f == (one + x) / f
assert one * f + x * f == (one + x) * f
assert x ** (field_modulus ** 2 - 1) == one
# The quadratic extension field
class FQcomplex(FQP):
def __init__(self, coeffs):
self.coeffs = [FQ(c) for c in coeffs]
self.modulus_coeffs = [1, 0]
self.degree = 2
self.__class__.degree = 2
# The 12th-degree extension field
class FQ12(FQP):
def __init__(self, coeffs):

View File

@ -1,7 +1,7 @@
# NOT YET FINISHED! Pairing code has bugs in it, is NOT bilinear!
from bn128_curve import double, add, multiply, is_on_curve, twist, b, b2, b12, curve_order, G1, G2
from bn128_field_elements import field_modulus, FQ, FQ2, FQ12
from bn128_curve import double, add, multiply, is_on_curve, neg, twist, b, b2, b12, curve_order, G1, G2, G12
from bn128_field_elements import field_modulus, FQ, FQ2, FQ12, FQcomplex
ate_loop_count = 29793968203157093288
log_ate_loop_count = 63
@ -15,10 +15,10 @@ def linefunc(P1, P2, T):
xt, yt = T
if x1 != x2:
m = (y2 - y1) / (x2 - x1)
return (yt - y1) - m * (xt - x1)
return m * (xt - x1) - (yt - y1)
elif y1 == y2:
m = 3 * x1**2 / (2 * y1)
return (yt - y1) - m * (xt - x1)
return m * (xt - x1) - (yt - y1)
else:
return xt - x1
@ -57,7 +57,9 @@ def miller_loop(Q, P):
R = add(R, Q)
assert R == multiply(Q, ate_loop_count)
Q1 = (Q[0] ** field_modulus, Q[1] ** field_modulus)
assert is_on_curve(Q1, b12)
nQ2 = (Q[0] ** (field_modulus ** 2), -Q[1] ** (field_modulus ** 2))
assert is_on_curve(nQ2, b12)
f = f * linefunc(R, Q1, P)
R = add(R, Q1)
f = f * linefunc(R, nQ2, P)

View File

@ -0,0 +1,24 @@
from bn128_pairing import pairing, neg, G2, G1, multiply, FQ12, curve_order
p1 = pairing(G2, G1)
pn1 = pairing(G2, neg(G1))
assert p1 * pn1 == FQ12.one()
print 'Pairing check against negative in G1 passed'
np1 = pairing(neg(G2), G1)
assert p1 * np1 == FQ12.one()
assert pn1 == np1
print 'Pairing check against negative in G2 passed'
assert p1 ** curve_order == FQ12.one()
print 'Pairing output has correct order'
p2 = pairing(G2, multiply(G1, 2))
assert p1 * p1 == p2
print 'Pairing bilinearity in G1 passed'
assert p1 != p2 and p1 != np1 and p2 != np1
print 'Pairing is non-degenerate'
po2 = pairing(multiply(G2, 2), G1)
assert p1 * p1 == po2
print 'Pairing bilinearity in G2 passed'
p3 = pairing(multiply(G2, 27), multiply(G1, 37))
po3 = pairing(G2, multiply(G1, 999))
assert p3 == po3
print 'Composite check passed'