mirror of
https://github.com/arnaucube/math.git
synced 2026-01-11 16:31:32 +01:00
Sage impls single-files code&tests
This commit is contained in:
81
fft.sage
81
fft.sage
@@ -60,3 +60,84 @@ def poly_mul(fa, fb, F, n):
|
|||||||
fc_coef = c_evals*ft_inv
|
fc_coef = c_evals*ft_inv
|
||||||
fc2=P(fc_coef.list())
|
fc2=P(fc_coef.list())
|
||||||
return fc2, c_evals
|
return fc2, c_evals
|
||||||
|
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
|
||||||
|
#####
|
||||||
|
# Roots of Unity test:
|
||||||
|
q = 17
|
||||||
|
F = GF(q)
|
||||||
|
n = 4
|
||||||
|
g, primitive_w = get_primitive_root_of_unity(F, n)
|
||||||
|
print("generator:", g)
|
||||||
|
print("primitive_w:", primitive_w)
|
||||||
|
|
||||||
|
w = get_nth_roots_of_unity(n, primitive_w)
|
||||||
|
print(f"{n}th roots of unity: {w}")
|
||||||
|
assert w == [1, 13, 16, 4]
|
||||||
|
|
||||||
|
|
||||||
|
#####
|
||||||
|
# FFT test:
|
||||||
|
|
||||||
|
def isprime(num):
|
||||||
|
for n in range(2,int(num^1/2)+1):
|
||||||
|
if num%n==0:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
# list valid values for q
|
||||||
|
for i in range(20):
|
||||||
|
if isprime(8*i+1):
|
||||||
|
print("q =", 8*i+1)
|
||||||
|
|
||||||
|
q = 41
|
||||||
|
F = GF(q)
|
||||||
|
n = 4
|
||||||
|
# q needs to be a prime, s.t. q-1 is divisible by n
|
||||||
|
assert (q-1)%n==0
|
||||||
|
print("q =", q, "n = ", n)
|
||||||
|
|
||||||
|
# ft: Vandermonde matrix for the nth roots of unity
|
||||||
|
w, ft, ft_inv = fft(F, n)
|
||||||
|
print("nth roots of unity:", w)
|
||||||
|
print("Vandermonde matrix:")
|
||||||
|
print(ft)
|
||||||
|
|
||||||
|
a = vector([3,4,5,9])
|
||||||
|
print("a:", a)
|
||||||
|
|
||||||
|
# interpolate f_a(x)
|
||||||
|
fa_coef = ft_inv * a
|
||||||
|
print("fa_coef:", fa_coef)
|
||||||
|
|
||||||
|
P.<x> = PolynomialRing(F)
|
||||||
|
fa = P(list(fa_coef))
|
||||||
|
print("f_a(x):", fa)
|
||||||
|
|
||||||
|
# check that evaluating fa(x) at the roots of unity returns the expected values of a
|
||||||
|
for i in range(len(a)):
|
||||||
|
assert fa(w[i]) == a[i]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Fast polynomial multiplicaton using FFT
|
||||||
|
print("\n---------")
|
||||||
|
print("---Fast polynomial multiplication using FFT")
|
||||||
|
|
||||||
|
n = 8
|
||||||
|
# q needs to be a prime, s.t. q-1 is divisible by n
|
||||||
|
assert (q-1)%n==0
|
||||||
|
print("q =", q, "n = ", n)
|
||||||
|
|
||||||
|
fa=P([1,2,3,4])
|
||||||
|
fb=P([1,2,3,4])
|
||||||
|
fc_expected = fa*fb
|
||||||
|
print("fc expected result:", fc_expected) # expected result
|
||||||
|
print("fc expected coef", fc_expected.coefficients())
|
||||||
|
|
||||||
|
fc, c_evals = poly_mul(fa, fb, F, n)
|
||||||
|
print("c_evals=(a_evals*b_evals)=", c_evals)
|
||||||
|
print("fc:", fc)
|
||||||
|
assert fc_expected == fc
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
load("fft.sage")
|
|
||||||
|
|
||||||
#####
|
|
||||||
# Roots of Unity test:
|
|
||||||
q = 17
|
|
||||||
F = GF(q)
|
|
||||||
n = 4
|
|
||||||
g, primitive_w = get_primitive_root_of_unity(F, n)
|
|
||||||
print("generator:", g)
|
|
||||||
print("primitive_w:", primitive_w)
|
|
||||||
|
|
||||||
w = get_nth_roots_of_unity(n, primitive_w)
|
|
||||||
print(f"{n}th roots of unity: {w}")
|
|
||||||
assert w == [1, 13, 16, 4]
|
|
||||||
|
|
||||||
|
|
||||||
#####
|
|
||||||
# FFT test:
|
|
||||||
|
|
||||||
def isprime(num):
|
|
||||||
for n in range(2,int(num^1/2)+1):
|
|
||||||
if num%n==0:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
# list valid values for q
|
|
||||||
for i in range(20):
|
|
||||||
if isprime(8*i+1):
|
|
||||||
print("q =", 8*i+1)
|
|
||||||
|
|
||||||
q = 41
|
|
||||||
F = GF(q)
|
|
||||||
n = 4
|
|
||||||
# q needs to be a prime, s.t. q-1 is divisible by n
|
|
||||||
assert (q-1)%n==0
|
|
||||||
print("q =", q, "n = ", n)
|
|
||||||
|
|
||||||
# ft: Vandermonde matrix for the nth roots of unity
|
|
||||||
w, ft, ft_inv = fft(F, n)
|
|
||||||
print("nth roots of unity:", w)
|
|
||||||
print("Vandermonde matrix:")
|
|
||||||
print(ft)
|
|
||||||
|
|
||||||
a = vector([3,4,5,9])
|
|
||||||
print("a:", a)
|
|
||||||
|
|
||||||
# interpolate f_a(x)
|
|
||||||
fa_coef = ft_inv * a
|
|
||||||
print("fa_coef:", fa_coef)
|
|
||||||
|
|
||||||
P.<x> = PolynomialRing(F)
|
|
||||||
fa = P(list(fa_coef))
|
|
||||||
print("f_a(x):", fa)
|
|
||||||
|
|
||||||
# check that evaluating fa(x) at the roots of unity returns the expected values of a
|
|
||||||
for i in range(len(a)):
|
|
||||||
assert fa(w[i]) == a[i]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Fast polynomial multiplicaton using FFT
|
|
||||||
print("\n---------")
|
|
||||||
print("---Fast polynomial multiplication using FFT")
|
|
||||||
|
|
||||||
n = 8
|
|
||||||
# q needs to be a prime, s.t. q-1 is divisible by n
|
|
||||||
assert (q-1)%n==0
|
|
||||||
print("q =", q, "n = ", n)
|
|
||||||
|
|
||||||
fa=P([1,2,3,4])
|
|
||||||
fb=P([1,2,3,4])
|
|
||||||
fc_expected = fa*fb
|
|
||||||
print("fc expected result:", fc_expected) # expected result
|
|
||||||
print("fc expected coef", fc_expected.coefficients())
|
|
||||||
|
|
||||||
fc, c_evals = poly_mul(fa, fb, F, n)
|
|
||||||
print("c_evals=(a_evals*b_evals)=", c_evals)
|
|
||||||
print("fc:", fc)
|
|
||||||
assert fc_expected == fc
|
|
||||||
158
ipa.sage
158
ipa.sage
@@ -303,3 +303,161 @@ def vec_scalar_mul_point(a, n):
|
|||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
import unittest, operator
|
||||||
|
|
||||||
|
# Ethereum elliptic curve
|
||||||
|
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
|
||||||
|
a = 0
|
||||||
|
b = 7
|
||||||
|
Fp = GF(p)
|
||||||
|
E = EllipticCurve(Fp, [a,b])
|
||||||
|
GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
|
||||||
|
GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
|
||||||
|
g = E(GX,GY)
|
||||||
|
n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
|
||||||
|
h = 1
|
||||||
|
q = g.order()
|
||||||
|
Fq = GF(q)
|
||||||
|
|
||||||
|
# simplier curve values
|
||||||
|
# p = 19
|
||||||
|
# Fp = GF(p)
|
||||||
|
# E = EllipticCurve(Fp,[0,3])
|
||||||
|
# g = E(1, 2)
|
||||||
|
# q = g.order()
|
||||||
|
# Fq = GF(q)
|
||||||
|
|
||||||
|
print(E)
|
||||||
|
print(Fq)
|
||||||
|
assert is_prime(p)
|
||||||
|
assert is_prime(q)
|
||||||
|
assert g * q == 0
|
||||||
|
|
||||||
|
class TestUtils(unittest.TestCase):
|
||||||
|
def test_vecs(self):
|
||||||
|
a = [1, 2, 3, 4, 5]
|
||||||
|
b = [1, 2, 3, 4, 5]
|
||||||
|
|
||||||
|
c = vec_scalar_mul_field(a, 10)
|
||||||
|
assert c == [10, 20, 30, 40, 50]
|
||||||
|
|
||||||
|
c = inner_product_field(a, b)
|
||||||
|
assert c == 55
|
||||||
|
|
||||||
|
# check that <a, b> with b = (1, x, x^2, ..., x^{d-1}) is the same
|
||||||
|
# than evaluating p(x) with coefficients a_i, at x
|
||||||
|
a = [Fq(1), Fq(2), Fq(3), Fq(4), Fq(5), Fq(6), Fq(7), Fq(8)]
|
||||||
|
z = Fq(3)
|
||||||
|
b = powers_of(z, 8)
|
||||||
|
c = inner_product_field(a, b)
|
||||||
|
|
||||||
|
x = PolynomialRing(Fq, 'x').gen()
|
||||||
|
px = 1 + 2*x + 3*x^2 + 4*x^3 + 5*x^4 + 6*x^5 + 7*x^6 + 8*x^7
|
||||||
|
assert c == px(x=z)
|
||||||
|
|
||||||
|
|
||||||
|
class TestIPA_bulletproofs(unittest.TestCase):
|
||||||
|
def test_inner_product(self):
|
||||||
|
d = 8
|
||||||
|
ipa = IPA_bulletproofs(Fq, E, g, d)
|
||||||
|
|
||||||
|
# prover
|
||||||
|
# p(x) = 1 + 2x + 3x² + 4x³ + 5x⁴ + 6x⁵ + 7x⁶ + 8x⁷
|
||||||
|
a = [ipa.F(1), ipa.F(2), ipa.F(3), ipa.F(4), ipa.F(5), ipa.F(6), ipa.F(7), ipa.F(8)]
|
||||||
|
x = ipa.F(3)
|
||||||
|
b = powers_of(x, ipa.d) # = b
|
||||||
|
|
||||||
|
# prover
|
||||||
|
P = ipa.commit(a, b)
|
||||||
|
print("commit", P)
|
||||||
|
v = ipa.evaluate(a, b)
|
||||||
|
print("v", v)
|
||||||
|
|
||||||
|
# verifier
|
||||||
|
# r = int(ipa.F.random_element())
|
||||||
|
|
||||||
|
# verifier generate random challenges {uᵢ} ∈ 𝕀 and U ∈ 𝔾
|
||||||
|
U = ipa.E.random_element()
|
||||||
|
k = int(math.log(d, 2))
|
||||||
|
u = [None] * k
|
||||||
|
for j in reversed(range(0, k)):
|
||||||
|
u[j] = ipa.F.random_element()
|
||||||
|
while (u[j] == 0): # prevent u[j] from being 0
|
||||||
|
u[j] = ipa.F.random_element()
|
||||||
|
|
||||||
|
P = P + int(inner_product_field(a, b)) * U
|
||||||
|
|
||||||
|
# prover
|
||||||
|
a_ipa, b_ipa, G_ipa, H_ipa, L, R = ipa.ipa(a, b, u, U)
|
||||||
|
|
||||||
|
# verifier
|
||||||
|
print("P", P)
|
||||||
|
print("a_ipa", a_ipa)
|
||||||
|
verif = ipa.verify(P, a_ipa, v, b, u, U, L, R, b_ipa, G_ipa, H_ipa)
|
||||||
|
print("Verification:", verif)
|
||||||
|
assert verif == True
|
||||||
|
|
||||||
|
|
||||||
|
class TestIPA_halo(unittest.TestCase):
|
||||||
|
def test_homomorphic_property(self):
|
||||||
|
ipa = IPA_halo(Fq, E, g, 5)
|
||||||
|
|
||||||
|
a = [1, 2, 3, 4, 5]
|
||||||
|
b = [1, 2, 3, 4, 5]
|
||||||
|
c = vec_add(a, b)
|
||||||
|
assert c == [2,4,6,8,10]
|
||||||
|
|
||||||
|
r = int(ipa.F.random_element())
|
||||||
|
s = int(ipa.F.random_element())
|
||||||
|
vc_a = ipa.commit(a, r)
|
||||||
|
vc_b = ipa.commit(b, s)
|
||||||
|
|
||||||
|
# com(a, r) + com(b, s) == com(a+b, r+s)
|
||||||
|
expected_vc_c = ipa.commit(vec_add(a, b), r+s)
|
||||||
|
vc_c = vc_a + vc_b
|
||||||
|
assert vc_c == expected_vc_c
|
||||||
|
|
||||||
|
def test_inner_product(self):
|
||||||
|
d = 8
|
||||||
|
ipa = IPA_halo(Fq, E, g, d)
|
||||||
|
|
||||||
|
# prover
|
||||||
|
# p(x) = 1 + 2x + 3x² + 4x³ + 5x⁴ + 6x⁵ + 7x⁶ + 8x⁷
|
||||||
|
a = [ipa.F(1), ipa.F(2), ipa.F(3), ipa.F(4), ipa.F(5), ipa.F(6), ipa.F(7), ipa.F(8)]
|
||||||
|
x = ipa.F(3)
|
||||||
|
x_powers = powers_of(x, ipa.d) # = b
|
||||||
|
|
||||||
|
# verifier
|
||||||
|
r = int(ipa.F.random_element())
|
||||||
|
|
||||||
|
# prover
|
||||||
|
P = ipa.commit(a, r)
|
||||||
|
print("commit", P)
|
||||||
|
v = ipa.evaluate(a, x_powers)
|
||||||
|
print("v", v)
|
||||||
|
|
||||||
|
# verifier generate random challenges {uᵢ} ∈ 𝕀 and U ∈ 𝔾
|
||||||
|
U = ipa.E.random_element()
|
||||||
|
k = int(math.log(ipa.d, 2))
|
||||||
|
u = [None] * k
|
||||||
|
for j in reversed(range(0, k)):
|
||||||
|
u[j] = ipa.F.random_element()
|
||||||
|
while (u[j] == 0): # prevent u[j] from being 0
|
||||||
|
u[j] = ipa.F.random_element()
|
||||||
|
|
||||||
|
P = P + int(v) * U
|
||||||
|
|
||||||
|
# prover
|
||||||
|
a_ipa, b_ipa, G_ipa, lj, rj, L, R = ipa.ipa(a, x_powers, u, U)
|
||||||
|
|
||||||
|
# verifier
|
||||||
|
print("P", P)
|
||||||
|
print("a_ipa", a_ipa)
|
||||||
|
print("\n Verify:")
|
||||||
|
verif = ipa.verify(P, a_ipa, v, x_powers, r, u, U, lj, rj, L, R)
|
||||||
|
assert verif == True
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|||||||
161
ipa_test.sage
161
ipa_test.sage
@@ -1,161 +0,0 @@
|
|||||||
import unittest, operator
|
|
||||||
load("ipa.sage")
|
|
||||||
|
|
||||||
# Halo paper: https://eprint.iacr.org/2019/1021.pdf
|
|
||||||
# Bulletproofs paper: https://eprint.iacr.org/2017/1066.pdf
|
|
||||||
|
|
||||||
# Ethereum elliptic curve
|
|
||||||
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
|
|
||||||
a = 0
|
|
||||||
b = 7
|
|
||||||
Fp = GF(p)
|
|
||||||
E = EllipticCurve(Fp, [a,b])
|
|
||||||
GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
|
|
||||||
GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
|
|
||||||
g = E(GX,GY)
|
|
||||||
n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
|
|
||||||
h = 1
|
|
||||||
q = g.order()
|
|
||||||
Fq = GF(q)
|
|
||||||
|
|
||||||
# simplier curve values
|
|
||||||
# p = 19
|
|
||||||
# Fp = GF(p)
|
|
||||||
# E = EllipticCurve(Fp,[0,3])
|
|
||||||
# g = E(1, 2)
|
|
||||||
# q = g.order()
|
|
||||||
# Fq = GF(q)
|
|
||||||
|
|
||||||
print(E)
|
|
||||||
print(Fq)
|
|
||||||
assert is_prime(p)
|
|
||||||
assert is_prime(q)
|
|
||||||
assert g * q == 0
|
|
||||||
|
|
||||||
class TestUtils(unittest.TestCase):
|
|
||||||
def test_vecs(self):
|
|
||||||
a = [1, 2, 3, 4, 5]
|
|
||||||
b = [1, 2, 3, 4, 5]
|
|
||||||
|
|
||||||
c = vec_scalar_mul_field(a, 10)
|
|
||||||
assert c == [10, 20, 30, 40, 50]
|
|
||||||
|
|
||||||
c = inner_product_field(a, b)
|
|
||||||
assert c == 55
|
|
||||||
|
|
||||||
# check that <a, b> with b = (1, x, x^2, ..., x^{d-1}) is the same
|
|
||||||
# than evaluating p(x) with coefficients a_i, at x
|
|
||||||
a = [Fq(1), Fq(2), Fq(3), Fq(4), Fq(5), Fq(6), Fq(7), Fq(8)]
|
|
||||||
z = Fq(3)
|
|
||||||
b = powers_of(z, 8)
|
|
||||||
c = inner_product_field(a, b)
|
|
||||||
|
|
||||||
x = PolynomialRing(Fq, 'x').gen()
|
|
||||||
px = 1 + 2*x + 3*x^2 + 4*x^3 + 5*x^4 + 6*x^5 + 7*x^6 + 8*x^7
|
|
||||||
assert c == px(x=z)
|
|
||||||
|
|
||||||
|
|
||||||
class TestIPA_bulletproofs(unittest.TestCase):
|
|
||||||
def test_inner_product(self):
|
|
||||||
d = 8
|
|
||||||
ipa = IPA_bulletproofs(Fq, E, g, d)
|
|
||||||
|
|
||||||
# prover
|
|
||||||
# p(x) = 1 + 2x + 3x² + 4x³ + 5x⁴ + 6x⁵ + 7x⁶ + 8x⁷
|
|
||||||
a = [ipa.F(1), ipa.F(2), ipa.F(3), ipa.F(4), ipa.F(5), ipa.F(6), ipa.F(7), ipa.F(8)]
|
|
||||||
x = ipa.F(3)
|
|
||||||
b = powers_of(x, ipa.d) # = b
|
|
||||||
|
|
||||||
# prover
|
|
||||||
P = ipa.commit(a, b)
|
|
||||||
print("commit", P)
|
|
||||||
v = ipa.evaluate(a, b)
|
|
||||||
print("v", v)
|
|
||||||
|
|
||||||
# verifier
|
|
||||||
# r = int(ipa.F.random_element())
|
|
||||||
|
|
||||||
# verifier generate random challenges {uᵢ} ∈ 𝕀 and U ∈ 𝔾
|
|
||||||
U = ipa.E.random_element()
|
|
||||||
k = int(math.log(d, 2))
|
|
||||||
u = [None] * k
|
|
||||||
for j in reversed(range(0, k)):
|
|
||||||
u[j] = ipa.F.random_element()
|
|
||||||
while (u[j] == 0): # prevent u[j] from being 0
|
|
||||||
u[j] = ipa.F.random_element()
|
|
||||||
|
|
||||||
P = P + int(inner_product_field(a, b)) * U
|
|
||||||
|
|
||||||
# prover
|
|
||||||
a_ipa, b_ipa, G_ipa, H_ipa, L, R = ipa.ipa(a, b, u, U)
|
|
||||||
|
|
||||||
# verifier
|
|
||||||
print("P", P)
|
|
||||||
print("a_ipa", a_ipa)
|
|
||||||
verif = ipa.verify(P, a_ipa, v, b, u, U, L, R, b_ipa, G_ipa, H_ipa)
|
|
||||||
print("Verification:", verif)
|
|
||||||
assert verif == True
|
|
||||||
|
|
||||||
|
|
||||||
class TestIPA_halo(unittest.TestCase):
|
|
||||||
def test_homomorphic_property(self):
|
|
||||||
ipa = IPA_halo(Fq, E, g, 5)
|
|
||||||
|
|
||||||
a = [1, 2, 3, 4, 5]
|
|
||||||
b = [1, 2, 3, 4, 5]
|
|
||||||
c = vec_add(a, b)
|
|
||||||
assert c == [2,4,6,8,10]
|
|
||||||
|
|
||||||
r = int(ipa.F.random_element())
|
|
||||||
s = int(ipa.F.random_element())
|
|
||||||
vc_a = ipa.commit(a, r)
|
|
||||||
vc_b = ipa.commit(b, s)
|
|
||||||
|
|
||||||
# com(a, r) + com(b, s) == com(a+b, r+s)
|
|
||||||
expected_vc_c = ipa.commit(vec_add(a, b), r+s)
|
|
||||||
vc_c = vc_a + vc_b
|
|
||||||
assert vc_c == expected_vc_c
|
|
||||||
|
|
||||||
def test_inner_product(self):
|
|
||||||
d = 8
|
|
||||||
ipa = IPA_halo(Fq, E, g, d)
|
|
||||||
|
|
||||||
# prover
|
|
||||||
# p(x) = 1 + 2x + 3x² + 4x³ + 5x⁴ + 6x⁵ + 7x⁶ + 8x⁷
|
|
||||||
a = [ipa.F(1), ipa.F(2), ipa.F(3), ipa.F(4), ipa.F(5), ipa.F(6), ipa.F(7), ipa.F(8)]
|
|
||||||
x = ipa.F(3)
|
|
||||||
x_powers = powers_of(x, ipa.d) # = b
|
|
||||||
|
|
||||||
# verifier
|
|
||||||
r = int(ipa.F.random_element())
|
|
||||||
|
|
||||||
# prover
|
|
||||||
P = ipa.commit(a, r)
|
|
||||||
print("commit", P)
|
|
||||||
v = ipa.evaluate(a, x_powers)
|
|
||||||
print("v", v)
|
|
||||||
|
|
||||||
# verifier generate random challenges {uᵢ} ∈ 𝕀 and U ∈ 𝔾
|
|
||||||
U = ipa.E.random_element()
|
|
||||||
k = int(math.log(ipa.d, 2))
|
|
||||||
u = [None] * k
|
|
||||||
for j in reversed(range(0, k)):
|
|
||||||
u[j] = ipa.F.random_element()
|
|
||||||
while (u[j] == 0): # prevent u[j] from being 0
|
|
||||||
u[j] = ipa.F.random_element()
|
|
||||||
|
|
||||||
P = P + int(v) * U
|
|
||||||
|
|
||||||
# prover
|
|
||||||
a_ipa, b_ipa, G_ipa, lj, rj, L, R = ipa.ipa(a, x_powers, u, U)
|
|
||||||
|
|
||||||
# verifier
|
|
||||||
print("P", P)
|
|
||||||
print("a_ipa", a_ipa)
|
|
||||||
print("\n Verify:")
|
|
||||||
verif = ipa.verify(P, a_ipa, v, x_powers, r, u, U, lj, rj, L, R)
|
|
||||||
assert verif == True
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
@@ -77,3 +77,32 @@ def inv_mod(a, N):
|
|||||||
if g != 1:
|
if g != 1:
|
||||||
raise Exception("inv_mod err, g!=1")
|
raise Exception("inv_mod err, g!=1")
|
||||||
return mod(x, N)
|
return mod(x, N)
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
|
||||||
|
#####
|
||||||
|
# Chinese Remainder Theorem tests
|
||||||
|
a_i = [5, 3, 10]
|
||||||
|
m_i = [7, 11, 13]
|
||||||
|
assert crt(a_i, m_i) == 894
|
||||||
|
|
||||||
|
a_i = [3, 8]
|
||||||
|
m_i = [13, 17]
|
||||||
|
assert crt(a_i, m_i) == 42
|
||||||
|
|
||||||
|
|
||||||
|
#####
|
||||||
|
# gcd, using Binary Euclidean algorithm tests
|
||||||
|
assert gcd(21, 12) == 3
|
||||||
|
assert gcd(1_426_668_559_730, 810_653_094_756) == 1_417_082
|
||||||
|
|
||||||
|
assert gcd_recursive(21, 12) == 3
|
||||||
|
|
||||||
|
#####
|
||||||
|
# Extended Euclidean algorithm tests
|
||||||
|
assert egcd(7, 19) == (1, -8, 3)
|
||||||
|
assert egcd_recursive(7, 19) == (1, -8, 3)
|
||||||
|
|
||||||
|
#####
|
||||||
|
# Inverse modulo N tests
|
||||||
|
assert inv_mod(7, 19) == 11
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
load("number-theory.sage")
|
|
||||||
|
|
||||||
#####
|
|
||||||
# Chinese Remainder Theorem tests
|
|
||||||
a_i = [5, 3, 10]
|
|
||||||
m_i = [7, 11, 13]
|
|
||||||
assert crt(a_i, m_i) == 894
|
|
||||||
|
|
||||||
a_i = [3, 8]
|
|
||||||
m_i = [13, 17]
|
|
||||||
assert crt(a_i, m_i) == 42
|
|
||||||
|
|
||||||
|
|
||||||
#####
|
|
||||||
# gcd, using Binary Euclidean algorithm tests
|
|
||||||
assert gcd(21, 12) == 3
|
|
||||||
assert gcd(1_426_668_559_730, 810_653_094_756) == 1_417_082
|
|
||||||
|
|
||||||
assert gcd_recursive(21, 12) == 3
|
|
||||||
|
|
||||||
#####
|
|
||||||
# Extended Euclidean algorithm tests
|
|
||||||
assert egcd(7, 19) == (1, -8, 3)
|
|
||||||
assert egcd_recursive(7, 19) == (1, -8, 3)
|
|
||||||
|
|
||||||
#####
|
|
||||||
# Inverse modulo N tests
|
|
||||||
assert inv_mod(7, 19) == 11
|
|
||||||
@@ -2,6 +2,7 @@ from hashlib import sha256
|
|||||||
|
|
||||||
# Ring Signatures
|
# Ring Signatures
|
||||||
# bLSAG: Back’s Linkable Spontaneous Anonymous Group signatures
|
# bLSAG: Back’s Linkable Spontaneous Anonymous Group signatures
|
||||||
|
#
|
||||||
# A Rust implementation of this scheme can be found at:
|
# A Rust implementation of this scheme can be found at:
|
||||||
# https://github.com/arnaucube/ring-signatures-rs
|
# https://github.com/arnaucube/ring-signatures-rs
|
||||||
|
|
||||||
@@ -93,3 +94,57 @@ def verify(g, R, m, key_image, sig):
|
|||||||
|
|
||||||
print_ring(c)
|
print_ring(c)
|
||||||
assert c1 == c[0]
|
assert c1 == c[0]
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
import unittest, operator
|
||||||
|
|
||||||
|
# ethereum elliptic curve
|
||||||
|
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
|
||||||
|
a = 0
|
||||||
|
b = 7
|
||||||
|
F = GF(p)
|
||||||
|
E = EllipticCurve(F, [a,b])
|
||||||
|
GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
|
||||||
|
GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
|
||||||
|
g = E(GX,GY)
|
||||||
|
n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
|
||||||
|
h = 1
|
||||||
|
q = g.order()
|
||||||
|
assert is_prime(p)
|
||||||
|
assert is_prime(q)
|
||||||
|
assert g * q == 0
|
||||||
|
|
||||||
|
|
||||||
|
class TestRingSignatures(unittest.TestCase):
|
||||||
|
def test_bLSAG_ring_of_5(self):
|
||||||
|
test_bLSAG(5, 3)
|
||||||
|
def test_bLSAG_ring_of_20(self):
|
||||||
|
test_bLSAG(20, 14)
|
||||||
|
|
||||||
|
def test_bLSAG(ring_size, pi):
|
||||||
|
print(f"[bLSAG] Testing with a ring of {ring_size} keys")
|
||||||
|
prover = Prover(F, g)
|
||||||
|
n = ring_size
|
||||||
|
R = [None] * n
|
||||||
|
|
||||||
|
# generate prover's key pair
|
||||||
|
K_pi = prover.new_key()
|
||||||
|
|
||||||
|
# generate other n public keys
|
||||||
|
for i in range(0, n):
|
||||||
|
R[i] = g * i
|
||||||
|
|
||||||
|
# set K_pi
|
||||||
|
R[pi] = K_pi
|
||||||
|
|
||||||
|
# sign m
|
||||||
|
m = 1234
|
||||||
|
print("sign")
|
||||||
|
sig = prover.sign(m, R)
|
||||||
|
|
||||||
|
print("verify")
|
||||||
|
key_image = prover.w * hashToPoint(prover.K)
|
||||||
|
verify(g, R, m, key_image, sig)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
import unittest, operator
|
|
||||||
load("ring-signatures.sage")
|
|
||||||
|
|
||||||
# A Rust implementation of this scheme can be found at:
|
|
||||||
# https://github.com/arnaucube/ring-signatures-rs
|
|
||||||
|
|
||||||
# ethereum elliptic curve
|
|
||||||
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
|
|
||||||
a = 0
|
|
||||||
b = 7
|
|
||||||
F = GF(p)
|
|
||||||
E = EllipticCurve(F, [a,b])
|
|
||||||
GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
|
|
||||||
GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
|
|
||||||
g = E(GX,GY)
|
|
||||||
n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
|
|
||||||
h = 1
|
|
||||||
q = g.order()
|
|
||||||
assert is_prime(p)
|
|
||||||
assert is_prime(q)
|
|
||||||
assert g * q == 0
|
|
||||||
|
|
||||||
|
|
||||||
class TestRingSignatures(unittest.TestCase):
|
|
||||||
def test_bLSAG_ring_of_5(self):
|
|
||||||
test_bLSAG(5, 3)
|
|
||||||
def test_bLSAG_ring_of_20(self):
|
|
||||||
test_bLSAG(20, 14)
|
|
||||||
|
|
||||||
def test_bLSAG(ring_size, pi):
|
|
||||||
print(f"[bLSAG] Testing with a ring of {ring_size} keys")
|
|
||||||
prover = Prover(F, g)
|
|
||||||
n = ring_size
|
|
||||||
R = [None] * n
|
|
||||||
|
|
||||||
# generate prover's key pair
|
|
||||||
K_pi = prover.new_key()
|
|
||||||
|
|
||||||
# generate other n public keys
|
|
||||||
for i in range(0, n):
|
|
||||||
R[i] = g * i
|
|
||||||
|
|
||||||
# set K_pi
|
|
||||||
R[pi] = K_pi
|
|
||||||
|
|
||||||
# sign m
|
|
||||||
m = 1234
|
|
||||||
print("sign")
|
|
||||||
sig = prover.sign(m, R)
|
|
||||||
|
|
||||||
print("verify")
|
|
||||||
key_image = prover.w * hashToPoint(prover.K)
|
|
||||||
verify(g, R, m, key_image, sig)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
131
sigma.sage
131
sigma.sage
@@ -211,3 +211,134 @@ class ORVerifier:
|
|||||||
# check g*z == X*c + A (in multiplicative notation would g^z ==X^c * A)
|
# check g*z == X*c + A (in multiplicative notation would g^z ==X^c * A)
|
||||||
for i in range(len(Xs)):
|
for i in range(len(Xs)):
|
||||||
assert self.g * int(zs[i]) == Xs[i] * int(cs[i]) + self.As[i]
|
assert self.g * int(zs[i]) == Xs[i] * int(cs[i]) + self.As[i]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
import unittest, operator
|
||||||
|
|
||||||
|
# ethereum elliptic curve
|
||||||
|
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
|
||||||
|
a = 0
|
||||||
|
b = 7
|
||||||
|
F = GF(p)
|
||||||
|
E = EllipticCurve(F, [a,b])
|
||||||
|
GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
|
||||||
|
GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
|
||||||
|
g = E(GX,GY)
|
||||||
|
n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
|
||||||
|
h = 1
|
||||||
|
q = g.order()
|
||||||
|
assert is_prime(p)
|
||||||
|
assert is_prime(q)
|
||||||
|
|
||||||
|
class TestSigmaProtocol(unittest.TestCase):
|
||||||
|
def test_interactive(self):
|
||||||
|
alice = Prover_interactive(F, g)
|
||||||
|
|
||||||
|
# Alice generates witness w & statement X
|
||||||
|
X = alice.new_key()
|
||||||
|
assert X == alice.g * int(alice.w)
|
||||||
|
|
||||||
|
# Alice generates the commitment A
|
||||||
|
A = alice.new_commitment()
|
||||||
|
assert A == alice.g * int(alice.a)
|
||||||
|
|
||||||
|
# Bob generates the challenge (and stores A)
|
||||||
|
bob = Verifier_interactive(F, g)
|
||||||
|
c = bob.new_challenge(A)
|
||||||
|
|
||||||
|
# Alice generates the proof
|
||||||
|
z = alice.gen_proof(c)
|
||||||
|
|
||||||
|
# Bob verifies the proof
|
||||||
|
assert bob.verify(X, z)
|
||||||
|
|
||||||
|
# check with the generic_verify function
|
||||||
|
assert generic_verify(g, X, A, c, z)
|
||||||
|
|
||||||
|
def test_non_interactive(self):
|
||||||
|
alice = Prover(F, g)
|
||||||
|
|
||||||
|
# Alice generates witness w & statement X
|
||||||
|
X = alice.new_key()
|
||||||
|
assert X == alice.g * int(alice.w)
|
||||||
|
|
||||||
|
# Alice generates the proof
|
||||||
|
A, z = alice.gen_proof(X)
|
||||||
|
|
||||||
|
# Bob generates the challenge
|
||||||
|
bob = Verifier(F, g)
|
||||||
|
|
||||||
|
# Bob verifies the proof
|
||||||
|
assert bob.verify(X, A, z)
|
||||||
|
|
||||||
|
# check with the generic_verify function
|
||||||
|
c = hash_two_points(A, X)
|
||||||
|
assert generic_verify(g, X, A, c, z)
|
||||||
|
|
||||||
|
def test_simulator(self):
|
||||||
|
sim = Simulator(F, g)
|
||||||
|
|
||||||
|
# set a public key X, for which we don't know w
|
||||||
|
unknown_w = 3
|
||||||
|
X = g * unknown_w
|
||||||
|
|
||||||
|
# simulate for X
|
||||||
|
A, c, z = sim.simulate(X)
|
||||||
|
|
||||||
|
# verify the simulated proof
|
||||||
|
assert generic_verify(g, X, A, c, z)
|
||||||
|
|
||||||
|
class TestORProof(unittest.TestCase):
|
||||||
|
def test_2_parties(self):
|
||||||
|
# set a public key X, for which we don't know w
|
||||||
|
unknown_w = 3
|
||||||
|
X_1 = g * unknown_w
|
||||||
|
|
||||||
|
alice = ORProver_2parties(F, g)
|
||||||
|
|
||||||
|
# Alice generates key pair
|
||||||
|
X = alice.new_key()
|
||||||
|
Xs = [X, X_1]
|
||||||
|
# Alice generates commitments (internally running the simulator)
|
||||||
|
As = alice.gen_commitments(Xs)
|
||||||
|
|
||||||
|
# Bob generates the challenge (and stores As)
|
||||||
|
bob = ORVerifier_2parties(F, g)
|
||||||
|
s = bob.new_challenge(As)
|
||||||
|
|
||||||
|
# Alice generates the ORproof
|
||||||
|
cs, zs = alice.gen_proof(s)
|
||||||
|
|
||||||
|
# Bob verifies the proofs
|
||||||
|
bob.verify(Xs, cs, zs)
|
||||||
|
|
||||||
|
def test_n_parties(self):
|
||||||
|
# set n public keys X, for which we don't know w
|
||||||
|
Xs = []
|
||||||
|
for i in range(10):
|
||||||
|
X_i = g * i
|
||||||
|
Xs.append(X_i)
|
||||||
|
|
||||||
|
alice = ORProver(F, g)
|
||||||
|
|
||||||
|
# Alice generates key pair
|
||||||
|
X = alice.new_key()
|
||||||
|
Xs.insert(0, X) # add X at the begining of Xs array
|
||||||
|
|
||||||
|
# Alice generates commitments (internally running the simulator)
|
||||||
|
As = alice.gen_commitments(Xs)
|
||||||
|
|
||||||
|
# Bob generates the challenge (and stores As)
|
||||||
|
bob = ORVerifier(F, g)
|
||||||
|
s = bob.new_challenge(As)
|
||||||
|
|
||||||
|
# Alice generates the ORproof
|
||||||
|
cs, zs = alice.gen_proof(s)
|
||||||
|
|
||||||
|
# Bob verifies the proofs
|
||||||
|
bob.verify(Xs, cs, zs)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|||||||
131
sigma_test.sage
131
sigma_test.sage
@@ -1,131 +0,0 @@
|
|||||||
import unittest, operator
|
|
||||||
load("sigma.sage")
|
|
||||||
|
|
||||||
# Tests for Sigma protocol & OR proofs
|
|
||||||
|
|
||||||
|
|
||||||
# ethereum elliptic curve
|
|
||||||
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
|
|
||||||
a = 0
|
|
||||||
b = 7
|
|
||||||
F = GF(p)
|
|
||||||
E = EllipticCurve(F, [a,b])
|
|
||||||
GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
|
|
||||||
GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
|
|
||||||
g = E(GX,GY)
|
|
||||||
n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
|
|
||||||
h = 1
|
|
||||||
q = g.order()
|
|
||||||
assert is_prime(p)
|
|
||||||
assert is_prime(q)
|
|
||||||
|
|
||||||
class TestSigmaProtocol(unittest.TestCase):
|
|
||||||
def test_interactive(self):
|
|
||||||
alice = Prover_interactive(F, g)
|
|
||||||
|
|
||||||
# Alice generates witness w & statement X
|
|
||||||
X = alice.new_key()
|
|
||||||
assert X == alice.g * int(alice.w)
|
|
||||||
|
|
||||||
# Alice generates the commitment A
|
|
||||||
A = alice.new_commitment()
|
|
||||||
assert A == alice.g * int(alice.a)
|
|
||||||
|
|
||||||
# Bob generates the challenge (and stores A)
|
|
||||||
bob = Verifier_interactive(F, g)
|
|
||||||
c = bob.new_challenge(A)
|
|
||||||
|
|
||||||
# Alice generates the proof
|
|
||||||
z = alice.gen_proof(c)
|
|
||||||
|
|
||||||
# Bob verifies the proof
|
|
||||||
assert bob.verify(X, z)
|
|
||||||
|
|
||||||
# check with the generic_verify function
|
|
||||||
assert generic_verify(g, X, A, c, z)
|
|
||||||
|
|
||||||
def test_non_interactive(self):
|
|
||||||
alice = Prover(F, g)
|
|
||||||
|
|
||||||
# Alice generates witness w & statement X
|
|
||||||
X = alice.new_key()
|
|
||||||
assert X == alice.g * int(alice.w)
|
|
||||||
|
|
||||||
# Alice generates the proof
|
|
||||||
A, z = alice.gen_proof(X)
|
|
||||||
|
|
||||||
# Bob generates the challenge
|
|
||||||
bob = Verifier(F, g)
|
|
||||||
|
|
||||||
# Bob verifies the proof
|
|
||||||
assert bob.verify(X, A, z)
|
|
||||||
|
|
||||||
# check with the generic_verify function
|
|
||||||
c = hash_two_points(A, X)
|
|
||||||
assert generic_verify(g, X, A, c, z)
|
|
||||||
|
|
||||||
def test_simulator(self):
|
|
||||||
sim = Simulator(F, g)
|
|
||||||
|
|
||||||
# set a public key X, for which we don't know w
|
|
||||||
unknown_w = 3
|
|
||||||
X = g * unknown_w
|
|
||||||
|
|
||||||
# simulate for X
|
|
||||||
A, c, z = sim.simulate(X)
|
|
||||||
|
|
||||||
# verify the simulated proof
|
|
||||||
assert generic_verify(g, X, A, c, z)
|
|
||||||
|
|
||||||
class TestORProof(unittest.TestCase):
|
|
||||||
def test_2_parties(self):
|
|
||||||
# set a public key X, for which we don't know w
|
|
||||||
unknown_w = 3
|
|
||||||
X_1 = g * unknown_w
|
|
||||||
|
|
||||||
alice = ORProver_2parties(F, g)
|
|
||||||
|
|
||||||
# Alice generates key pair
|
|
||||||
X = alice.new_key()
|
|
||||||
Xs = [X, X_1]
|
|
||||||
# Alice generates commitments (internally running the simulator)
|
|
||||||
As = alice.gen_commitments(Xs)
|
|
||||||
|
|
||||||
# Bob generates the challenge (and stores As)
|
|
||||||
bob = ORVerifier_2parties(F, g)
|
|
||||||
s = bob.new_challenge(As)
|
|
||||||
|
|
||||||
# Alice generates the ORproof
|
|
||||||
cs, zs = alice.gen_proof(s)
|
|
||||||
|
|
||||||
# Bob verifies the proofs
|
|
||||||
bob.verify(Xs, cs, zs)
|
|
||||||
|
|
||||||
def test_n_parties(self):
|
|
||||||
# set n public keys X, for which we don't know w
|
|
||||||
Xs = []
|
|
||||||
for i in range(10):
|
|
||||||
X_i = g * i
|
|
||||||
Xs.append(X_i)
|
|
||||||
|
|
||||||
alice = ORProver(F, g)
|
|
||||||
|
|
||||||
# Alice generates key pair
|
|
||||||
X = alice.new_key()
|
|
||||||
Xs.insert(0, X) # add X at the begining of Xs array
|
|
||||||
|
|
||||||
# Alice generates commitments (internally running the simulator)
|
|
||||||
As = alice.gen_commitments(Xs)
|
|
||||||
|
|
||||||
# Bob generates the challenge (and stores As)
|
|
||||||
bob = ORVerifier(F, g)
|
|
||||||
s = bob.new_challenge(As)
|
|
||||||
|
|
||||||
# Alice generates the ORproof
|
|
||||||
cs, zs = alice.gen_proof(s)
|
|
||||||
|
|
||||||
# Bob verifies the proofs
|
|
||||||
bob.verify(Xs, cs, zs)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
Reference in New Issue
Block a user