charm-crypto-framework 0.61.1__cp313-cp313-macosx_10_13_universal2.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- charm/__init__.py +5 -0
- charm/adapters/__init__.py +0 -0
- charm/adapters/abenc_adapt_hybrid.py +90 -0
- charm/adapters/dabenc_adapt_hybrid.py +145 -0
- charm/adapters/ibenc_adapt_hybrid.py +72 -0
- charm/adapters/ibenc_adapt_identityhash.py +80 -0
- charm/adapters/kpabenc_adapt_hybrid.py +91 -0
- charm/adapters/pkenc_adapt_bchk05.py +121 -0
- charm/adapters/pkenc_adapt_chk04.py +91 -0
- charm/adapters/pkenc_adapt_hybrid.py +98 -0
- charm/adapters/pksig_adapt_naor01.py +89 -0
- charm/config.py +7 -0
- charm/core/__init__.py +0 -0
- charm/core/benchmark/benchmark_util.c +353 -0
- charm/core/benchmark/benchmark_util.h +61 -0
- charm/core/benchmark/benchmarkmodule.c +476 -0
- charm/core/benchmark/benchmarkmodule.h +162 -0
- charm/core/benchmark.cpython-313-darwin.so +0 -0
- charm/core/crypto/AES/AES.c +1464 -0
- charm/core/crypto/AES.cpython-313-darwin.so +0 -0
- charm/core/crypto/DES/DES.c +113 -0
- charm/core/crypto/DES.cpython-313-darwin.so +0 -0
- charm/core/crypto/DES3/DES3.c +26 -0
- charm/core/crypto/DES3.cpython-313-darwin.so +0 -0
- charm/core/crypto/__init__.py +0 -0
- charm/core/crypto/cryptobase/XOR.c +80 -0
- charm/core/crypto/cryptobase/_counter.c +496 -0
- charm/core/crypto/cryptobase/_counter.h +54 -0
- charm/core/crypto/cryptobase/block_template.c +900 -0
- charm/core/crypto/cryptobase/block_template.h +69 -0
- charm/core/crypto/cryptobase/cryptobasemodule.c +220 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt.h +90 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_argchk.h +44 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_cfg.h +186 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_cipher.h +941 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_custom.h +556 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_des.c +1912 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_hash.h +407 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_mac.h +496 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_macros.h +435 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_math.h +534 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_misc.h +103 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_pk.h +653 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_pkcs.h +90 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_prng.h +199 -0
- charm/core/crypto/cryptobase/stream_template.c +271 -0
- charm/core/crypto/cryptobase/strxor.c +229 -0
- charm/core/crypto/cryptobase.cpython-313-darwin.so +0 -0
- charm/core/engine/__init__.py +5 -0
- charm/core/engine/protocol.py +293 -0
- charm/core/engine/util.py +174 -0
- charm/core/math/__init__.py +0 -0
- charm/core/math/elliptic_curve/ecmodule.c +1986 -0
- charm/core/math/elliptic_curve/ecmodule.h +230 -0
- charm/core/math/elliptic_curve.cpython-313-darwin.so +0 -0
- charm/core/math/elliptic_curve.pyi +63 -0
- charm/core/math/integer/integermodule.c +2539 -0
- charm/core/math/integer/integermodule.h +145 -0
- charm/core/math/integer.cpython-313-darwin.so +0 -0
- charm/core/math/integer.pyi +76 -0
- charm/core/math/pairing/miracl/miracl_config.h +37 -0
- charm/core/math/pairing/miracl/miracl_interface.h +118 -0
- charm/core/math/pairing/miracl/miracl_interface2.h +126 -0
- charm/core/math/pairing/miracl/pairingmodule2.c +2094 -0
- charm/core/math/pairing/miracl/pairingmodule2.h +307 -0
- charm/core/math/pairing/pairingmodule.c +2230 -0
- charm/core/math/pairing/pairingmodule.h +241 -0
- charm/core/math/pairing/relic/pairingmodule3.c +1853 -0
- charm/core/math/pairing/relic/pairingmodule3.h +233 -0
- charm/core/math/pairing/relic/relic_interface.c +1337 -0
- charm/core/math/pairing/relic/relic_interface.h +217 -0
- charm/core/math/pairing/relic/test_relic.c +171 -0
- charm/core/math/pairing.cpython-313-darwin.so +0 -0
- charm/core/math/pairing.pyi +69 -0
- charm/core/utilities/base64.c +248 -0
- charm/core/utilities/base64.h +15 -0
- charm/schemes/__init__.py +0 -0
- charm/schemes/abenc/__init__.py +0 -0
- charm/schemes/abenc/abenc_accountability_jyjxgd20.py +647 -0
- charm/schemes/abenc/abenc_bsw07.py +146 -0
- charm/schemes/abenc/abenc_ca_cpabe_ar17.py +684 -0
- charm/schemes/abenc/abenc_dacmacs_yj14.py +298 -0
- charm/schemes/abenc/abenc_lsw08.py +159 -0
- charm/schemes/abenc/abenc_maabe_rw15.py +236 -0
- charm/schemes/abenc/abenc_maabe_yj14.py +297 -0
- charm/schemes/abenc/abenc_tbpre_lww14.py +309 -0
- charm/schemes/abenc/abenc_unmcpabe_yahk14.py +223 -0
- charm/schemes/abenc/abenc_waters09.py +144 -0
- charm/schemes/abenc/abenc_yct14.py +208 -0
- charm/schemes/abenc/abenc_yllc15.py +178 -0
- charm/schemes/abenc/ac17.py +248 -0
- charm/schemes/abenc/bsw07.py +141 -0
- charm/schemes/abenc/cgw15.py +277 -0
- charm/schemes/abenc/dabe_aw11.py +204 -0
- charm/schemes/abenc/dfa_fe12.py +144 -0
- charm/schemes/abenc/pk_hve08.py +179 -0
- charm/schemes/abenc/waters11.py +143 -0
- charm/schemes/aggrsign_MuSig.py +150 -0
- charm/schemes/aggrsign_bls.py +267 -0
- charm/schemes/blindsig_ps16.py +654 -0
- charm/schemes/chamhash_adm05.py +113 -0
- charm/schemes/chamhash_rsa_hw09.py +100 -0
- charm/schemes/commit/__init__.py +0 -0
- charm/schemes/commit/commit_gs08.py +77 -0
- charm/schemes/commit/commit_pedersen92.py +53 -0
- charm/schemes/encap_bchk05.py +62 -0
- charm/schemes/grpsig/__init__.py +0 -0
- charm/schemes/grpsig/groupsig_bgls04.py +114 -0
- charm/schemes/grpsig/groupsig_bgls04_var.py +115 -0
- charm/schemes/hibenc/__init__.py +0 -0
- charm/schemes/hibenc/hibenc_bb04.py +105 -0
- charm/schemes/hibenc/hibenc_lew11.py +193 -0
- charm/schemes/ibenc/__init__.py +0 -0
- charm/schemes/ibenc/clpkc_rp03.py +119 -0
- charm/schemes/ibenc/ibenc_CW13_z.py +168 -0
- charm/schemes/ibenc/ibenc_bb03.py +94 -0
- charm/schemes/ibenc/ibenc_bf01.py +121 -0
- charm/schemes/ibenc/ibenc_ckrs09.py +120 -0
- charm/schemes/ibenc/ibenc_cllww12_z.py +172 -0
- charm/schemes/ibenc/ibenc_lsw08.py +120 -0
- charm/schemes/ibenc/ibenc_sw05.py +238 -0
- charm/schemes/ibenc/ibenc_waters05.py +144 -0
- charm/schemes/ibenc/ibenc_waters05_z.py +164 -0
- charm/schemes/ibenc/ibenc_waters09.py +107 -0
- charm/schemes/ibenc/ibenc_waters09_z.py +147 -0
- charm/schemes/joye_scheme.py +106 -0
- charm/schemes/lem_scheme.py +207 -0
- charm/schemes/pk_fre_ccv11.py +107 -0
- charm/schemes/pk_vrf.py +127 -0
- charm/schemes/pkenc/__init__.py +0 -0
- charm/schemes/pkenc/pkenc_cs98.py +108 -0
- charm/schemes/pkenc/pkenc_elgamal85.py +122 -0
- charm/schemes/pkenc/pkenc_gm82.py +98 -0
- charm/schemes/pkenc/pkenc_paillier99.py +118 -0
- charm/schemes/pkenc/pkenc_rabin.py +254 -0
- charm/schemes/pkenc/pkenc_rsa.py +186 -0
- charm/schemes/pksig/__init__.py +0 -0
- charm/schemes/pksig/pksig_CW13_z.py +135 -0
- charm/schemes/pksig/pksig_bls04.py +87 -0
- charm/schemes/pksig/pksig_boyen.py +156 -0
- charm/schemes/pksig/pksig_chch.py +97 -0
- charm/schemes/pksig/pksig_chp.py +70 -0
- charm/schemes/pksig/pksig_cl03.py +150 -0
- charm/schemes/pksig/pksig_cl04.py +87 -0
- charm/schemes/pksig/pksig_cllww12_z.py +142 -0
- charm/schemes/pksig/pksig_cyh.py +132 -0
- charm/schemes/pksig/pksig_dsa.py +76 -0
- charm/schemes/pksig/pksig_ecdsa.py +71 -0
- charm/schemes/pksig/pksig_hess.py +104 -0
- charm/schemes/pksig/pksig_hw.py +110 -0
- charm/schemes/pksig/pksig_lamport.py +63 -0
- charm/schemes/pksig/pksig_ps01.py +135 -0
- charm/schemes/pksig/pksig_ps02.py +124 -0
- charm/schemes/pksig/pksig_ps03.py +119 -0
- charm/schemes/pksig/pksig_rsa_hw09.py +206 -0
- charm/schemes/pksig/pksig_schnorr91.py +77 -0
- charm/schemes/pksig/pksig_waters.py +115 -0
- charm/schemes/pksig/pksig_waters05.py +121 -0
- charm/schemes/pksig/pksig_waters09.py +121 -0
- charm/schemes/pre_mg07.py +150 -0
- charm/schemes/prenc/pre_afgh06.py +126 -0
- charm/schemes/prenc/pre_bbs98.py +123 -0
- charm/schemes/prenc/pre_nal16.py +216 -0
- charm/schemes/protocol_a01.py +272 -0
- charm/schemes/protocol_ao00.py +215 -0
- charm/schemes/protocol_cns07.py +274 -0
- charm/schemes/protocol_schnorr91.py +125 -0
- charm/schemes/sigma1.py +64 -0
- charm/schemes/sigma2.py +129 -0
- charm/schemes/sigma3.py +126 -0
- charm/schemes/threshold/__init__.py +59 -0
- charm/schemes/threshold/dkls23_dkg.py +556 -0
- charm/schemes/threshold/dkls23_presign.py +1089 -0
- charm/schemes/threshold/dkls23_sign.py +761 -0
- charm/schemes/threshold/xrpl_wallet.py +967 -0
- charm/test/__init__.py +0 -0
- charm/test/adapters/__init__.py +0 -0
- charm/test/adapters/abenc_adapt_hybrid_test.py +29 -0
- charm/test/adapters/dabenc_adapt_hybrid_test.py +56 -0
- charm/test/adapters/ibenc_adapt_hybrid_test.py +36 -0
- charm/test/adapters/ibenc_adapt_identityhash_test.py +32 -0
- charm/test/adapters/kpabenc_adapt_hybrid_test.py +30 -0
- charm/test/benchmark/abenc_yllc15_bench.py +92 -0
- charm/test/benchmark/benchmark_test.py +148 -0
- charm/test/benchmark_threshold.py +260 -0
- charm/test/conftest.py +38 -0
- charm/test/fuzz/__init__.py +1 -0
- charm/test/fuzz/conftest.py +5 -0
- charm/test/fuzz/fuzz_policy_parser.py +76 -0
- charm/test/fuzz/fuzz_serialization.py +83 -0
- charm/test/schemes/__init__.py +0 -0
- charm/test/schemes/abenc/__init__.py +0 -0
- charm/test/schemes/abenc/abenc_bsw07_test.py +39 -0
- charm/test/schemes/abenc/abenc_dacmacs_yj14_test.py +16 -0
- charm/test/schemes/abenc/abenc_lsw08_test.py +33 -0
- charm/test/schemes/abenc/abenc_maabe_yj14_test.py +16 -0
- charm/test/schemes/abenc/abenc_tbpre_lww14_test.py +16 -0
- charm/test/schemes/abenc/abenc_waters09_test.py +38 -0
- charm/test/schemes/abenc/abenc_yllc15_test.py +74 -0
- charm/test/schemes/chamhash_adm05_test.py +31 -0
- charm/test/schemes/chamhash_rsa_hw09_test.py +29 -0
- charm/test/schemes/commit/__init__.py +0 -0
- charm/test/schemes/commit/commit_gs08_test.py +24 -0
- charm/test/schemes/commit/commit_pedersen92_test.py +26 -0
- charm/test/schemes/dabe_aw11_test.py +45 -0
- charm/test/schemes/encap_bchk05_test.py +21 -0
- charm/test/schemes/grpsig/__init__.py +0 -0
- charm/test/schemes/grpsig/groupsig_bgls04_test.py +35 -0
- charm/test/schemes/grpsig/groupsig_bgls04_var_test.py +39 -0
- charm/test/schemes/hibenc/__init__.py +0 -0
- charm/test/schemes/hibenc/hibenc_bb04_test.py +28 -0
- charm/test/schemes/ibenc/__init__.py +0 -0
- charm/test/schemes/ibenc/ibenc_bb03_test.py +26 -0
- charm/test/schemes/ibenc/ibenc_bf01_test.py +24 -0
- charm/test/schemes/ibenc/ibenc_ckrs09_test.py +25 -0
- charm/test/schemes/ibenc/ibenc_lsw08_test.py +31 -0
- charm/test/schemes/ibenc/ibenc_sw05_test.py +32 -0
- charm/test/schemes/ibenc/ibenc_waters05_test.py +31 -0
- charm/test/schemes/ibenc/ibenc_waters09_test.py +27 -0
- charm/test/schemes/pk_vrf_test.py +29 -0
- charm/test/schemes/pkenc/__init__.py +0 -0
- charm/test/schemes/pkenc_test.py +255 -0
- charm/test/schemes/pksig/__init__.py +0 -0
- charm/test/schemes/pksig_test.py +376 -0
- charm/test/schemes/rsa_alg_test.py +340 -0
- charm/test/schemes/threshold_test.py +1792 -0
- charm/test/serialize/__init__.py +0 -0
- charm/test/serialize/serialize_test.py +40 -0
- charm/test/toolbox/__init__.py +0 -0
- charm/test/toolbox/conversion_test.py +30 -0
- charm/test/toolbox/ecgroup_test.py +53 -0
- charm/test/toolbox/integer_arithmetic_test.py +441 -0
- charm/test/toolbox/paddingschemes_test.py +238 -0
- charm/test/toolbox/policy_parser_stress_test.py +969 -0
- charm/test/toolbox/secretshare_test.py +28 -0
- charm/test/toolbox/symcrypto_test.py +108 -0
- charm/test/toolbox/test_policy_expression.py +16 -0
- charm/test/vectors/__init__.py +1 -0
- charm/test/vectors/test_bls_vectors.py +289 -0
- charm/test/vectors/test_pedersen_vectors.py +315 -0
- charm/test/vectors/test_schnorr_vectors.py +368 -0
- charm/test/zkp_compiler/__init__.py +9 -0
- charm/test/zkp_compiler/benchmark_zkp.py +258 -0
- charm/test/zkp_compiler/test_and_proof.py +240 -0
- charm/test/zkp_compiler/test_batch_verify.py +248 -0
- charm/test/zkp_compiler/test_dleq_proof.py +264 -0
- charm/test/zkp_compiler/test_or_proof.py +231 -0
- charm/test/zkp_compiler/test_proof_serialization.py +121 -0
- charm/test/zkp_compiler/test_range_proof.py +241 -0
- charm/test/zkp_compiler/test_representation_proof.py +325 -0
- charm/test/zkp_compiler/test_schnorr_proof.py +221 -0
- charm/test/zkp_compiler/test_thread_safety.py +169 -0
- charm/test/zkp_compiler/test_zkp_parser.py +139 -0
- charm/toolbox/ABEnc.py +26 -0
- charm/toolbox/ABEncMultiAuth.py +66 -0
- charm/toolbox/ABEnumeric.py +800 -0
- charm/toolbox/Commit.py +24 -0
- charm/toolbox/DFA.py +89 -0
- charm/toolbox/FSA.py +1254 -0
- charm/toolbox/Hash.py +39 -0
- charm/toolbox/IBEnc.py +62 -0
- charm/toolbox/IBSig.py +64 -0
- charm/toolbox/PKEnc.py +66 -0
- charm/toolbox/PKSig.py +56 -0
- charm/toolbox/PREnc.py +32 -0
- charm/toolbox/ZKProof.py +289 -0
- charm/toolbox/__init__.py +0 -0
- charm/toolbox/bitstring.py +49 -0
- charm/toolbox/broadcast.py +220 -0
- charm/toolbox/conversion.py +100 -0
- charm/toolbox/eccurve.py +149 -0
- charm/toolbox/ecgroup.py +143 -0
- charm/toolbox/enum.py +60 -0
- charm/toolbox/hash_module.py +91 -0
- charm/toolbox/integergroup.py +323 -0
- charm/toolbox/iterate.py +22 -0
- charm/toolbox/matrixops.py +76 -0
- charm/toolbox/mpc_utils.py +296 -0
- charm/toolbox/msp.py +175 -0
- charm/toolbox/mta.py +985 -0
- charm/toolbox/node.py +120 -0
- charm/toolbox/ot/__init__.py +22 -0
- charm/toolbox/ot/base_ot.py +374 -0
- charm/toolbox/ot/dpf.py +642 -0
- charm/toolbox/ot/mpfss.py +228 -0
- charm/toolbox/ot/ot_extension.py +589 -0
- charm/toolbox/ot/silent_ot.py +378 -0
- charm/toolbox/paddingschemes.py +423 -0
- charm/toolbox/paddingschemes_test.py +238 -0
- charm/toolbox/pairingcurves.py +85 -0
- charm/toolbox/pairinggroup.py +186 -0
- charm/toolbox/policy_expression_spec.py +70 -0
- charm/toolbox/policytree.py +189 -0
- charm/toolbox/reCompiler.py +346 -0
- charm/toolbox/redundancyschemes.py +65 -0
- charm/toolbox/schemebase.py +188 -0
- charm/toolbox/secretshare.py +104 -0
- charm/toolbox/secretutil.py +174 -0
- charm/toolbox/securerandom.py +73 -0
- charm/toolbox/sigmaprotocol.py +46 -0
- charm/toolbox/specialprimes.py +45 -0
- charm/toolbox/symcrypto.py +279 -0
- charm/toolbox/threshold_sharing.py +553 -0
- charm/toolbox/xmlserialize.py +94 -0
- charm/toolbox/zknode.py +105 -0
- charm/zkp_compiler/__init__.py +89 -0
- charm/zkp_compiler/and_proof.py +460 -0
- charm/zkp_compiler/batch_verify.py +324 -0
- charm/zkp_compiler/dleq_proof.py +423 -0
- charm/zkp_compiler/or_proof.py +305 -0
- charm/zkp_compiler/range_proof.py +417 -0
- charm/zkp_compiler/representation_proof.py +466 -0
- charm/zkp_compiler/schnorr_proof.py +273 -0
- charm/zkp_compiler/thread_safe.py +150 -0
- charm/zkp_compiler/zk_demo.py +489 -0
- charm/zkp_compiler/zkp_factory.py +330 -0
- charm/zkp_compiler/zkp_generator.py +370 -0
- charm/zkp_compiler/zkparser.py +269 -0
- charm_crypto_framework-0.61.1.dist-info/METADATA +337 -0
- charm_crypto_framework-0.61.1.dist-info/RECORD +323 -0
- charm_crypto_framework-0.61.1.dist-info/WHEEL +5 -0
- charm_crypto_framework-0.61.1.dist-info/licenses/LICENSE.txt +165 -0
- charm_crypto_framework-0.61.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unit tests for Representation ZK proof implementation.
|
|
3
|
+
|
|
4
|
+
Tests cover:
|
|
5
|
+
- Interactive proof protocol with multiple generators
|
|
6
|
+
- Non-interactive (Fiat-Shamir) proof
|
|
7
|
+
- Serialization/deserialization
|
|
8
|
+
- Different pairing groups
|
|
9
|
+
- Edge cases and error handling
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import unittest
|
|
13
|
+
from charm.toolbox.pairinggroup import PairingGroup, ZR, G1
|
|
14
|
+
from charm.zkp_compiler.representation_proof import RepresentationProof, RepresentationProofData
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TestRepresentationProofInteractive(unittest.TestCase):
|
|
18
|
+
"""Tests for interactive Representation protocol."""
|
|
19
|
+
|
|
20
|
+
def setUp(self):
|
|
21
|
+
"""Set up test fixtures."""
|
|
22
|
+
self.group = PairingGroup('BN254')
|
|
23
|
+
|
|
24
|
+
def test_prove_and_verify_interactive_two_generators(self):
|
|
25
|
+
"""Test complete interactive proof cycle with two generators (Pedersen commitment style)."""
|
|
26
|
+
g1 = self.group.random(G1)
|
|
27
|
+
g2 = self.group.random(G1)
|
|
28
|
+
x1 = self.group.random(ZR)
|
|
29
|
+
x2 = self.group.random(ZR)
|
|
30
|
+
h = (g1 ** x1) * (g2 ** x2)
|
|
31
|
+
|
|
32
|
+
# Create prover and verifier
|
|
33
|
+
prover = RepresentationProof.Prover([x1, x2], self.group)
|
|
34
|
+
verifier = RepresentationProof.Verifier(self.group)
|
|
35
|
+
|
|
36
|
+
# Step 1: Prover creates commitment
|
|
37
|
+
commitment = prover.create_commitment([g1, g2])
|
|
38
|
+
self.assertIsNotNone(commitment)
|
|
39
|
+
|
|
40
|
+
# Step 2: Verifier creates challenge
|
|
41
|
+
challenge = verifier.create_challenge()
|
|
42
|
+
self.assertIsNotNone(challenge)
|
|
43
|
+
|
|
44
|
+
# Step 3: Prover creates response
|
|
45
|
+
responses = prover.create_response(challenge)
|
|
46
|
+
self.assertIsNotNone(responses)
|
|
47
|
+
self.assertEqual(len(responses), 2)
|
|
48
|
+
|
|
49
|
+
# Step 4: Verifier verifies
|
|
50
|
+
result = verifier.verify([g1, g2], h, commitment, responses)
|
|
51
|
+
self.assertTrue(result)
|
|
52
|
+
|
|
53
|
+
def test_prove_and_verify_interactive_three_generators(self):
|
|
54
|
+
"""Test complete interactive proof cycle with three generators."""
|
|
55
|
+
g1 = self.group.random(G1)
|
|
56
|
+
g2 = self.group.random(G1)
|
|
57
|
+
g3 = self.group.random(G1)
|
|
58
|
+
x1 = self.group.random(ZR)
|
|
59
|
+
x2 = self.group.random(ZR)
|
|
60
|
+
x3 = self.group.random(ZR)
|
|
61
|
+
h = (g1 ** x1) * (g2 ** x2) * (g3 ** x3)
|
|
62
|
+
|
|
63
|
+
prover = RepresentationProof.Prover([x1, x2, x3], self.group)
|
|
64
|
+
verifier = RepresentationProof.Verifier(self.group)
|
|
65
|
+
|
|
66
|
+
commitment = prover.create_commitment([g1, g2, g3])
|
|
67
|
+
challenge = verifier.create_challenge()
|
|
68
|
+
responses = prover.create_response(challenge)
|
|
69
|
+
|
|
70
|
+
self.assertEqual(len(responses), 3)
|
|
71
|
+
result = verifier.verify([g1, g2, g3], h, commitment, responses)
|
|
72
|
+
self.assertTrue(result)
|
|
73
|
+
|
|
74
|
+
def test_invalid_proof_fails_interactive(self):
|
|
75
|
+
"""Test that wrong witnesses fail verification."""
|
|
76
|
+
g1 = self.group.random(G1)
|
|
77
|
+
g2 = self.group.random(G1)
|
|
78
|
+
x1 = self.group.random(ZR)
|
|
79
|
+
x2 = self.group.random(ZR)
|
|
80
|
+
h = (g1 ** x1) * (g2 ** x2)
|
|
81
|
+
|
|
82
|
+
# Use wrong witnesses
|
|
83
|
+
wrong_x1 = self.group.random(ZR)
|
|
84
|
+
wrong_x2 = self.group.random(ZR)
|
|
85
|
+
prover = RepresentationProof.Prover([wrong_x1, wrong_x2], self.group)
|
|
86
|
+
verifier = RepresentationProof.Verifier(self.group)
|
|
87
|
+
|
|
88
|
+
commitment = prover.create_commitment([g1, g2])
|
|
89
|
+
challenge = verifier.create_challenge()
|
|
90
|
+
responses = prover.create_response(challenge)
|
|
91
|
+
|
|
92
|
+
# Should fail because wrong witnesses
|
|
93
|
+
result = verifier.verify([g1, g2], h, commitment, responses)
|
|
94
|
+
self.assertFalse(result)
|
|
95
|
+
|
|
96
|
+
def test_prover_commitment_before_response(self):
|
|
97
|
+
"""Test that prover must create commitment before response."""
|
|
98
|
+
x1 = self.group.random(ZR)
|
|
99
|
+
x2 = self.group.random(ZR)
|
|
100
|
+
prover = RepresentationProof.Prover([x1, x2], self.group)
|
|
101
|
+
|
|
102
|
+
# Try to create response without commitment
|
|
103
|
+
with self.assertRaises(ValueError):
|
|
104
|
+
prover.create_response(self.group.random(ZR))
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class TestRepresentationProofNonInteractive(unittest.TestCase):
|
|
108
|
+
"""Tests for non-interactive (Fiat-Shamir) Representation proof."""
|
|
109
|
+
|
|
110
|
+
def setUp(self):
|
|
111
|
+
"""Set up test fixtures."""
|
|
112
|
+
self.group = PairingGroup('BN254')
|
|
113
|
+
|
|
114
|
+
def test_non_interactive_proof_valid_two_generators(self):
|
|
115
|
+
"""Test Fiat-Shamir transformed proof with two generators."""
|
|
116
|
+
g1 = self.group.random(G1)
|
|
117
|
+
g2 = self.group.random(G1)
|
|
118
|
+
x1 = self.group.random(ZR)
|
|
119
|
+
x2 = self.group.random(ZR)
|
|
120
|
+
h = (g1 ** x1) * (g2 ** x2)
|
|
121
|
+
|
|
122
|
+
proof = RepresentationProof.prove_non_interactive(
|
|
123
|
+
self.group, [g1, g2], h, [x1, x2]
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
self.assertIsNotNone(proof)
|
|
127
|
+
self.assertIsNotNone(proof.commitment)
|
|
128
|
+
self.assertIsNotNone(proof.challenge)
|
|
129
|
+
self.assertIsNotNone(proof.responses)
|
|
130
|
+
self.assertEqual(len(proof.responses), 2)
|
|
131
|
+
|
|
132
|
+
result = RepresentationProof.verify_non_interactive(
|
|
133
|
+
self.group, [g1, g2], h, proof
|
|
134
|
+
)
|
|
135
|
+
self.assertTrue(result)
|
|
136
|
+
|
|
137
|
+
def test_non_interactive_proof_valid_three_generators(self):
|
|
138
|
+
"""Test Fiat-Shamir transformed proof with three generators."""
|
|
139
|
+
g1 = self.group.random(G1)
|
|
140
|
+
g2 = self.group.random(G1)
|
|
141
|
+
g3 = self.group.random(G1)
|
|
142
|
+
x1 = self.group.random(ZR)
|
|
143
|
+
x2 = self.group.random(ZR)
|
|
144
|
+
x3 = self.group.random(ZR)
|
|
145
|
+
h = (g1 ** x1) * (g2 ** x2) * (g3 ** x3)
|
|
146
|
+
|
|
147
|
+
proof = RepresentationProof.prove_non_interactive(
|
|
148
|
+
self.group, [g1, g2, g3], h, [x1, x2, x3]
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
self.assertEqual(len(proof.responses), 3)
|
|
152
|
+
result = RepresentationProof.verify_non_interactive(
|
|
153
|
+
self.group, [g1, g2, g3], h, proof
|
|
154
|
+
)
|
|
155
|
+
self.assertTrue(result)
|
|
156
|
+
|
|
157
|
+
def test_non_interactive_wrong_witness_fails(self):
|
|
158
|
+
"""Test that wrong witness fails non-interactive verification."""
|
|
159
|
+
g1 = self.group.random(G1)
|
|
160
|
+
g2 = self.group.random(G1)
|
|
161
|
+
x1 = self.group.random(ZR)
|
|
162
|
+
x2 = self.group.random(ZR)
|
|
163
|
+
h = (g1 ** x1) * (g2 ** x2)
|
|
164
|
+
|
|
165
|
+
# Create proof with wrong witnesses
|
|
166
|
+
wrong_x1 = self.group.random(ZR)
|
|
167
|
+
wrong_x2 = self.group.random(ZR)
|
|
168
|
+
proof = RepresentationProof.prove_non_interactive(
|
|
169
|
+
self.group, [g1, g2], h, [wrong_x1, wrong_x2]
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
result = RepresentationProof.verify_non_interactive(
|
|
173
|
+
self.group, [g1, g2], h, proof
|
|
174
|
+
)
|
|
175
|
+
self.assertFalse(result)
|
|
176
|
+
|
|
177
|
+
def test_non_interactive_tampered_proof_fails(self):
|
|
178
|
+
"""Test that tampered proof fails verification."""
|
|
179
|
+
g1 = self.group.random(G1)
|
|
180
|
+
g2 = self.group.random(G1)
|
|
181
|
+
x1 = self.group.random(ZR)
|
|
182
|
+
x2 = self.group.random(ZR)
|
|
183
|
+
h = (g1 ** x1) * (g2 ** x2)
|
|
184
|
+
|
|
185
|
+
proof = RepresentationProof.prove_non_interactive(
|
|
186
|
+
self.group, [g1, g2], h, [x1, x2]
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# Tamper with the first response
|
|
190
|
+
tampered_responses = list(proof.responses)
|
|
191
|
+
tampered_responses[0] = tampered_responses[0] + self.group.random(ZR)
|
|
192
|
+
tampered = RepresentationProofData(
|
|
193
|
+
commitment=proof.commitment,
|
|
194
|
+
challenge=proof.challenge,
|
|
195
|
+
responses=tampered_responses,
|
|
196
|
+
proof_type=proof.proof_type
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
result = RepresentationProof.verify_non_interactive(
|
|
200
|
+
self.group, [g1, g2], h, tampered
|
|
201
|
+
)
|
|
202
|
+
self.assertFalse(result)
|
|
203
|
+
|
|
204
|
+
def test_proof_deterministic_verification(self):
|
|
205
|
+
"""Test that same proof verifies consistently."""
|
|
206
|
+
g1 = self.group.random(G1)
|
|
207
|
+
g2 = self.group.random(G1)
|
|
208
|
+
x1 = self.group.random(ZR)
|
|
209
|
+
x2 = self.group.random(ZR)
|
|
210
|
+
h = (g1 ** x1) * (g2 ** x2)
|
|
211
|
+
|
|
212
|
+
proof = RepresentationProof.prove_non_interactive(
|
|
213
|
+
self.group, [g1, g2], h, [x1, x2]
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
# Verify multiple times
|
|
217
|
+
for _ in range(5):
|
|
218
|
+
result = RepresentationProof.verify_non_interactive(
|
|
219
|
+
self.group, [g1, g2], h, proof
|
|
220
|
+
)
|
|
221
|
+
self.assertTrue(result)
|
|
222
|
+
|
|
223
|
+
def test_single_generator_equivalent_to_schnorr(self):
|
|
224
|
+
"""Test that with 1 generator, representation proof works like Schnorr."""
|
|
225
|
+
g = self.group.random(G1)
|
|
226
|
+
x = self.group.random(ZR)
|
|
227
|
+
h = g ** x
|
|
228
|
+
|
|
229
|
+
# Create representation proof with single generator
|
|
230
|
+
proof = RepresentationProof.prove_non_interactive(
|
|
231
|
+
self.group, [g], h, [x]
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
self.assertIsNotNone(proof)
|
|
235
|
+
self.assertEqual(len(proof.responses), 1)
|
|
236
|
+
|
|
237
|
+
result = RepresentationProof.verify_non_interactive(
|
|
238
|
+
self.group, [g], h, proof
|
|
239
|
+
)
|
|
240
|
+
self.assertTrue(result)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class TestRepresentationProofSerialization(unittest.TestCase):
|
|
244
|
+
"""Tests for proof serialization and deserialization."""
|
|
245
|
+
|
|
246
|
+
def setUp(self):
|
|
247
|
+
"""Set up test fixtures."""
|
|
248
|
+
self.group = PairingGroup('BN254')
|
|
249
|
+
|
|
250
|
+
def test_serialization_roundtrip(self):
|
|
251
|
+
"""Test that proof can be serialized and deserialized."""
|
|
252
|
+
g1 = self.group.random(G1)
|
|
253
|
+
g2 = self.group.random(G1)
|
|
254
|
+
x1 = self.group.random(ZR)
|
|
255
|
+
x2 = self.group.random(ZR)
|
|
256
|
+
h = (g1 ** x1) * (g2 ** x2)
|
|
257
|
+
|
|
258
|
+
proof = RepresentationProof.prove_non_interactive(
|
|
259
|
+
self.group, [g1, g2], h, [x1, x2]
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
# Serialize and deserialize
|
|
263
|
+
serialized = RepresentationProof.serialize_proof(proof, self.group)
|
|
264
|
+
self.assertIsInstance(serialized, bytes)
|
|
265
|
+
|
|
266
|
+
deserialized = RepresentationProof.deserialize_proof(serialized, self.group)
|
|
267
|
+
self.assertEqual(deserialized.commitment, proof.commitment)
|
|
268
|
+
self.assertEqual(deserialized.challenge, proof.challenge)
|
|
269
|
+
self.assertEqual(len(deserialized.responses), len(proof.responses))
|
|
270
|
+
for i in range(len(proof.responses)):
|
|
271
|
+
self.assertEqual(deserialized.responses[i], proof.responses[i])
|
|
272
|
+
|
|
273
|
+
def test_serialized_proof_verifies(self):
|
|
274
|
+
"""Test that deserialized proof still verifies."""
|
|
275
|
+
g1 = self.group.random(G1)
|
|
276
|
+
g2 = self.group.random(G1)
|
|
277
|
+
x1 = self.group.random(ZR)
|
|
278
|
+
x2 = self.group.random(ZR)
|
|
279
|
+
h = (g1 ** x1) * (g2 ** x2)
|
|
280
|
+
|
|
281
|
+
proof = RepresentationProof.prove_non_interactive(
|
|
282
|
+
self.group, [g1, g2], h, [x1, x2]
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
# Serialize, deserialize, then verify
|
|
286
|
+
serialized = RepresentationProof.serialize_proof(proof, self.group)
|
|
287
|
+
deserialized = RepresentationProof.deserialize_proof(serialized, self.group)
|
|
288
|
+
|
|
289
|
+
result = RepresentationProof.verify_non_interactive(
|
|
290
|
+
self.group, [g1, g2], h, deserialized
|
|
291
|
+
)
|
|
292
|
+
self.assertTrue(result)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
class TestRepresentationProofWithDifferentGroups(unittest.TestCase):
|
|
296
|
+
"""Test Representation proofs with different pairing groups."""
|
|
297
|
+
|
|
298
|
+
def test_with_bn254_group(self):
|
|
299
|
+
"""Test with BN254 pairing group."""
|
|
300
|
+
self._test_with_group('BN254')
|
|
301
|
+
|
|
302
|
+
def test_with_mnt224_group(self):
|
|
303
|
+
"""Test with MNT224 pairing group."""
|
|
304
|
+
self._test_with_group('MNT224')
|
|
305
|
+
|
|
306
|
+
def _test_with_group(self, curve_name):
|
|
307
|
+
"""Helper to test with a specific group."""
|
|
308
|
+
group = PairingGroup(curve_name)
|
|
309
|
+
g1 = group.random(G1)
|
|
310
|
+
g2 = group.random(G1)
|
|
311
|
+
x1 = group.random(ZR)
|
|
312
|
+
x2 = group.random(ZR)
|
|
313
|
+
h = (g1 ** x1) * (g2 ** x2)
|
|
314
|
+
|
|
315
|
+
proof = RepresentationProof.prove_non_interactive(
|
|
316
|
+
group, [g1, g2], h, [x1, x2]
|
|
317
|
+
)
|
|
318
|
+
result = RepresentationProof.verify_non_interactive(
|
|
319
|
+
group, [g1, g2], h, proof
|
|
320
|
+
)
|
|
321
|
+
self.assertTrue(result)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
if __name__ == "__main__":
|
|
325
|
+
unittest.main()
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unit tests for Schnorr ZK proof implementation.
|
|
3
|
+
|
|
4
|
+
Tests cover:
|
|
5
|
+
- Interactive proof protocol
|
|
6
|
+
- Non-interactive (Fiat-Shamir) proof
|
|
7
|
+
- Different pairing groups
|
|
8
|
+
- Edge cases and error handling
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import unittest
|
|
12
|
+
from charm.toolbox.pairinggroup import PairingGroup, ZR, G1
|
|
13
|
+
from charm.zkp_compiler.schnorr_proof import SchnorrProof, Proof
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TestSchnorrProofInteractive(unittest.TestCase):
|
|
17
|
+
"""Tests for interactive Schnorr protocol."""
|
|
18
|
+
|
|
19
|
+
def setUp(self):
|
|
20
|
+
"""Set up test fixtures."""
|
|
21
|
+
self.group = PairingGroup('BN254')
|
|
22
|
+
self.g = self.group.random(G1)
|
|
23
|
+
self.x = self.group.random(ZR)
|
|
24
|
+
self.h = self.g ** self.x
|
|
25
|
+
|
|
26
|
+
def test_prove_and_verify_interactive(self):
|
|
27
|
+
"""Test complete interactive proof cycle."""
|
|
28
|
+
# Create prover and verifier
|
|
29
|
+
prover = SchnorrProof.Prover(self.x, self.group)
|
|
30
|
+
verifier = SchnorrProof.Verifier(self.group)
|
|
31
|
+
|
|
32
|
+
# Step 1: Prover creates commitment
|
|
33
|
+
commitment = prover.create_commitment(self.g)
|
|
34
|
+
self.assertIsNotNone(commitment)
|
|
35
|
+
|
|
36
|
+
# Step 2: Verifier creates challenge
|
|
37
|
+
challenge = verifier.create_challenge()
|
|
38
|
+
self.assertIsNotNone(challenge)
|
|
39
|
+
|
|
40
|
+
# Step 3: Prover creates response
|
|
41
|
+
response = prover.create_response(challenge)
|
|
42
|
+
self.assertIsNotNone(response)
|
|
43
|
+
|
|
44
|
+
# Step 4: Verifier verifies
|
|
45
|
+
result = verifier.verify(self.g, self.h, commitment, response)
|
|
46
|
+
self.assertTrue(result)
|
|
47
|
+
|
|
48
|
+
def test_invalid_proof_fails_interactive(self):
|
|
49
|
+
"""Test that wrong secret fails verification."""
|
|
50
|
+
wrong_x = self.group.random(ZR)
|
|
51
|
+
prover = SchnorrProof.Prover(wrong_x, self.group)
|
|
52
|
+
verifier = SchnorrProof.Verifier(self.group)
|
|
53
|
+
|
|
54
|
+
commitment = prover.create_commitment(self.g)
|
|
55
|
+
challenge = verifier.create_challenge()
|
|
56
|
+
response = prover.create_response(challenge)
|
|
57
|
+
|
|
58
|
+
# Should fail because wrong secret
|
|
59
|
+
result = verifier.verify(self.g, self.h, commitment, response)
|
|
60
|
+
self.assertFalse(result)
|
|
61
|
+
|
|
62
|
+
def test_prover_commitment_before_response(self):
|
|
63
|
+
"""Test that prover must create commitment before response."""
|
|
64
|
+
prover = SchnorrProof.Prover(self.x, self.group)
|
|
65
|
+
|
|
66
|
+
# Try to create response without commitment
|
|
67
|
+
with self.assertRaises(Exception):
|
|
68
|
+
prover.create_response(self.group.random(ZR))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class TestSchnorrProofNonInteractive(unittest.TestCase):
|
|
72
|
+
"""Tests for non-interactive (Fiat-Shamir) Schnorr proof."""
|
|
73
|
+
|
|
74
|
+
def setUp(self):
|
|
75
|
+
"""Set up test fixtures."""
|
|
76
|
+
self.group = PairingGroup('BN254')
|
|
77
|
+
self.g = self.group.random(G1)
|
|
78
|
+
self.x = self.group.random(ZR)
|
|
79
|
+
self.h = self.g ** self.x
|
|
80
|
+
|
|
81
|
+
def test_non_interactive_proof_valid(self):
|
|
82
|
+
"""Test Fiat-Shamir transformed proof."""
|
|
83
|
+
proof = SchnorrProof.prove_non_interactive(
|
|
84
|
+
self.group, self.g, self.h, self.x
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
self.assertIsNotNone(proof)
|
|
88
|
+
self.assertIsNotNone(proof.commitment)
|
|
89
|
+
self.assertIsNotNone(proof.challenge)
|
|
90
|
+
self.assertIsNotNone(proof.response)
|
|
91
|
+
|
|
92
|
+
result = SchnorrProof.verify_non_interactive(
|
|
93
|
+
self.group, self.g, self.h, proof
|
|
94
|
+
)
|
|
95
|
+
self.assertTrue(result)
|
|
96
|
+
|
|
97
|
+
def test_non_interactive_wrong_secret_fails(self):
|
|
98
|
+
"""Test that wrong secret fails non-interactive verification."""
|
|
99
|
+
wrong_x = self.group.random(ZR)
|
|
100
|
+
proof = SchnorrProof.prove_non_interactive(
|
|
101
|
+
self.group, self.g, self.h, wrong_x
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
result = SchnorrProof.verify_non_interactive(
|
|
105
|
+
self.group, self.g, self.h, proof
|
|
106
|
+
)
|
|
107
|
+
self.assertFalse(result)
|
|
108
|
+
|
|
109
|
+
def test_non_interactive_tampered_proof_fails(self):
|
|
110
|
+
"""Test that tampered proof fails verification."""
|
|
111
|
+
proof = SchnorrProof.prove_non_interactive(
|
|
112
|
+
self.group, self.g, self.h, self.x
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Tamper with the response
|
|
116
|
+
tampered = Proof(
|
|
117
|
+
commitment=proof.commitment,
|
|
118
|
+
challenge=proof.challenge,
|
|
119
|
+
response=proof.response + self.group.random(ZR),
|
|
120
|
+
proof_type=proof.proof_type
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
result = SchnorrProof.verify_non_interactive(
|
|
124
|
+
self.group, self.g, self.h, tampered
|
|
125
|
+
)
|
|
126
|
+
self.assertFalse(result)
|
|
127
|
+
|
|
128
|
+
def test_proof_deterministic_verification(self):
|
|
129
|
+
"""Test that same proof verifies consistently."""
|
|
130
|
+
proof = SchnorrProof.prove_non_interactive(
|
|
131
|
+
self.group, self.g, self.h, self.x
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Verify multiple times
|
|
135
|
+
for _ in range(5):
|
|
136
|
+
result = SchnorrProof.verify_non_interactive(
|
|
137
|
+
self.group, self.g, self.h, proof
|
|
138
|
+
)
|
|
139
|
+
self.assertTrue(result)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class TestSchnorrProofWithDifferentGroups(unittest.TestCase):
|
|
143
|
+
"""Test Schnorr proofs with different pairing groups."""
|
|
144
|
+
|
|
145
|
+
def test_with_bn254_group(self):
|
|
146
|
+
"""Test with BN254 pairing group."""
|
|
147
|
+
self._test_with_group('BN254')
|
|
148
|
+
|
|
149
|
+
def test_with_mnt224_group(self):
|
|
150
|
+
"""Test with MNT224 pairing group."""
|
|
151
|
+
self._test_with_group('MNT224')
|
|
152
|
+
|
|
153
|
+
def _test_with_group(self, curve_name):
|
|
154
|
+
"""Helper to test with a specific group."""
|
|
155
|
+
group = PairingGroup(curve_name)
|
|
156
|
+
g = group.random(G1)
|
|
157
|
+
x = group.random(ZR)
|
|
158
|
+
h = g ** x
|
|
159
|
+
|
|
160
|
+
proof = SchnorrProof.prove_non_interactive(group, g, h, x)
|
|
161
|
+
result = SchnorrProof.verify_non_interactive(group, g, h, proof)
|
|
162
|
+
self.assertTrue(result)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class TestSchnorrProofSecurity(unittest.TestCase):
|
|
166
|
+
"""Security-focused tests for Schnorr proofs."""
|
|
167
|
+
|
|
168
|
+
def setUp(self):
|
|
169
|
+
"""Set up test fixtures."""
|
|
170
|
+
self.group = PairingGroup('BN254')
|
|
171
|
+
self.g = self.group.random(G1)
|
|
172
|
+
self.x = self.group.random(ZR)
|
|
173
|
+
self.h = self.g ** self.x
|
|
174
|
+
|
|
175
|
+
def test_invalid_proof_structure_rejected(self):
|
|
176
|
+
"""Test that proofs with missing attributes are rejected."""
|
|
177
|
+
# Create a fake proof object without required attributes
|
|
178
|
+
class FakeProof:
|
|
179
|
+
pass
|
|
180
|
+
|
|
181
|
+
fake_proof = FakeProof()
|
|
182
|
+
result = SchnorrProof.verify_non_interactive(self.group, self.g, self.h, fake_proof)
|
|
183
|
+
self.assertFalse(result)
|
|
184
|
+
|
|
185
|
+
def test_identity_commitment_rejected(self):
|
|
186
|
+
"""Test that proofs with identity element commitment are rejected."""
|
|
187
|
+
# Create a valid proof first
|
|
188
|
+
proof = SchnorrProof.prove_non_interactive(self.group, self.g, self.h, self.x)
|
|
189
|
+
|
|
190
|
+
# Replace commitment with identity element
|
|
191
|
+
identity = self.group.init(G1, 1)
|
|
192
|
+
tampered_proof = Proof(
|
|
193
|
+
commitment=identity,
|
|
194
|
+
challenge=proof.challenge,
|
|
195
|
+
response=proof.response,
|
|
196
|
+
proof_type='schnorr'
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
result = SchnorrProof.verify_non_interactive(self.group, self.g, self.h, tampered_proof)
|
|
200
|
+
self.assertFalse(result)
|
|
201
|
+
|
|
202
|
+
def test_challenge_mismatch_rejected(self):
|
|
203
|
+
"""Test that proofs with wrong challenge are rejected."""
|
|
204
|
+
proof = SchnorrProof.prove_non_interactive(self.group, self.g, self.h, self.x)
|
|
205
|
+
|
|
206
|
+
# Tamper with the challenge
|
|
207
|
+
wrong_challenge = self.group.random(ZR)
|
|
208
|
+
tampered_proof = Proof(
|
|
209
|
+
commitment=proof.commitment,
|
|
210
|
+
challenge=wrong_challenge,
|
|
211
|
+
response=proof.response,
|
|
212
|
+
proof_type='schnorr'
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
result = SchnorrProof.verify_non_interactive(self.group, self.g, self.h, tampered_proof)
|
|
216
|
+
self.assertFalse(result)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
if __name__ == "__main__":
|
|
220
|
+
unittest.main()
|
|
221
|
+
|