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
|
||||
fc2=P(fc_coef.list())
|
||||
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
|
||||
|
||||
|
||||
# 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:
|
||||
raise Exception("inv_mod err, g!=1")
|
||||
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
|
||||
# bLSAG: Back’s Linkable Spontaneous Anonymous Group signatures
|
||||
#
|
||||
# A Rust implementation of this scheme can be found at:
|
||||
# https://github.com/arnaucube/ring-signatures-rs
|
||||
|
||||
@@ -93,3 +94,57 @@ def verify(g, R, m, key_image, sig):
|
||||
|
||||
print_ring(c)
|
||||
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)
|
||||
for i in range(len(Xs)):
|
||||
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