You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@milagro.apache.org by sa...@apache.org on 2020/05/14 22:46:04 UTC
[incubator-milagro-MPC] 06/06: update python wrappers
This is an automated email from the ASF dual-hosted git repository.
sandreoli pushed a commit to branch review-ncc
in repository https://gitbox.apache.org/repos/asf/incubator-milagro-MPC.git
commit 739cfe6ee667c908a4fe598bc634d5426a596c25
Author: Samuele Andreoli <sa...@yahoo.it>
AuthorDate: Thu May 14 23:43:57 2020 +0100
update python wrappers
---
python/amcl/core_utils.py | 2 ++
python/amcl/factoring_zk.py | 48 +++++++++++++++++++++----------
python/amcl/schnorr.py | 25 +++++++++++------
python/benchmark/bench_schnorr.py | 14 +++++----
python/benchmark/bench_zk_factoring.py | 20 +++++++------
python/examples/example_full.py | 43 +++++++++++++++++-----------
python/examples/example_schnorr.py | 24 ++++++++++------
python/examples/example_zk_factoring.py | 16 +++++++----
python/test/CMakeLists.txt | 2 +-
python/test/test_schnorr.py | 11 ++++++--
python/test/test_zk_factoring.py | 50 +++++++++++++++++++++------------
11 files changed, 167 insertions(+), 88 deletions(-)
diff --git a/python/amcl/core_utils.py b/python/amcl/core_utils.py
index 4b09d65..cfad037 100644
--- a/python/amcl/core_utils.py
+++ b/python/amcl/core_utils.py
@@ -197,6 +197,8 @@ def generate_random(rng, length):
"""
random_value1, random_value1_val = make_octet(length)
+ _ = random_value1_val # Suppress warning
+
_libamcl_core.generateRandom(rng, random_value1)
random_value = to_str(random_value1)
diff --git a/python/amcl/factoring_zk.py b/python/amcl/factoring_zk.py
index d4eb3d6..32b8f3f 100644
--- a/python/amcl/factoring_zk.py
+++ b/python/amcl/factoring_zk.py
@@ -28,8 +28,8 @@ from . import core_utils
_ffi = core_utils._ffi
_ffi.cdef("""
-void FACTORING_ZK_prove(csprng *RNG, octet *P, octet *Q, octet *R, octet *E, octet *Y);
-int FACTORING_ZK_verify(octet *N, octet *E, octet *Y);
+void FACTORING_ZK_prove(csprng *RNG, octet *P, octet *Q, octet *ID, octet *AD, octet *R, octet *E, octet *Y);
+int FACTORING_ZK_verify(octet *N, octet *E, octet *Y, octet *ID, octet *AD);
""")
if (platform.system() == 'Windows'):
@@ -51,7 +51,7 @@ OK = 0
FAIL = 91
-def prove(rng, p, q, r=None):
+def prove(rng, p, q, id, ad=None, r=None):
"""Generate factoring knowledge proof
@@ -62,6 +62,8 @@ def prove(rng, p, q, r=None):
number generator instance
p : First prime factor of n. HFS_2048 bytes long
q : Second prime factor of n. HFS_2048 bytes long
+ id : Unique identifier of the prover
+ ad : Additional data to bind in the proof. Optional
r : Deterministic value for r. FS_2048 bytes long
Returns::
@@ -79,13 +81,20 @@ def prove(rng, p, q, r=None):
_ = r_val # Suppress warning
rng = _ffi.NULL
- p_oct, p_val = core_utils.make_octet(None, p)
- q_oct, q_val = core_utils.make_octet(None, q)
- e_oct, e_val = core_utils.make_octet(B)
- y_oct, y_val = core_utils.make_octet(FS_2048)
- _ = p_val, q_val, e_val, y_val # Suppress warnings
+ if ad is None:
+ ad_oct = _ffi.NULL
+ else:
+ ad_oct, ad_val = core_utils.make_octet(None, ad)
+ _ = ad_val # Suppress warning
+
+ p_oct, p_val = core_utils.make_octet(None, p)
+ q_oct, q_val = core_utils.make_octet(None, q)
+ e_oct, e_val = core_utils.make_octet(B)
+ y_oct, y_val = core_utils.make_octet(FS_2048)
+ id_oct, id_val = core_utils.make_octet(None, id)
+ _ = p_val, q_val, e_val, y_val, id_val # Suppress warnings
- _libamcl_mpc.FACTORING_ZK_prove(rng, p_oct, q_oct, r_oct, e_oct, y_oct)
+ _libamcl_mpc.FACTORING_ZK_prove(rng, p_oct, q_oct, id_oct, ad_oct, r_oct, e_oct, y_oct)
# Clear memory
core_utils.clear_octet(p_oct)
@@ -94,7 +103,7 @@ def prove(rng, p, q, r=None):
return core_utils.to_str(e_oct), core_utils.to_str(y_oct)
-def verify(n, e, y):
+def verify(n, e, y, id, ad=None):
"""Verify knowledge of factoring proof
Args::
@@ -102,6 +111,8 @@ def verify(n, e, y):
n : public modulus
e : First component of the factoring proof. B bytes long
y : Second component of the factoring proof. FS_2048 bytes long
+ id : Unique identifier of the prover
+ ad : Additional data to bind in the challenge. Optional
Returns::
@@ -110,11 +121,18 @@ def verify(n, e, y):
Raises:
"""
- n_oct, n_val = core_utils.make_octet(None, n)
- e_oct, e_val = core_utils.make_octet(None, e)
- y_oct, y_val = core_utils.make_octet(None, y)
- _ = n_val, e_val, y_val # Suppress warning
+ if ad is None:
+ ad_oct = _ffi.NULL
+ else:
+ ad_oct, ad_val = core_utils.make_octet(None, ad)
+ _ = ad_val # Suppress warning
+
+ n_oct, n_val = core_utils.make_octet(None, n)
+ e_oct, e_val = core_utils.make_octet(None, e)
+ y_oct, y_val = core_utils.make_octet(None, y)
+ id_oct, id_val = core_utils.make_octet(None, id)
+ _ = n_val, e_val, y_val, id_val # Suppress warning
- rc = _libamcl_mpc.FACTORING_ZK_verify(n_oct, e_oct, y_oct)
+ rc = _libamcl_mpc.FACTORING_ZK_verify(n_oct, e_oct, y_oct, id_oct, ad_oct)
return rc
diff --git a/python/amcl/schnorr.py b/python/amcl/schnorr.py
index d6c462c..49b57d3 100644
--- a/python/amcl/schnorr.py
+++ b/python/amcl/schnorr.py
@@ -30,7 +30,7 @@ _ffi = core_utils._ffi
_ffi.cdef("""
extern void SCHNORR_random_challenge(csprng *RNG, octet *E);
extern void SCHNORR_commit(csprng *RNG, octet *R, octet *C);
-extern void SCHNORR_challenge(const octet *V, const octet *C, octet *E);
+extern void SCHNORR_challenge(const octet *V, const octet *C, octet *ID, octet *AD, octet *E);
extern void SCHNORR_prove(const octet *R, const octet *E, const octet *X, octet *P);
extern int SCHNORR_verify(octet *V, octet *C, const octet *E, const octet *P);
""")
@@ -121,7 +121,7 @@ def commit(rng, r=None):
return r, core_utils.to_str(C)
-def challenge(V, C):
+def challenge(V, C, ID, AD=None):
"""Generate a deterministic challenge for the Schnorr's Proof
Generates a deterministic value r in [0, .., q] suitable as a
@@ -130,8 +130,10 @@ def challenge(V, C):
Args::
- V : Public ECP of the DLOG. V = x.G
- C : Commitment for the Schnorr's Proof
+ V : Public ECP of the DLOG. V = x.G
+ C : Commitment for the Schnorr's Proof
+ ID : Unique idenitifier of the prover
+ AD : Additional data to bind in the challenge. Optional
Returns::
@@ -140,14 +142,21 @@ def challenge(V, C):
Raises:
"""
- V_oct, V_val = core_utils.make_octet(None, V)
- C_oct, C_val = core_utils.make_octet(None, C)
- _ = V_val, C_val # Suppress warning
+ if AD is None:
+ AD_oct = _ffi.NULL
+ else:
+ AD_oct, AD_val = core_utils.make_octet(None, AD)
+ _ = AD_val # Suppress warning
+
+ V_oct, V_val = core_utils.make_octet(None, V)
+ C_oct, C_val = core_utils.make_octet(None, C)
+ ID_oct, ID_val = core_utils.make_octet(None, ID)
+ _ = V_val, C_val, ID_val # Suppress warning
e, e_val = core_utils.make_octet(EGS)
_ = e_val # Suppress warning
- _libamcl_mpc.SCHNORR_challenge(V_oct, C_oct, e)
+ _libamcl_mpc.SCHNORR_challenge(V_oct, C_oct, ID_oct, AD_oct, e)
return core_utils.to_str(e)
diff --git a/python/benchmark/bench_schnorr.py b/python/benchmark/bench_schnorr.py
index ba95584..e70e68c 100755
--- a/python/benchmark/bench_schnorr.py
+++ b/python/benchmark/bench_schnorr.py
@@ -30,14 +30,18 @@ r_hex = "803ccd21cddad626e15f21b1ad787949e9beef08e6e68a9e00df59dec16ed290"
x_hex = "fab4ce512dff74bd9c71c89a14de5b877af45dca0329ee3fcb72611c0784fef3"
V_hex = "032cf4b348c9d00718f01ed98923e164df53b5e8bc4c2250662ed2df784e1784f4"
+ID = b"unique_user_identifier"
+AD_hex = "d7d3155616778fb436a1eb2070892205"
+
if __name__ == "__main__":
- r = bytes.fromhex(r_hex)
- x = bytes.fromhex(x_hex)
- V = bytes.fromhex(V_hex)
+ r = bytes.fromhex(r_hex)
+ x = bytes.fromhex(x_hex)
+ V = bytes.fromhex(V_hex)
+ AD = bytes.fromhex(AD_hex)
# Generate quantities for benchmark
r, C = schnorr.commit(None, r)
- e = schnorr.challenge(V, C)
+ e = schnorr.challenge(V, C, ID, AD=AD)
p = schnorr.prove(r, e, x)
# Check consistency of the generated quantities
@@ -47,7 +51,7 @@ if __name__ == "__main__":
fncall = lambda: schnorr.commit(None, r)
time_func("commit ", fncall, unit="us")
- fncall = lambda: schnorr.challenge(V, C)
+ fncall = lambda: schnorr.challenge(V, C, ID, AD=AD)
time_func("challenge", fncall, unit="us")
fncall = lambda: schnorr.prove(r, e, x)
diff --git a/python/benchmark/bench_zk_factoring.py b/python/benchmark/bench_zk_factoring.py
index f9ab584..342f067 100755
--- a/python/benchmark/bench_zk_factoring.py
+++ b/python/benchmark/bench_zk_factoring.py
@@ -31,19 +31,23 @@ q_hex = "dbffe278edd44c2655714e5a4cc82e66e46063f9ab69df9d0ed20eb3d7f2d8c7d985df7
n_hex = "c0870b552afb6c8c09f79e39ad6ca17ca93085c2cd7a726ade69574961ff9ce8ad33c7dda2e0703a3b0010c2e5bb7552c74164ce8dd011d85e5969090df53fe10e39cbe530704da32ff07228a6b6da34a5929e8a231c3080d812dc6e93affd81682339a6aee192927c582da8941bebf46e13c4ea3918a1477951fa66d367e70d8551b1869316d48317e0702d7bce242a326000f3dc763c44eba2044a1df713a94c1339edd464b145dcadf94e6e61be73dc270c878e1a28be720df2209202d00e101c3b255b757eaf547acd863d51eb676b851511b3dadeda926714719dceddd3af7908893ae65f2b95ee5c4d36cc6862cbe [...]
r_hex = "c05f6c79e81fab2f1aa6af48dc5afa89a21c0aee03e93944cacfefef1be90f41ec8c2055760beafa9ed87dd67dbd56b33a2568dfec62a03f06c4f8449a93eee858507f4b602bf305e1c9968d9f5b6dc3120c27e053a1d7e51590e0bacb8d36c27bccce1a57c1e3aeb0832905d4e2bb8eaee883b4df042d8660cf3e0c9777b6be34c18bef02347f92cb71f372f61c018860211932dd46de8f925212d7afe6dd2f3cda05f8d5a6bd1b138b66c5efd7fca31f926c721f6d4207b97fc01cdf325da21233f6df37adbcd67472b332f7490a4a96e0fef31beef55b9446067b8e8d807384e3d31051c7a1f27296a6ae111b30c3d1f [...]
+uid = b"unique_user_identifier"
+ad_hex = "d7d3155616778fb436a1eb2070892205"
+
if __name__ == "__main__":
- p = bytes.fromhex(p_hex)
- q = bytes.fromhex(q_hex)
- n = bytes.fromhex(n_hex)
- r = bytes.fromhex(r_hex)
+ p = bytes.fromhex(p_hex)
+ q = bytes.fromhex(q_hex)
+ n = bytes.fromhex(n_hex)
+ r = bytes.fromhex(r_hex)
+ ad = bytes.fromhex(ad_hex)
# Generate quantities for benchmark
- e, y = factoring_zk.prove(None, p, q, r)
- assert factoring_zk.verify(n, e, y) == factoring_zk.OK
+ e, y = factoring_zk.prove(None, p, q, uid, ad=ad, r=r)
+ assert factoring_zk.verify(n, e, y, uid, ad=ad) == factoring_zk.OK
# Run benchmark
- fncall = lambda: factoring_zk.prove(None, p, q, r)
+ fncall = lambda: factoring_zk.prove(None, p, q, uid, ad=ad, r=r)
time_func("prove ", fncall)
- fncall = lambda: factoring_zk.verify(n, e, y)
+ fncall = lambda: factoring_zk.verify(n, e, y, uid, ad=ad)
time_func("verify", fncall)
diff --git a/python/examples/example_full.py b/python/examples/example_full.py
index cece81b..f8b0448 100755
--- a/python/examples/example_full.py
+++ b/python/examples/example_full.py
@@ -66,7 +66,7 @@ def generate_key_material(rng, player):
return key_material
-def generate_key_material_zkp(rng, key_material):
+def generate_key_material_zkp(rng, key_material, ID, AD=None):
""" Generate ZK Proofs for key material
Generate a commitment to the ECDSA PK, a Schnorr's
@@ -98,19 +98,19 @@ def generate_key_material_zkp(rng, key_material):
# Generate Schnorr's proof for ECDSA PK
sr, sc = schnorr.commit(rng)
- e = schnorr.challenge(key_material['ecdsa_pk'], sc)
+ e = schnorr.challenge(key_material['ecdsa_pk'], sc, ID, AD=AD)
sp = schnorr.prove(sr, e, key_material['ecdsa_sk'])
# Generate ZKP of knowledge of factorization for
# Paillier key pair
psk_p, psk_q = mpc.mpc_dump_paillier_sk(key_material['paillier_sk'])
- fe, fy = factoring_zk.prove(rng, psk_p, psk_q)
+ fe, fy = factoring_zk.prove(rng, psk_p, psk_q, ID, ad=AD)
return r, c, sc, sp, fe, fy
-def verify_key_material(key_material, r, c, sc, sp, fe, fy, player):
+def verify_key_material(key_material, r, c, sc, sp, fe, fy, player, ID, AD=None):
""" Verify key material
Verify the conunterparty key material using the
@@ -137,13 +137,13 @@ def verify_key_material(key_material, r, c, sc, sp, fe, fy, player):
assert rc == commitments.OK, f"[{player}] Failure decommitting ecdsa_pk. rc {rc}"
# Verify ECDSA PK Schnorr's proof
- e = schnorr.challenge(key_material['ecdsa_pk'], sc)
+ e = schnorr.challenge(key_material['ecdsa_pk'], sc, ID, AD=AD)
rc = schnorr.verify(key_material['ecdsa_pk'], sc, e, sp)
assert rc == schnorr.OK, f"[{player}] Invalid ECDSA PK Schnorr Proof. rc {rc}"
# Verify factoring ZKP
n = mpc.paillier_pk_to_octet(key_material['paillier_pk'])
- rc = factoring_zk.verify(n, fe, fy)
+ rc = factoring_zk.verify(n, fe, fy, ID, ad=AD)
assert rc == factoring_zk.OK, f"[{player}] Invalid Factoring ZKP. rc {rc}"
@@ -152,6 +152,9 @@ if __name__ == "__main__":
rng = core_utils.create_csprng(seed)
+ alice_id = b"alice_unique_identifier"
+ bob_id = b"bob_unique_identifier"
+
### Key setup ###
print("Setup Key Material\n")
@@ -160,12 +163,16 @@ if __name__ == "__main__":
key_material1 = generate_key_material(rng, "Alice")
key_material2 = generate_key_material(rng, "Bob")
+ # Generate and exchange nonce for liveliness
+ alice_ad = core_utils.generate_random(rng, 32)
+ bob_ad = core_utils.generate_random(rng, 32)
+
print("[Alice] Generate ECDSA and Paillier key pairs")
print("[Bob] Generate ECDSA and Paillier key pairs")
# Generate key material ZKP
- r1, c1, sc1, sp1, fe1, fy1 = generate_key_material_zkp(rng, key_material1)
- r2, c2, sc2, sp2, fe2, fy2 = generate_key_material_zkp(rng, key_material2)
+ r1, c1, sc1, sp1, fe1, fy1 = generate_key_material_zkp(rng, key_material1, alice_id, AD = alice_ad)
+ r2, c2, sc2, sp2, fe2, fy2 = generate_key_material_zkp(rng, key_material2, bob_id, AD = bob_ad)
print("[Alice] Generate commitment to ECDSA PK and ZKPs")
print("[Bob] Generate commitment to ECDSA PK and ZKPs")
@@ -190,10 +197,10 @@ if __name__ == "__main__":
}
print("[Alice] Verify ZKP")
- verify_key_material(c_key_material1, r2, c2, sc2, sp2, fe2, fy2, "Alice")
+ verify_key_material(c_key_material1, r2, c2, sc2, sp2, fe2, fy2, "Alice", bob_id, AD=bob_ad)
print("[Bob] Verify ZKP")
- verify_key_material(c_key_material2, r1, c1, sc1, sp1, fe1, fy1, "Bob")
+ verify_key_material(c_key_material2, r1, c1, sc1, sp1, fe1, fy1, "Bob", alice_id, AD=alice_ad)
# Recombine full ECDSA PK
rc, ecdsa_full_pk1 = mpc.mpc_sum_pk(key_material1['ecdsa_pk'], c_key_material1['ecdsa_pk'])
@@ -208,7 +215,7 @@ if __name__ == "__main__":
# Message
M = b'test message'
- print(f"\nSign message '{M.encode('utf-8')}'")
+ print(f"\nSign message '{M.decode('utf-8')}'")
# Generate k, gamma and gamma.G
print("[Alice] Generate k, gamma and gamma.G")
@@ -219,13 +226,17 @@ if __name__ == "__main__":
GAMMA2, gamma2 = mpc.mpc_ecdsa_key_pair_generate(rng)
k2 = mpc.mpc_k_generate(rng)
- ## Commit to GAMMA1, GAMMA2
+ ## Commit to GAMMA1, GAMMA2 and exchange nonces for liveliness
print("[Alice] Commit to GAMMA1")
GAMMAR1, GAMMAC1 = commitments.nm_commit(rng, GAMMA1)
+ bob_ad = core_utils.generate_random(rng, 32)
+
print("[Bob] Commit to GAMMA2")
GAMMAR2, GAMMAC2 = commitments.nm_commit(rng, GAMMA2)
+ alice_ad = core_utils.generate_random(rng, 32)
+
## Engage in MTA with k_i, gamma_j
# k1, gamma2
@@ -275,12 +286,12 @@ if __name__ == "__main__":
# Generate Schnorr's Proofs
print("[Alice] Generate Schnorr's Proof")
GAMMA_schnorr_r1, GAMMA_schnorr_c1 = schnorr.commit(rng)
- GAMMA_schnorr_e1 = schnorr.challenge(GAMMA1, GAMMA_schnorr_c1)
+ GAMMA_schnorr_e1 = schnorr.challenge(GAMMA1, GAMMA_schnorr_c1, alice_id, AD = alice_ad)
GAMMA_schnorr_p1 = schnorr.prove(GAMMA_schnorr_r1, GAMMA_schnorr_e1, gamma1)
print("[Bob] Generate Schnorr's Proof")
GAMMA_schnorr_r2, GAMMA_schnorr_c2 = schnorr.commit(rng)
- GAMMA_schnorr_e2 = schnorr.challenge(GAMMA2, GAMMA_schnorr_c2)
+ GAMMA_schnorr_e2 = schnorr.challenge(GAMMA2, GAMMA_schnorr_c2, bob_id, AD = bob_ad)
GAMMA_schnorr_p2 = schnorr.prove(GAMMA_schnorr_r2, GAMMA_schnorr_e2, gamma2)
print("[Alice] Transmit decommitment and Schnorr Proof for GAMMA1")
@@ -290,14 +301,14 @@ if __name__ == "__main__":
rc = commitments.nm_decommit(GAMMA2, GAMMAR2, GAMMAC2)
assert rc == commitments.OK, f'[Alice] Error decommitting GAMMA2. rc {rc}'
- GAMMA_schnorr_e2 = schnorr.challenge(GAMMA2, GAMMA_schnorr_c2)
+ GAMMA_schnorr_e2 = schnorr.challenge(GAMMA2, GAMMA_schnorr_c2, bob_id, AD=bob_ad)
rc = schnorr.verify(GAMMA2, GAMMA_schnorr_c2, GAMMA_schnorr_e2, GAMMA_schnorr_p2)
assert rc == schnorr.OK, f'[Alice] Error verifying Schnorr proof for GAMMA2'
rc = commitments.nm_decommit(GAMMA1, GAMMAR1, GAMMAC1)
assert rc == commitments.OK, f'[Bob] Error decommitting GAMMA1. rc {rc}'
- GAMMA_schnorr_e1 = schnorr.challenge(GAMMA1, GAMMA_schnorr_c1)
+ GAMMA_schnorr_e1 = schnorr.challenge(GAMMA1, GAMMA_schnorr_c1, alice_id, AD=alice_ad)
rc = schnorr.verify(GAMMA1, GAMMA_schnorr_c1, GAMMA_schnorr_e1, GAMMA_schnorr_p1)
assert rc == schnorr.OK, f'[Bob] Error verifying Schnorr proof for GAMMA1'
diff --git a/python/examples/example_schnorr.py b/python/examples/example_schnorr.py
index 0e12cd2..b6592d4 100755
--- a/python/examples/example_schnorr.py
+++ b/python/examples/example_schnorr.py
@@ -31,19 +31,25 @@ seed_hex = "78d0fb6705ce77dee47d03eb5b9c5d30"
x_hex = "fab4ce512dff74bd9c71c89a14de5b877af45dca0329ee3fcb72611c0784fef3"
V_hex = "032cf4b348c9d00718f01ed98923e164df53b5e8bc4c2250662ed2df784e1784f4"
+ID = b"unique_user_identifier"
+
if __name__ == "__main__":
seed = bytes.fromhex(seed_hex)
- x = bytes.fromhex(x_hex)
- V = bytes.fromhex(V_hex)
+ x = bytes.fromhex(x_hex)
+ V = bytes.fromhex(V_hex)
# random number generator
rng = core_utils.create_csprng(seed)
+ AD = core_utils.generate_random(rng, 32)
+
print("Example Schnorr Protocol")
print("DLOG: V = x.G")
- print(f"\tx = {x_hex}")
- print(f"\tV = {V_hex}")
+ print(f"\tx = {x_hex}")
+ print(f"\tV = {V_hex}")
+ print(f"\tID = {ID.decode('utf-8')}")
+ print(f"\tAD = {AD.hex()}")
# Generate commitment C = r.G, r random in [0, ..., q]
r, C = schnorr.commit(rng)
@@ -52,10 +58,10 @@ if __name__ == "__main__":
print(f"\tr = {r.hex()}")
print(f"\tC = {C.hex()}")
- # Generate deterministic challenge e = H(G, V, C)
- e = schnorr.challenge(V, C)
+ # Generate deterministic challenge e = H(G, V, C, ID, AD)
+ e = schnorr.challenge(V, C, ID, AD = AD)
- print("\n[Prover] Deterministic Challenge e = H(G, V, C)")
+ print("\n[Prover] Deterministic Challenge e = H(G, V, C, ID, AD)")
print(f"\te = {e.hex()}")
# Generate proof p = r - ex mod q
@@ -65,8 +71,8 @@ if __name__ == "__main__":
print(f"\tp = {p.hex()}")
# Verifier regenerates deterministic challenge
- e = schnorr.challenge(V, C)
- print("\n[Verifier] Deterministic Challenge e = H(G, V, C)")
+ e = schnorr.challenge(V, C, ID, AD = AD)
+ print("\n[Verifier] Deterministic Challenge e = H(G, V, C, ID, AD)")
print(f"\te = {e.hex()}")
# Verify
diff --git a/python/examples/example_zk_factoring.py b/python/examples/example_zk_factoring.py
index 08d6f6a..bf80508 100755
--- a/python/examples/example_zk_factoring.py
+++ b/python/examples/example_zk_factoring.py
@@ -32,6 +32,8 @@ p_hex = "e008507e09c24d756280f3d94912fb9ac16c0a8a1757ee01a350736acfc7f65880f87ec
q_hex = "dbffe278edd44c2655714e5a4cc82e66e46063f9ab69df9d0ed20eb3d7f2d8c7d985df71c28707f32b961d160ca938e9cf909cd77c4f8c630aec34b67714cbfd4942d7147c509db131bc2d6a667eb30df146f64b710f8f5247848b0a75738a38772e31014fd63f0b769209928d586499616dcc90700b393156e12eea7e15a835"
n_hex = "c0870b552afb6c8c09f79e39ad6ca17ca93085c2cd7a726ade69574961ff9ce8ad33c7dda2e0703a3b0010c2e5bb7552c74164ce8dd011d85e5969090df53fe10e39cbe530704da32ff07228a6b6da34a5929e8a231c3080d812dc6e93affd81682339a6aee192927c582da8941bebf46e13c4ea3918a1477951fa66d367e70d8551b1869316d48317e0702d7bce242a326000f3dc763c44eba2044a1df713a94c1339edd464b145dcadf94e6e61be73dc270c878e1a28be720df2209202d00e101c3b255b757eaf547acd863d51eb676b851511b3dadeda926714719dceddd3af7908893ae65f2b95ee5c4d36cc6862cbe [...]
+uid = b"unique_user_identifier"
+
if __name__ == "__main__":
seed = bytes.fromhex(seed_hex)
rng = core_utils.create_csprng(seed)
@@ -40,21 +42,25 @@ if __name__ == "__main__":
q = bytes.fromhex(q_hex)
n = bytes.fromhex(n_hex)
+ ad = core_utils.generate_random(rng, 32)
+
print("Example ZK Proof of Knowledge of factoring")
print("Parameters")
- print(f"\tP = {p.hex()}")
- print(f"\tQ = {q.hex()}")
- print(f"\tN = {n.hex()}")
+ print(f"\tP = {p.hex()}")
+ print(f"\tQ = {q.hex()}")
+ print(f"\tN = {n.hex()}")
+ print(f"\tID = {uid.decode('utf-8')}")
+ print(f"\tAD = {ad.hex()}")
# Prove
- e, y = factoring_zk.prove(rng, p, q, None)
+ e, y = factoring_zk.prove(rng, p, q, uid, ad=ad)
print("\nGenerate proof")
print(f"\tE = {e.hex()}")
print(f"\tY = {y.hex()}")
# Verify
- ec = factoring_zk.verify(n, e, y)
+ ec = factoring_zk.verify(n, e, y, uid, ad=ad)
print("\nVerify proof")
if ec == factoring_zk.OK:
diff --git a/python/test/CMakeLists.txt b/python/test/CMakeLists.txt
index ced24cd..77def9b 100644
--- a/python/test/CMakeLists.txt
+++ b/python/test/CMakeLists.txt
@@ -60,9 +60,9 @@ file(COPY ${GCM_TV} DESTINATION "${PROJECT_BINARY_DIR}/python/test/gcm/")
if(NOT CMAKE_BUILD_TYPE STREQUAL "ASan")
add_python_test(test_python_aes test_aes.py)
add_python_test(test_python_mpc_mta test_mta.py)
+ add_python_test(test_python_mpc_ecdsa test_ecdsa.py)
add_python_test(test_python_mpc_r test_r.py)
add_python_test(test_python_mpc_s test_s.py)
- add_python_test(test_python_mpc_ecdsa test_ecdsa.py)
add_python_test(test_python_mpc_schnorr test_schnorr.py)
add_python_test(test_python_mpc_nm_commit test_nm_commit.py)
add_python_test(test_python_mpc_zk_factoring test_zk_factoring.py)
diff --git a/python/test/test_schnorr.py b/python/test/test_schnorr.py
index 766c37f..9423265 100755
--- a/python/test/test_schnorr.py
+++ b/python/test/test_schnorr.py
@@ -78,12 +78,17 @@ class TestChallenge(unittest.TestCase):
""" Test using test vectors """
for vector in self.tv:
- V = bytes.fromhex(vector["V"])
- C = bytes.fromhex(vector["C"])
+ V = bytes.fromhex(vector["V"])
+ C = bytes.fromhex(vector["C"])
+ ID = bytes.fromhex(vector["ID"])
+ AD = bytes.fromhex(vector["AD"])
+
+ if not AD:
+ AD = None
e_golden = bytes.fromhex(vector["E"])
- e = schnorr.challenge(V, C)
+ e = schnorr.challenge(V, C, ID, AD=AD)
self.assertEqual(e, e_golden)
diff --git a/python/test/test_zk_factoring.py b/python/test/test_zk_factoring.py
index 7218de5..42f2ea0 100755
--- a/python/test/test_zk_factoring.py
+++ b/python/test/test_zk_factoring.py
@@ -30,11 +30,21 @@ from amcl import core_utils, factoring_zk
seed_hex = "78d0fb6705ce77dee47d03eb5b9c5d30"
-p_hex = "e008507e09c24d756280f3d94912fb9ac16c0a8a1757ee01a350736acfc7f65880f87eca55d6680253383fc546d03fd9ebab7d8fa746455180888cb7c17edf58d3327296468e5ab736374bc9a0fa02606ed5d3a4a5fb1677891f87fbf3c655c3e0549a86b17b7ddce07c8f73e253105e59f5d3ed2c7ba5bdf8495df40ae71a7f"
-q_hex = "dbffe278edd44c2655714e5a4cc82e66e46063f9ab69df9d0ed20eb3d7f2d8c7d985df71c28707f32b961d160ca938e9cf909cd77c4f8c630aec34b67714cbfd4942d7147c509db131bc2d6a667eb30df146f64b710f8f5247848b0a75738a38772e31014fd63f0b769209928d586499616dcc90700b393156e12eea7e15a835"
+p_hex = "e008507e09c24d756280f3d94912fb9ac16c0a8a1757ee01a350736acfc7f65880f87eca55d6680253383fc546d03fd9ebab7d8fa746455180888cb7c17edf58d3327296468e5ab736374bc9a0fa02606ed5d3a4a5fb1677891f87fbf3c655c3e0549a86b17b7ddce07c8f73e253105e59f5d3ed2c7ba5bdf8495df40ae71a7f"
+q_hex = "dbffe278edd44c2655714e5a4cc82e66e46063f9ab69df9d0ed20eb3d7f2d8c7d985df71c28707f32b961d160ca938e9cf909cd77c4f8c630aec34b67714cbfd4942d7147c509db131bc2d6a667eb30df146f64b710f8f5247848b0a75738a38772e31014fd63f0b769209928d586499616dcc90700b393156e12eea7e15a835"
+id_str = "unique_identifier"
+ad_hex = "d7d3155616778fb436a1eb2070892205"
-e_hex = "32c670610e73c428785944ab7b582371"
-y_hex = "b4ebebd6177b2eb04149aa463ede7ba2216657e3b4de42f496c0d493b4d734131e63edcde042d951b9bf285622b9d69e9ee170156deeb173725032a952068e68b18f69bd4e52677d48d846055988877ce9e97b962f01e3f425f3101a6a589f020c858b1ee5ae8f79e4c63ce2356d8a9aa703100b3b3588d0aae7d7857b672d1beb25afc90a93045837aca1c39511816d4fc84ad0db35edf9adac810c46965868e79a5eb9509f9d7c315c5439daf561b312c0dd276263464409aef75a65c157277ba0bcef2cb1929995ba6749a8c54187cf2a9cfc9febc40bee8b149973590f9d34ae8c79111792e92b5fcdbd993f6ce8ad1 [...]
+e_hex = "5812ec82060d2a3eab3c967a2d710223"
+y_hex = "b4ebebd6177b2eb04149aa463ede7ba2216657e3b4de42f496c0d493b4d734131e63edcde042d951b9bf285622b9d69e9ee170156deeb173725032a952068e68b18f69bd4e52677d48d846055988877ce9e97b962f01e3f425f3101a6a589f020c858b1ee5ae8f79e4c63ce2356d8a9ae7b4e925357bc7aa2fb609c7cb6578b209f3993868c4e569dafeed4bc0a590453b6159819eed28dc7d2d25011641fa7312076813d85751fd23c75f5182e0c97d2fc8dce58d53a5ec2df3ec2ba08a063f6f9de97a8174c442acbd627dd864df41d1e322267c5674bd5459a3f12afad2b26fe5116a110b243cf8a78ce61d8eed22afd [...]
+
+
+def process_tv(vector):
+ for key, val in vector.items():
+ if key != "TEST":
+ vector[key] = bytes.fromhex(val)
+
+ return vector
class TestProve(unittest.TestCase):
@@ -45,24 +55,27 @@ class TestProve(unittest.TestCase):
seed = bytes.fromhex(seed_hex)
self.rng = core_utils.create_csprng(seed)
- self.p = bytes.fromhex(p_hex)
- self.q = bytes.fromhex(q_hex)
- self.e = bytes.fromhex(e_hex)
- self.y = bytes.fromhex(y_hex)
+ self.p = bytes.fromhex(p_hex)
+ self.q = bytes.fromhex(q_hex)
+ self.e = bytes.fromhex(e_hex)
+ self.y = bytes.fromhex(y_hex)
+ self.id = id_str.encode('utf-8')
+ self.ad = bytes.fromhex(ad_hex)
with open("factoring_zk/prove.json", "r") as f:
self.tv = json.load(f)
for vector in self.tv:
- for key, val in vector.items():
- if key != "TEST":
- vector[key] = bytes.fromhex(val)
+ process_tv(vector)
def test_tv(self):
""" test using test vectors """
for vector in self.tv:
- e, y = factoring_zk.prove(None, vector['P'], vector['Q'], vector['R'])
+ if not vector['AD']:
+ vector['AD'] = None
+
+ e, y = factoring_zk.prove(None, vector['P'], vector['Q'], vector['ID'], ad=vector['AD'], r=vector['R'])
self.assertEqual(e, vector['E'])
self.assertEqual(y, vector['Y'])
@@ -70,7 +83,7 @@ class TestProve(unittest.TestCase):
def test_random(self):
""" test using PRNG """
- e, y = factoring_zk.prove(self.rng, self.p, self.q)
+ e, y = factoring_zk.prove(self.rng, self.p, self.q, self.id, ad=self.ad)
self.assertEqual(e, self.e)
self.assertEqual(y, self.y)
@@ -83,22 +96,23 @@ class TestVerify(unittest.TestCase):
self.tv = json.load(f)
for vector in self.tv:
- for key, val in vector.items():
- if key != "TEST":
- vector[key] = bytes.fromhex(val)
+ process_tv(vector)
def test_tv(self):
""" test using test vectors """
for vector in self.tv:
- ec = factoring_zk.verify(vector['N'], vector['E'], vector['Y'])
+ if not vector['AD']:
+ vector['AD'] = None
+
+ ec = factoring_zk.verify(vector['N'], vector['E'], vector['Y'], vector['ID'], ad=vector['AD'])
self.assertEqual(ec, factoring_zk.OK)
def test_failure(self):
""" Test error codes are propagated correctly """
- ec = factoring_zk.verify(self.tv[0]['Y'], self.tv[0]['E'], self.tv[0]['N'])
+ ec = factoring_zk.verify(self.tv[0]['Y'], self.tv[0]['E'], self.tv[0]['N'], self.tv[0]['ID'])
self.assertEqual(ec, factoring_zk.FAIL)