diff --git a/fft.sage b/fft.sage index 6f7bbdd..c01d17e 100644 --- a/fft.sage +++ b/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. = 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 diff --git a/fft_test.sage b/fft_test.sage deleted file mode 100644 index f2a1cf3..0000000 --- a/fft_test.sage +++ /dev/null @@ -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. = 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 diff --git a/ipa.sage b/ipa.sage index b6cee17..55dbada 100644 --- a/ipa.sage +++ b/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 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() diff --git a/ipa_test.sage b/ipa_test.sage deleted file mode 100644 index bcf6b2b..0000000 --- a/ipa_test.sage +++ /dev/null @@ -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 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() diff --git a/number-theory.sage b/number-theory.sage index d7928c4..db5353c 100644 --- a/number-theory.sage +++ b/number-theory.sage @@ -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 diff --git a/number-theory_test.sage b/number-theory_test.sage deleted file mode 100644 index 8011de5..0000000 --- a/number-theory_test.sage +++ /dev/null @@ -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 diff --git a/ring-signatures.sage b/ring-signatures.sage index 58442b2..f5eb873 100644 --- a/ring-signatures.sage +++ b/ring-signatures.sage @@ -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() diff --git a/ring-signatures_test.sage b/ring-signatures_test.sage deleted file mode 100644 index f91babc..0000000 --- a/ring-signatures_test.sage +++ /dev/null @@ -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() diff --git a/sigma.sage b/sigma.sage index a2d61c3..e8c48f4 100644 --- a/sigma.sage +++ b/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() diff --git a/sigma_test.sage b/sigma_test.sage deleted file mode 100644 index d882e29..0000000 --- a/sigma_test.sage +++ /dev/null @@ -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()