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,330 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Factory for creating ZK proof instances without dynamic code execution.
|
|
3
|
+
|
|
4
|
+
This module provides a safe alternative to the exec()-based code generation
|
|
5
|
+
in zkp_generator.py, eliminating code injection vulnerabilities.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
import re
|
|
10
|
+
from charm.zkp_compiler.zkparser import ZKParser
|
|
11
|
+
from charm.zkp_compiler.schnorr_proof import SchnorrProof, Proof
|
|
12
|
+
from charm.zkp_compiler.dleq_proof import DLEQProof
|
|
13
|
+
from charm.toolbox.ZKProof import ZKProofBase, ZKParseError, ZKValidationError
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
# Allowed characters in ZK statements
|
|
18
|
+
_VALID_STATEMENT_PATTERN = re.compile(r'^[\w\s\^\=\(\)\*]+$')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def validate_statement(statement):
|
|
22
|
+
"""
|
|
23
|
+
Validate a ZK statement string.
|
|
24
|
+
|
|
25
|
+
Checks for valid characters and prevents injection attacks.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
statement: The ZK statement string to validate
|
|
29
|
+
|
|
30
|
+
Raises:
|
|
31
|
+
ZKValidationError: If statement is invalid or contains suspicious characters
|
|
32
|
+
"""
|
|
33
|
+
if not isinstance(statement, str):
|
|
34
|
+
raise ZKValidationError("Statement must be a string")
|
|
35
|
+
|
|
36
|
+
if not statement.strip():
|
|
37
|
+
raise ZKValidationError("Statement cannot be empty")
|
|
38
|
+
|
|
39
|
+
if not _VALID_STATEMENT_PATTERN.match(statement):
|
|
40
|
+
raise ZKValidationError(
|
|
41
|
+
"Statement contains invalid characters. "
|
|
42
|
+
"Only alphanumeric characters, ^, =, *, (, ), and whitespace are allowed."
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Check for suspicious patterns that might indicate injection attempts
|
|
46
|
+
suspicious_patterns = ['__', 'import', 'exec', 'eval', 'compile', 'open', 'file']
|
|
47
|
+
statement_lower = statement.lower()
|
|
48
|
+
for pattern in suspicious_patterns:
|
|
49
|
+
if pattern in statement_lower:
|
|
50
|
+
raise ZKValidationError(f"Statement contains suspicious pattern: {pattern}")
|
|
51
|
+
|
|
52
|
+
logger.debug("Statement validated: %s", statement)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class SchnorrProofInstance:
|
|
56
|
+
"""
|
|
57
|
+
Wrapper that provides a clean API for Schnorr proofs.
|
|
58
|
+
|
|
59
|
+
Encapsulates the generator, public value, and optionally secret,
|
|
60
|
+
providing prove() and verify() methods.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
def __init__(self, group, g, h, secret_x=None):
|
|
64
|
+
"""
|
|
65
|
+
Initialize a Schnorr proof instance.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
group: The pairing group to use
|
|
69
|
+
g: The generator element
|
|
70
|
+
h: The public element (h = g^x)
|
|
71
|
+
secret_x: The secret exponent (required for proving, optional for verifying)
|
|
72
|
+
"""
|
|
73
|
+
self.group = group
|
|
74
|
+
self.g = g
|
|
75
|
+
self.h = h
|
|
76
|
+
self._secret_x = secret_x
|
|
77
|
+
|
|
78
|
+
def prove(self, interactive=False):
|
|
79
|
+
"""
|
|
80
|
+
Generate a proof (non-interactive by default).
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
interactive: If True, raises an error (use create_interactive_prover instead)
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
Proof object containing commitment, challenge, and response
|
|
87
|
+
|
|
88
|
+
Raises:
|
|
89
|
+
ZKValidationError: If secret is not available or interactive mode requested
|
|
90
|
+
"""
|
|
91
|
+
if self._secret_x is None:
|
|
92
|
+
raise ZKValidationError("Cannot prove without secret")
|
|
93
|
+
if interactive:
|
|
94
|
+
raise ZKValidationError(
|
|
95
|
+
"For interactive proofs, use create_interactive_prover() instead"
|
|
96
|
+
)
|
|
97
|
+
return SchnorrProof.prove_non_interactive(
|
|
98
|
+
self.group, self.g, self.h, self._secret_x
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
def verify(self, proof):
|
|
102
|
+
"""
|
|
103
|
+
Verify a proof.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
proof: Proof object to verify
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
True if proof is valid, False otherwise
|
|
110
|
+
"""
|
|
111
|
+
return SchnorrProof.verify_non_interactive(
|
|
112
|
+
self.group, self.g, self.h, proof
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
def create_interactive_prover(self):
|
|
116
|
+
"""
|
|
117
|
+
Create an interactive prover instance.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
SchnorrProof.Prover instance
|
|
121
|
+
|
|
122
|
+
Raises:
|
|
123
|
+
ZKValidationError: If secret is not available
|
|
124
|
+
"""
|
|
125
|
+
if self._secret_x is None:
|
|
126
|
+
raise ZKValidationError("Cannot create prover without secret")
|
|
127
|
+
return SchnorrProof.Prover(self._secret_x, self.group)
|
|
128
|
+
|
|
129
|
+
def create_interactive_verifier(self):
|
|
130
|
+
"""
|
|
131
|
+
Create an interactive verifier instance.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
SchnorrProof.Verifier instance
|
|
135
|
+
"""
|
|
136
|
+
return SchnorrProof.Verifier(self.group)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class ZKProofFactory:
|
|
140
|
+
"""
|
|
141
|
+
Factory for creating ZK proof instances without dynamic code execution.
|
|
142
|
+
|
|
143
|
+
This factory replaces the insecure exec()-based code generation with
|
|
144
|
+
direct class instantiation, eliminating code injection vulnerabilities.
|
|
145
|
+
|
|
146
|
+
Example:
|
|
147
|
+
>>> from charm.toolbox.pairinggroup import PairingGroup, ZR, G1
|
|
148
|
+
>>> group = PairingGroup('SS512')
|
|
149
|
+
>>> g = group.random(G1)
|
|
150
|
+
>>> x = group.random(ZR)
|
|
151
|
+
>>> h = g ** x
|
|
152
|
+
>>>
|
|
153
|
+
>>> # Create a Schnorr proof instance
|
|
154
|
+
>>> proof_instance = ZKProofFactory.create_schnorr_proof(group, g, h, x)
|
|
155
|
+
>>> proof = proof_instance.prove()
|
|
156
|
+
>>> assert proof_instance.verify(proof)
|
|
157
|
+
"""
|
|
158
|
+
|
|
159
|
+
@staticmethod
|
|
160
|
+
def create_schnorr_proof(group, g, h, secret_x=None):
|
|
161
|
+
"""
|
|
162
|
+
Create a Schnorr proof instance for proving knowledge of discrete log.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
group: The pairing group to use
|
|
166
|
+
g: The generator element
|
|
167
|
+
h: The public element (h = g^x)
|
|
168
|
+
secret_x: The secret exponent (required for proving, optional for verifying)
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
SchnorrProofInstance: An instance that can prove or verify
|
|
172
|
+
"""
|
|
173
|
+
logger.debug("Creating Schnorr proof instance")
|
|
174
|
+
return SchnorrProofInstance(group, g, h, secret_x)
|
|
175
|
+
|
|
176
|
+
@staticmethod
|
|
177
|
+
def create_from_statement(group, statement, public_params, secret_params=None):
|
|
178
|
+
"""
|
|
179
|
+
Create a proof instance from a parsed ZK statement.
|
|
180
|
+
|
|
181
|
+
This method parses the statement and determines the appropriate
|
|
182
|
+
proof type, then creates the corresponding proof instance.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
group: The pairing group to use
|
|
186
|
+
statement: A ZK statement string like "h = g^x"
|
|
187
|
+
public_params: Dict mapping variable names to public values
|
|
188
|
+
secret_params: Dict mapping variable names to secret values (optional)
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
SchnorrProofInstance: An instance of the appropriate proof type
|
|
192
|
+
|
|
193
|
+
Raises:
|
|
194
|
+
ZKParseError: If the statement cannot be parsed
|
|
195
|
+
ZKValidationError: If required parameters are missing
|
|
196
|
+
"""
|
|
197
|
+
# Validate statement first
|
|
198
|
+
validate_statement(statement)
|
|
199
|
+
|
|
200
|
+
# Parse the statement
|
|
201
|
+
try:
|
|
202
|
+
parser = ZKParser()
|
|
203
|
+
stmt_object = parser.parse(statement)
|
|
204
|
+
except Exception as e:
|
|
205
|
+
raise ZKParseError(f"Failed to parse statement: {e}") from e
|
|
206
|
+
|
|
207
|
+
# Extract required variables from the parsed statement
|
|
208
|
+
# For now, we support simple Schnorr-style statements: h = g^x
|
|
209
|
+
# The parser returns a tree structure that we need to analyze
|
|
210
|
+
|
|
211
|
+
if not isinstance(public_params, dict):
|
|
212
|
+
raise ZKValidationError("public_params must be a dictionary")
|
|
213
|
+
|
|
214
|
+
if secret_params is not None and not isinstance(secret_params, dict):
|
|
215
|
+
raise ZKValidationError("secret_params must be a dictionary")
|
|
216
|
+
|
|
217
|
+
# Check for required public parameters
|
|
218
|
+
if 'g' not in public_params:
|
|
219
|
+
raise ZKValidationError("Missing required public parameter: 'g' (generator)")
|
|
220
|
+
if 'h' not in public_params:
|
|
221
|
+
raise ZKValidationError("Missing required public parameter: 'h' (public value)")
|
|
222
|
+
|
|
223
|
+
g = public_params['g']
|
|
224
|
+
h = public_params['h']
|
|
225
|
+
|
|
226
|
+
# Get secret if available
|
|
227
|
+
secret_x = None
|
|
228
|
+
if secret_params and 'x' in secret_params:
|
|
229
|
+
secret_x = secret_params['x']
|
|
230
|
+
|
|
231
|
+
logger.debug("Created proof instance from statement: %s", statement)
|
|
232
|
+
return SchnorrProofInstance(group, g, h, secret_x)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def prove_and_verify_schnorr(group, g, h, x):
|
|
236
|
+
"""
|
|
237
|
+
Proves and immediately verifies a Schnorr proof.
|
|
238
|
+
|
|
239
|
+
Useful for testing and debugging.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
group: The pairing group to use
|
|
243
|
+
g: The generator element
|
|
244
|
+
h: The public element (h = g^x)
|
|
245
|
+
x: The secret exponent
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
tuple: (proof, is_valid) where proof is the Proof object and is_valid is True if verification passed
|
|
249
|
+
|
|
250
|
+
Example::
|
|
251
|
+
|
|
252
|
+
group = PairingGroup('SS512')
|
|
253
|
+
g = group.random(G1)
|
|
254
|
+
x = group.random(ZR)
|
|
255
|
+
h = g ** x
|
|
256
|
+
proof, is_valid = prove_and_verify_schnorr(group, g, h, x)
|
|
257
|
+
assert is_valid
|
|
258
|
+
"""
|
|
259
|
+
proof = SchnorrProof.prove_non_interactive(group, g, h, x)
|
|
260
|
+
is_valid = SchnorrProof.verify_non_interactive(group, g, h, proof)
|
|
261
|
+
return proof, is_valid
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def prove_and_verify_dleq(group, g1, h1, g2, h2, x):
|
|
265
|
+
"""
|
|
266
|
+
Proves and immediately verifies a DLEQ proof.
|
|
267
|
+
|
|
268
|
+
Useful for testing and debugging.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
group: The pairing group to use
|
|
272
|
+
g1: The first generator element
|
|
273
|
+
h1: The first public element (h1 = g1^x)
|
|
274
|
+
g2: The second generator element
|
|
275
|
+
h2: The second public element (h2 = g2^x)
|
|
276
|
+
x: The secret exponent
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
tuple: (proof, is_valid) where proof is the DLEQProofData object and is_valid is True if verification passed
|
|
280
|
+
|
|
281
|
+
Example::
|
|
282
|
+
|
|
283
|
+
group = PairingGroup('SS512')
|
|
284
|
+
g1 = group.random(G1)
|
|
285
|
+
g2 = group.random(G1)
|
|
286
|
+
x = group.random(ZR)
|
|
287
|
+
h1 = g1 ** x
|
|
288
|
+
h2 = g2 ** x
|
|
289
|
+
proof, is_valid = prove_and_verify_dleq(group, g1, h1, g2, h2, x)
|
|
290
|
+
assert is_valid
|
|
291
|
+
"""
|
|
292
|
+
proof = DLEQProof.prove_non_interactive(group, g1, h1, g2, h2, x)
|
|
293
|
+
is_valid = DLEQProof.verify_non_interactive(group, g1, h1, g2, h2, proof)
|
|
294
|
+
return proof, is_valid
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def configure_logging(level: str = 'WARNING') -> None:
|
|
298
|
+
"""
|
|
299
|
+
Configure logging for all ZKP compiler modules.
|
|
300
|
+
|
|
301
|
+
Args:
|
|
302
|
+
level: Logging level ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')
|
|
303
|
+
|
|
304
|
+
Example:
|
|
305
|
+
>>> from charm.zkp_compiler import configure_logging
|
|
306
|
+
>>> configure_logging('DEBUG') # Enable debug output
|
|
307
|
+
"""
|
|
308
|
+
numeric_level = getattr(logging, level.upper(), logging.WARNING)
|
|
309
|
+
|
|
310
|
+
# Configure all ZKP module loggers
|
|
311
|
+
zkp_modules = [
|
|
312
|
+
'charm.zkp_compiler.schnorr_proof',
|
|
313
|
+
'charm.zkp_compiler.dleq_proof',
|
|
314
|
+
'charm.zkp_compiler.representation_proof',
|
|
315
|
+
'charm.zkp_compiler.and_proof',
|
|
316
|
+
'charm.zkp_compiler.or_proof',
|
|
317
|
+
'charm.zkp_compiler.range_proof',
|
|
318
|
+
'charm.zkp_compiler.batch_verify',
|
|
319
|
+
]
|
|
320
|
+
|
|
321
|
+
for module in zkp_modules:
|
|
322
|
+
module_logger = logging.getLogger(module)
|
|
323
|
+
module_logger.setLevel(numeric_level)
|
|
324
|
+
if not module_logger.handlers:
|
|
325
|
+
handler = logging.StreamHandler()
|
|
326
|
+
handler.setFormatter(logging.Formatter(
|
|
327
|
+
'%(name)s - %(levelname)s - %(message)s'
|
|
328
|
+
))
|
|
329
|
+
module_logger.addHandler(handler)
|
|
330
|
+
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Legacy ZKP Generator Module (DEPRECATED)
|
|
3
|
+
========================================
|
|
4
|
+
|
|
5
|
+
.. deprecated:: 0.60
|
|
6
|
+
This module uses insecure dynamic code generation (exec/compile) which
|
|
7
|
+
can lead to code injection vulnerabilities. It will be removed in v0.80.
|
|
8
|
+
|
|
9
|
+
For production use, please migrate to the new secure API:
|
|
10
|
+
|
|
11
|
+
- :class:`charm.zkp_compiler.schnorr_proof.SchnorrProof`
|
|
12
|
+
- :class:`charm.zkp_compiler.dleq_proof.DLEQProof`
|
|
13
|
+
- :class:`charm.zkp_compiler.representation_proof.RepresentationProof`
|
|
14
|
+
- :class:`charm.zkp_compiler.zkp_factory.ZKProofFactory`
|
|
15
|
+
|
|
16
|
+
See the migration guide in doc/zkp_proof_types_design.md
|
|
17
|
+
|
|
18
|
+
Example Migration
|
|
19
|
+
-----------------
|
|
20
|
+
Old (deprecated)::
|
|
21
|
+
|
|
22
|
+
from charm.zkp_compiler.zkp_generator import executeIntZKProof
|
|
23
|
+
result = executeIntZKProof(public, secret, statement, party_info)
|
|
24
|
+
|
|
25
|
+
New (recommended)::
|
|
26
|
+
|
|
27
|
+
from charm.zkp_compiler.schnorr_proof import SchnorrProof
|
|
28
|
+
proof = SchnorrProof.prove_non_interactive(group, g, h, x)
|
|
29
|
+
is_valid = SchnorrProof.verify_non_interactive(group, g, h, proof)
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
import logging
|
|
33
|
+
import warnings
|
|
34
|
+
|
|
35
|
+
from pyparsing import *
|
|
36
|
+
from charm.zkp_compiler.zkparser import *
|
|
37
|
+
from charm.core.engine.protocol import *
|
|
38
|
+
from charm.core.engine.util import *
|
|
39
|
+
#from charm.core.math.pairing import *
|
|
40
|
+
|
|
41
|
+
# Emit deprecation warning when this module is imported
|
|
42
|
+
warnings.warn(
|
|
43
|
+
"The zkp_generator module is deprecated and will be removed in v0.80. "
|
|
44
|
+
"It uses insecure dynamic code execution (exec/compile). "
|
|
45
|
+
"Please migrate to charm.zkp_compiler.schnorr_proof or charm.zkp_compiler.zkp_factory. "
|
|
46
|
+
"See doc/zkp_proof_types_design.md for migration guide.",
|
|
47
|
+
DeprecationWarning,
|
|
48
|
+
stacklevel=2
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Set up logging instead of print statements
|
|
52
|
+
logger = logging.getLogger(__name__)
|
|
53
|
+
|
|
54
|
+
int_default = True
|
|
55
|
+
|
|
56
|
+
def newStateFunction(func_name, args=True):
|
|
57
|
+
if args:
|
|
58
|
+
return """\
|
|
59
|
+
def %s(self, input):\n""" % func_name
|
|
60
|
+
else:
|
|
61
|
+
return """\
|
|
62
|
+
def %s(self):\n""" % func_name
|
|
63
|
+
|
|
64
|
+
def addToCode(lines):
|
|
65
|
+
stmts = " " # 8 spaces
|
|
66
|
+
for stmt in lines:
|
|
67
|
+
if type(stmt) == str:
|
|
68
|
+
# print("Adding =>", stmt)
|
|
69
|
+
stmts += stmt + "; "
|
|
70
|
+
return stmts + "\n"
|
|
71
|
+
|
|
72
|
+
PROVER, VERIFIER = 1,2
|
|
73
|
+
# Handle a Schnorr HVZK proof-of-knowledge of a discrete logarithm
|
|
74
|
+
def KoDLFixedBase(publicDict, secretDict, baseVarKey, expVarKey, statesCode, interactive):
|
|
75
|
+
if type(publicDict) != dict or type(secretDict) != dict:
|
|
76
|
+
print("Type Error!"); return None
|
|
77
|
+
|
|
78
|
+
# First move of protocol: prover picks random integer "k", store k as a secret, output g^k
|
|
79
|
+
stateDef = newStateFunction("prover_state1", False)
|
|
80
|
+
# stateDef += addToCode(["print('State PROVER 1:')"]) # DEBUG
|
|
81
|
+
stateDef += addToCode(["pk = Protocol.get(self, "+str(list(publicDict.keys()))+", dict)"])
|
|
82
|
+
prov_keys, obj_ret, ver_keys2, ver_keys4 = "","", "", []
|
|
83
|
+
rand_elems,dl_elems,store_elems,non_int_def2 = [],[],[],""
|
|
84
|
+
for i in range(len(expVarKey)):
|
|
85
|
+
k = 'k' + str(i)
|
|
86
|
+
prov_keys += expVarKey[i]+","
|
|
87
|
+
rand_elems.append(k + " = self.group.random(ZR)")
|
|
88
|
+
dl_elems.append("val_"+ k + " = pk['" + baseVarKey + "'] ** " + k)
|
|
89
|
+
store_elems.append("Protocol.store(self, ('"+k+"',"+k+"), ('"+expVarKey[i]+"',"+expVarKey[i]+") )")
|
|
90
|
+
obj_ret += "'val_"+k+"':val_"+k+", "
|
|
91
|
+
ver_keys2 += ", ('val_"+k+"', input['val_"+k+"'])"
|
|
92
|
+
four = 'val_'+k
|
|
93
|
+
ver_keys4.append('%s' % four) # used in verify_state4
|
|
94
|
+
non_int_def2 += "input['%s']," % four # used for non-interactive in state def2
|
|
95
|
+
stateDef += addToCode(["("+prov_keys+") = Protocol.get(self, "+str(list(expVarKey))+")"])
|
|
96
|
+
stateDef += addToCode(rand_elems)
|
|
97
|
+
stateDef += addToCode(dl_elems)
|
|
98
|
+
stateDef += addToCode(store_elems)
|
|
99
|
+
stateDef += addToCode(["Protocol.setState(self, 3)","return {"+obj_ret+"'pk':pk }"])
|
|
100
|
+
statesCode += stateDef + "\n"
|
|
101
|
+
|
|
102
|
+
# Second move of protocol: verifier computes random challenge c, outputs c
|
|
103
|
+
stateDef2 = newStateFunction("verifier_state2")
|
|
104
|
+
c = 'c'
|
|
105
|
+
# stateDef2 += addToCode(["print('State VERIFIER 2:')"]) # DEBUG
|
|
106
|
+
if interactive == True:
|
|
107
|
+
stateDef2 += addToCode(["c = self.group.random(ZR)"])
|
|
108
|
+
else:
|
|
109
|
+
stateDef2 += addToCode(["c = self.group.hash(("+str(non_int_def2)+"), ZR)"])
|
|
110
|
+
stateDef2 += addToCode(["Protocol.store(self, ('c',c), ('pk',input['pk'])"+ ver_keys2 +" )",
|
|
111
|
+
"Protocol.setState(self, 4)", "return {'c':c}"])
|
|
112
|
+
statesCode += stateDef2 + "\n"
|
|
113
|
+
|
|
114
|
+
stateDef3 = newStateFunction("prover_state3")
|
|
115
|
+
# stateDef3 += addToCode(["print('State PROVER 3:')"]) # DEBUG
|
|
116
|
+
stateDef3 += addToCode(["c = input['c']"])
|
|
117
|
+
getVals, test_elems = "", ""
|
|
118
|
+
compute, ver_inputs = [],[]
|
|
119
|
+
prf_stmt = []
|
|
120
|
+
for i in range(len(expVarKey)):
|
|
121
|
+
z,k = 'z' + str(i),'k' + str(i)
|
|
122
|
+
getVals += "'"+ expVarKey[i] +"','"+k+"',"
|
|
123
|
+
compute.append(z + " = val['"+expVarKey[i]+"'] * c + val['"+k+"']")
|
|
124
|
+
test_elems += "'"+z+"':"+z+","
|
|
125
|
+
ver_inputs.append(z + " = input['"+z+"']")
|
|
126
|
+
prf_stmt.append("val['pk']['"+baseVarKey+"'] ** "+z) # used in verify_state4
|
|
127
|
+
|
|
128
|
+
stateDef3 += addToCode(["val = Protocol.get(self, ["+getVals+"], dict)"])
|
|
129
|
+
stateDef3 += addToCode(compute)
|
|
130
|
+
stateDef3 += addToCode(["Protocol.setState(self, 5)", "return {"+test_elems+"}"])
|
|
131
|
+
statesCode += stateDef3 + "\n"
|
|
132
|
+
|
|
133
|
+
stateDef4 = newStateFunction("verifier_state4")
|
|
134
|
+
# stateDef4 += addToCode(["print('State VERIFIER 4:')"]) # DEBUG
|
|
135
|
+
stateDef4 += addToCode(ver_inputs)
|
|
136
|
+
pk = ['pk']
|
|
137
|
+
pk.extend(ver_keys4); pk.append('c')
|
|
138
|
+
|
|
139
|
+
stateDef4 += addToCode(["val = Protocol.get(self, "+ str(pk) +", dict)"])
|
|
140
|
+
# need to compute g^z =?= g^k (val_k) * (pubkey)^c
|
|
141
|
+
verify4_stmt = []
|
|
142
|
+
for i in range(len(expVarKey)):
|
|
143
|
+
pub_key = secretDict[ expVarKey[i] ] # get pubkey for secret
|
|
144
|
+
verify4_stmt.append("\n if ("+ prf_stmt[i] + ") == " + "((val['pk']['"+pub_key+"'] ** val['c']) * val['"+ver_keys4[i]+"'] ): result = 'OK'\n else: result = 'FAIL'")
|
|
145
|
+
# verify4_stmt.append("print(val['pk']['g']); result = 'OK'")
|
|
146
|
+
stateDef4 += addToCode(verify4_stmt)
|
|
147
|
+
stateDef4 += addToCode(["Protocol.setState(self, 6)", "Protocol.setErrorCode(self, result)"] )
|
|
148
|
+
stateDef4 += addToCode(["print('Result => ',result); return result"])
|
|
149
|
+
statesCode += stateDef4 + "\n"
|
|
150
|
+
|
|
151
|
+
stateDef5 = newStateFunction("prover_state5")
|
|
152
|
+
# stateDef5 += addToCode(["print('State PROVER 5:')"]) # DEBUG
|
|
153
|
+
stateDef5 += addToCode(["Protocol.setState(self, None)", "Protocol.setErrorCode(self, input); return None"])
|
|
154
|
+
statesCode += stateDef5 + "\n"
|
|
155
|
+
|
|
156
|
+
stateDef6 = newStateFunction("verifier_state6")
|
|
157
|
+
# stateDef6 += addToCode(["print('State VERIFIER 6:')"]) # DEBUG
|
|
158
|
+
stateDef6 += addToCode(["Protocol.setState(self, None)", "return None"])
|
|
159
|
+
statesCode += stateDef6 + "\n"
|
|
160
|
+
|
|
161
|
+
# print("Finishing state 1 =>", statesCode)
|
|
162
|
+
# SECURITY: Removed filesystem write of generated code (tmpGenCode.py)
|
|
163
|
+
# The generated code is logged at DEBUG level for debugging purposes
|
|
164
|
+
logger.debug("Generated ZK proof code:\n%s", statesCode)
|
|
165
|
+
|
|
166
|
+
return statesCode
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
# Return a fixed preamble for an interactive ZK proof protocol.
|
|
170
|
+
def genIZKPreamble():
|
|
171
|
+
return """\
|
|
172
|
+
\nfrom charm.engine.protocol import *
|
|
173
|
+
from charm.engine.util import *
|
|
174
|
+
from socket import *
|
|
175
|
+
from charm.toolbox.pairinggroup import PairingGroup,ZR,G1,G2,GT,pair
|
|
176
|
+
|
|
177
|
+
class %s(Protocol):
|
|
178
|
+
def __init__(self, groupObj, common_input=None):
|
|
179
|
+
Protocol.__init__(self, None)
|
|
180
|
+
PROVER,VERIFIER = %s,%s
|
|
181
|
+
prover_states = { 1:self.prover_state1, 3:self.prover_state3, 5:self.prover_state5 }
|
|
182
|
+
verifier_states = { 2:self.verifier_state2, 4:self.verifier_state4, 6:self.verifier_state6 }
|
|
183
|
+
prover_trans = { 1:3, 3:5 }
|
|
184
|
+
verifier_trans = { 2:4, 4:6 }
|
|
185
|
+
# describe the parties involved and the valid transitions
|
|
186
|
+
Protocol.addPartyType(self, VERIFIER, verifier_states, verifier_trans)
|
|
187
|
+
Protocol.addPartyType(self, PROVER, prover_states, prover_trans, True)
|
|
188
|
+
|
|
189
|
+
# must pass in a group object parameter (allows us to operate in any setting)
|
|
190
|
+
self.group = groupObj
|
|
191
|
+
|
|
192
|
+
if common_input == None: # generate common parameters to P and V
|
|
193
|
+
db = {}
|
|
194
|
+
self.__gen_setup = True
|
|
195
|
+
else: # can be used as a sub-protocol if common_input is specified by caller
|
|
196
|
+
db = common_input
|
|
197
|
+
self.__gen_setup = False
|
|
198
|
+
self.PROVER, self.VERIFIER = PROVER, VERIFIER
|
|
199
|
+
Protocol.setSubclassVars(self, self.group, db)\n"""
|
|
200
|
+
|
|
201
|
+
# public contains a dictionary of the public group elements (keys appropriately labeled)
|
|
202
|
+
# secret contains a dictionary of the secret elements (keys must be appropriately labeled)
|
|
203
|
+
# statement is the statement for which we would like to prove via ZK and thus code
|
|
204
|
+
# we need to generate to prove the statement.
|
|
205
|
+
def parseAndGenerateCode(public, secretDict, statement, party_ID, interactive):
|
|
206
|
+
# parse the statement such that we know the baseVar, expName (secret)
|
|
207
|
+
output = genIZKPreamble()
|
|
208
|
+
output = output % ('ZKProof', PROVER, VERIFIER)
|
|
209
|
+
|
|
210
|
+
parser = ZKParser()
|
|
211
|
+
stmt_object = parser.parse(statement)
|
|
212
|
+
pk, sk = [], []
|
|
213
|
+
gen, sec = [], {}
|
|
214
|
+
extract(stmt_object, pk, sk, sec, gen)
|
|
215
|
+
# Get the preamble (including class definition and __init__ routine
|
|
216
|
+
# print("Public params...", pk)
|
|
217
|
+
# print("Secret keys...", sk)
|
|
218
|
+
# print("Secret key =>", sec)
|
|
219
|
+
|
|
220
|
+
baseVar = gen.pop() # NOTE: we only support one generator for now (i.e. 'g'), for more advanced
|
|
221
|
+
expSecret = sk # e.g. ['x', 'y',...]
|
|
222
|
+
secret = sec # mapping of secret to public key (e.g. {'x':'h', 'y':'j'}
|
|
223
|
+
|
|
224
|
+
# print("Input public =>", public)
|
|
225
|
+
# print("Input private =>", secret)
|
|
226
|
+
|
|
227
|
+
final_src = KoDLFixedBase(public, secret, baseVar, expSecret, output, interactive)
|
|
228
|
+
return final_src
|
|
229
|
+
|
|
230
|
+
def extract(node, pk, sk, sk_pk_map, gen):
|
|
231
|
+
if node.type == node.EXP:
|
|
232
|
+
# print("public =>", node.getLeft(), "in pk?")
|
|
233
|
+
# print("secret =>", node.getRight(), "in sk?")
|
|
234
|
+
if not node.getLeft() in pk:
|
|
235
|
+
pk.append(node.getLeft())
|
|
236
|
+
if not node.getLeft() in gen:
|
|
237
|
+
gen.append(node.getLeft()) # ONLY SUPPORT 1 generator (may need to re-arch generator to support multiple gens)
|
|
238
|
+
sk.append(node.getRight())
|
|
239
|
+
|
|
240
|
+
elif node.type == node.EQ:
|
|
241
|
+
# print("public =>", node.getLeft(), "in pk?")
|
|
242
|
+
extract(node.getRight(), pk, sk, sk_pk_map, gen)
|
|
243
|
+
sec_key = sk.pop()
|
|
244
|
+
sk_pk_map[sec_key] = node.getLeft()
|
|
245
|
+
sk.append(sec_key)
|
|
246
|
+
if not node.getLeft() in pk:
|
|
247
|
+
pk.append(node.getLeft())
|
|
248
|
+
elif node.type == node.AND:
|
|
249
|
+
extract(node.getLeft(), pk, sk, sk_pk_map, gen)
|
|
250
|
+
extract(node.getRight(), pk, sk, sk_pk_map, gen)
|
|
251
|
+
else:
|
|
252
|
+
return None
|
|
253
|
+
return None
|
|
254
|
+
|
|
255
|
+
# does tyep checking on the parsed statement object to determine
|
|
256
|
+
# 1) all the public keys (in stmt) appear in pk
|
|
257
|
+
# 2) all the secret keys (in stmt) appear in sk
|
|
258
|
+
def dict_check(node, pk, sk):
|
|
259
|
+
if node.type == node.EXP:
|
|
260
|
+
if not node.getLeft() in pk: return False
|
|
261
|
+
if not node.getRight() in sk: return False
|
|
262
|
+
elif node.type == node.EQ:
|
|
263
|
+
if not node.getLeft() in pk: return False
|
|
264
|
+
return dict_check(node.getRight(), pk, sk)
|
|
265
|
+
elif node.type == node.AND:
|
|
266
|
+
if dict_check(node.getLeft(), pk, sk) == False: return False
|
|
267
|
+
if dict_check(node.getRight(), pk, sk) == False: return False
|
|
268
|
+
elif node.type == node.OR:
|
|
269
|
+
if dict_check(node.getLeft(), pk, sk) or dict_check(node.getLeft(), pk, sk): return True
|
|
270
|
+
else: return False
|
|
271
|
+
return True
|
|
272
|
+
|
|
273
|
+
def write_out(name, prefix, value):
|
|
274
|
+
"""Log debug output instead of writing to filesystem.
|
|
275
|
+
|
|
276
|
+
SECURITY: This function previously wrote to the filesystem, which could
|
|
277
|
+
allow attackers to write arbitrary content. Now it logs to the debug
|
|
278
|
+
logger instead.
|
|
279
|
+
"""
|
|
280
|
+
logger.debug("%s: %s => %s", name, prefix, value)
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
# Generate an interactive ZK proof from a statement and variables. The output
|
|
284
|
+
# of this function is a subclass of Protocol. To execute the proof, first
|
|
285
|
+
# set it up using the Protocol API and run Execute().
|
|
286
|
+
def executeIntZKProof(public, secret, statement, party_info, interactive=int_default):
|
|
287
|
+
"""Execute an interactive ZK proof.
|
|
288
|
+
|
|
289
|
+
.. deprecated:: 0.60
|
|
290
|
+
This function uses insecure dynamic code execution (exec/compile).
|
|
291
|
+
Use :class:`charm.zkp_compiler.zkp_factory.ZKProofFactory` instead.
|
|
292
|
+
|
|
293
|
+
Migration example::
|
|
294
|
+
|
|
295
|
+
# Old (deprecated):
|
|
296
|
+
# result = executeIntZKProof(public, secret, statement, party_info)
|
|
297
|
+
|
|
298
|
+
# New (recommended):
|
|
299
|
+
from charm.zkp_compiler.zkp_factory import ZKProofFactory
|
|
300
|
+
proof_instance = ZKProofFactory.create_schnorr_proof(group, g, h, x)
|
|
301
|
+
proof = proof_instance.prove()
|
|
302
|
+
is_valid = proof_instance.verify(proof)
|
|
303
|
+
"""
|
|
304
|
+
warnings.warn(
|
|
305
|
+
"executeIntZKProof() uses insecure dynamic code execution. "
|
|
306
|
+
"Use charm.zkp_compiler.zkp_factory.ZKProofFactory instead.",
|
|
307
|
+
DeprecationWarning,
|
|
308
|
+
stacklevel=2
|
|
309
|
+
)
|
|
310
|
+
logger.info("Executing Interactive ZK proof...")
|
|
311
|
+
# verify that party_info contains wellformed dictionary
|
|
312
|
+
party_keys = set(['party', 'setting', 'socket'])
|
|
313
|
+
if not party_keys.issubset(set(party_info.keys())):
|
|
314
|
+
missing_keys = party_keys.difference_update(set(party_info_keys()))
|
|
315
|
+
logger.error("Required key/values missing: '%s'", missing_keys)
|
|
316
|
+
return None
|
|
317
|
+
|
|
318
|
+
p_name, p_socket, groupObj = party_info['party'], party_info['socket'], party_info['setting']
|
|
319
|
+
if p_name.upper() == 'PROVER': partyID = PROVER
|
|
320
|
+
elif p_name.upper() == 'VERIFIER': partyID = VERIFIER
|
|
321
|
+
else: logger.error("Unrecognized party!"); return None
|
|
322
|
+
|
|
323
|
+
# Parse through the statement and insert code into each state of the prover and/or verifier
|
|
324
|
+
ZKClass = parseAndGenerateCode(public, secret, statement, partyID, interactive)
|
|
325
|
+
dummy_class = '<string>'
|
|
326
|
+
# SECURITY WARNING: compile() and exec() are used here for legacy compatibility.
|
|
327
|
+
# This is a known security vulnerability. Use ZKProofFactory for new code.
|
|
328
|
+
proof_code = compile(ZKClass, dummy_class, 'exec')
|
|
329
|
+
logger.debug("Proof code object => %s", proof_code)
|
|
330
|
+
# return proof_code
|
|
331
|
+
ns = {}
|
|
332
|
+
exec(proof_code, globals(), ns) # nosec B102 - legacy code, deprecated
|
|
333
|
+
ZKProof = ns['ZKProof']
|
|
334
|
+
|
|
335
|
+
prov_db = None
|
|
336
|
+
if(partyID == PROVER):
|
|
337
|
+
prov_db = {}; prov_db.update(public); prov_db.update(secret)
|
|
338
|
+
zkp = ZKProof(groupObj, prov_db)
|
|
339
|
+
zkp.setup( {'name':p_name.lower(), 'type':partyID, 'socket':p_socket})
|
|
340
|
+
# is there a way to check type of socket?
|
|
341
|
+
zkp.execute(partyID)
|
|
342
|
+
return zkp.result
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def executeNonIntZKProof(public, secret, statement, party_info):
|
|
346
|
+
"""Execute a non-interactive ZK proof.
|
|
347
|
+
|
|
348
|
+
.. deprecated:: 0.60
|
|
349
|
+
This function uses insecure dynamic code execution (exec/compile).
|
|
350
|
+
Use :class:`charm.zkp_compiler.schnorr_proof.SchnorrProof` instead.
|
|
351
|
+
|
|
352
|
+
Migration example::
|
|
353
|
+
|
|
354
|
+
# Old (deprecated):
|
|
355
|
+
# result = executeNonIntZKProof(public, secret, statement, party_info)
|
|
356
|
+
|
|
357
|
+
# New (recommended):
|
|
358
|
+
from charm.zkp_compiler.schnorr_proof import SchnorrProof
|
|
359
|
+
proof = SchnorrProof.prove_non_interactive(group, g, h, x)
|
|
360
|
+
is_valid = SchnorrProof.verify_non_interactive(group, g, h, proof)
|
|
361
|
+
"""
|
|
362
|
+
warnings.warn(
|
|
363
|
+
"executeNonIntZKProof() uses insecure dynamic code execution. "
|
|
364
|
+
"Use charm.zkp_compiler.schnorr_proof.SchnorrProof instead.",
|
|
365
|
+
DeprecationWarning,
|
|
366
|
+
stacklevel=2
|
|
367
|
+
)
|
|
368
|
+
logger.info("Executing Non-interactive ZK proof...")
|
|
369
|
+
return executeIntZKProof(public, secret, statement, party_info, interactive=False)
|
|
370
|
+
|