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 <[email protected]> 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)
