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,466 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Knowledge of Representation Zero-Knowledge Proof implementation.
|
|
3
|
+
|
|
4
|
+
This module provides a direct implementation of the Knowledge of Representation
|
|
5
|
+
ZKP protocol for proving knowledge of multiple discrete logarithms simultaneously.
|
|
6
|
+
|
|
7
|
+
=== What This Proves ===
|
|
8
|
+
The Representation proof proves: "I know (x1, x2, ..., xn) such that
|
|
9
|
+
h = g1^x1 * g2^x2 * ... * gn^xn" without revealing any of the xi values.
|
|
10
|
+
|
|
11
|
+
This is a generalization of Schnorr's proof to multiple bases. While Schnorr
|
|
12
|
+
proves knowledge of a single discrete log, representation proofs prove knowledge
|
|
13
|
+
of multiple discrete logs whose weighted combination (in the exponent) produces
|
|
14
|
+
a given public value.
|
|
15
|
+
|
|
16
|
+
=== Mathematical Basis ===
|
|
17
|
+
Given:
|
|
18
|
+
- Public generators: g1, g2, ..., gn (in group G)
|
|
19
|
+
- Public value: h = g1^x1 * g2^x2 * ... * gn^xn
|
|
20
|
+
- Secret witnesses: x1, x2, ..., xn (in Zr)
|
|
21
|
+
|
|
22
|
+
The protocol works because:
|
|
23
|
+
1. Prover commits to random values r1, r2, ..., rn via u = g1^r1 * g2^r2 * ... * gn^rn
|
|
24
|
+
2. Given challenge c, prover computes zi = ri + c*xi for each i
|
|
25
|
+
3. Verification checks: g1^z1 * g2^z2 * ... * gn^zn == u * h^c
|
|
26
|
+
|
|
27
|
+
This works because:
|
|
28
|
+
g1^z1 * g2^z2 * ... * gn^zn
|
|
29
|
+
= g1^(r1+c*x1) * g2^(r2+c*x2) * ... * gn^(rn+c*xn)
|
|
30
|
+
= (g1^r1 * g2^r2 * ... * gn^rn) * (g1^x1 * g2^x2 * ... * gn^xn)^c
|
|
31
|
+
= u * h^c
|
|
32
|
+
|
|
33
|
+
=== Security Properties ===
|
|
34
|
+
- Zero-Knowledge: The verifier learns nothing about xi beyond validity of the proof
|
|
35
|
+
- Soundness: A prover who doesn't know the witnesses cannot produce a valid proof
|
|
36
|
+
(except with negligible probability)
|
|
37
|
+
- Completeness: An honest prover with valid witnesses always convinces the verifier
|
|
38
|
+
|
|
39
|
+
=== Use Cases ===
|
|
40
|
+
1. Pedersen Commitments: Prove knowledge of (v, r) for C = g^v * h^r (n=2)
|
|
41
|
+
2. Anonymous Credentials: Prove possession of multiple hidden attributes
|
|
42
|
+
3. Multi-Attribute Proofs: Prove knowledge of several values in a single proof
|
|
43
|
+
4. Range Proofs: Often built on top of representation proofs
|
|
44
|
+
5. Voting Schemes: Prove ballot is well-formed without revealing vote
|
|
45
|
+
|
|
46
|
+
Usage Examples:
|
|
47
|
+
# Interactive mode (see class docstrings for full examples)
|
|
48
|
+
prover = RepresentationProof.Prover(witnesses, group)
|
|
49
|
+
verifier = RepresentationProof.Verifier(group)
|
|
50
|
+
commitment = prover.create_commitment(generators)
|
|
51
|
+
challenge = verifier.create_challenge()
|
|
52
|
+
responses = prover.create_response(challenge)
|
|
53
|
+
valid = verifier.verify(generators, h, commitment, responses)
|
|
54
|
+
|
|
55
|
+
# Non-interactive mode
|
|
56
|
+
proof = RepresentationProof.prove_non_interactive(group, generators, h, witnesses)
|
|
57
|
+
valid = RepresentationProof.verify_non_interactive(group, generators, h, proof)
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
from typing import List, Any
|
|
61
|
+
|
|
62
|
+
from charm.toolbox.pairinggroup import PairingGroup, ZR, G1
|
|
63
|
+
from charm.core.engine.util import objectToBytes, bytesToObject
|
|
64
|
+
import logging
|
|
65
|
+
|
|
66
|
+
logger = logging.getLogger(__name__)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class RepresentationProofData:
|
|
70
|
+
"""Container for Representation proof data.
|
|
71
|
+
|
|
72
|
+
Holds the commitment, challenge, and list of responses for a
|
|
73
|
+
knowledge of representation proof.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
def __init__(self, commitment: Any, challenge: Any, responses: List[Any], proof_type: str = 'representation') -> None:
|
|
77
|
+
"""
|
|
78
|
+
Initialize a representation proof.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
commitment: The prover's commitment (u = g1^r1 * g2^r2 * ... * gn^rn)
|
|
82
|
+
challenge: The challenge value (c)
|
|
83
|
+
responses: List of response values [z1, z2, ..., zn] where zi = ri + c*xi
|
|
84
|
+
proof_type: Type identifier for the proof
|
|
85
|
+
"""
|
|
86
|
+
self.commitment = commitment
|
|
87
|
+
self.challenge = challenge
|
|
88
|
+
self.responses = responses
|
|
89
|
+
self.proof_type = proof_type
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class RepresentationProof:
|
|
93
|
+
"""
|
|
94
|
+
Knowledge of Representation Zero-Knowledge Proof.
|
|
95
|
+
|
|
96
|
+
Proves knowledge of (x1, x2, ..., xn) such that h = g1^x1 * g2^x2 * ... * gn^xn
|
|
97
|
+
without revealing any xi.
|
|
98
|
+
|
|
99
|
+
This is a generalization of Schnorr's proof that enables proving knowledge
|
|
100
|
+
of multiple discrete logarithms simultaneously. It forms the basis for
|
|
101
|
+
many practical cryptographic protocols including Pedersen commitment
|
|
102
|
+
openings and anonymous credential systems.
|
|
103
|
+
|
|
104
|
+
Supports both interactive and non-interactive (Fiat-Shamir) modes.
|
|
105
|
+
|
|
106
|
+
Example (Non-Interactive):
|
|
107
|
+
>>> group = PairingGroup('BN254')
|
|
108
|
+
>>> # Setup: two generators and two witnesses
|
|
109
|
+
>>> g1, g2 = group.random(G1), group.random(G1)
|
|
110
|
+
>>> x1, x2 = group.random(ZR), group.random(ZR)
|
|
111
|
+
>>> h = (g1 ** x1) * (g2 ** x2) # Public value
|
|
112
|
+
>>>
|
|
113
|
+
>>> # Prove knowledge of x1, x2
|
|
114
|
+
>>> proof = RepresentationProof.prove_non_interactive(
|
|
115
|
+
... group, [g1, g2], h, [x1, x2])
|
|
116
|
+
>>>
|
|
117
|
+
>>> # Verify the proof
|
|
118
|
+
>>> valid = RepresentationProof.verify_non_interactive(
|
|
119
|
+
... group, [g1, g2], h, proof)
|
|
120
|
+
>>> assert valid
|
|
121
|
+
|
|
122
|
+
Example (Interactive):
|
|
123
|
+
>>> group = PairingGroup('BN254')
|
|
124
|
+
>>> g1, g2 = group.random(G1), group.random(G1)
|
|
125
|
+
>>> x1, x2 = group.random(ZR), group.random(ZR)
|
|
126
|
+
>>> h = (g1 ** x1) * (g2 ** x2)
|
|
127
|
+
>>>
|
|
128
|
+
>>> # Interactive protocol
|
|
129
|
+
>>> prover = RepresentationProof.Prover([x1, x2], group)
|
|
130
|
+
>>> verifier = RepresentationProof.Verifier(group)
|
|
131
|
+
>>>
|
|
132
|
+
>>> commitment = prover.create_commitment([g1, g2])
|
|
133
|
+
>>> challenge = verifier.create_challenge()
|
|
134
|
+
>>> responses = prover.create_response(challenge)
|
|
135
|
+
>>> valid = verifier.verify([g1, g2], h, commitment, responses)
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
class Prover:
|
|
139
|
+
"""Prover for Representation protocol.
|
|
140
|
+
|
|
141
|
+
The prover knows the secret witnesses (x1, x2, ..., xn) and wants
|
|
142
|
+
to prove this knowledge without revealing the actual values.
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
def __init__(self, witnesses, group):
|
|
146
|
+
"""
|
|
147
|
+
Initialize prover with secret witnesses.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
witnesses: List of secret discrete log values [x1, x2, ..., xn]
|
|
151
|
+
group: The pairing group object
|
|
152
|
+
"""
|
|
153
|
+
self._r_values = None # Random commitment values (private)
|
|
154
|
+
self.group = group
|
|
155
|
+
self._witnesses = witnesses # Secrets (private)
|
|
156
|
+
self._n = len(witnesses) # Number of witnesses
|
|
157
|
+
|
|
158
|
+
def create_commitment(self, generators):
|
|
159
|
+
"""
|
|
160
|
+
Create prover's commitment: u = g1^r1 * g2^r2 * ... * gn^rn.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
generators: List of generator elements [g1, g2, ..., gn]
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
The commitment u = prod(gi^ri)
|
|
167
|
+
|
|
168
|
+
Raises:
|
|
169
|
+
ValueError: If number of generators doesn't match number of witnesses
|
|
170
|
+
"""
|
|
171
|
+
if len(generators) != self._n:
|
|
172
|
+
raise ValueError(
|
|
173
|
+
f"Number of generators ({len(generators)}) must match "
|
|
174
|
+
f"number of witnesses ({self._n})"
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
# Generate random values r1, r2, ..., rn
|
|
178
|
+
self._r_values = [self.group.random(ZR) for _ in range(self._n)]
|
|
179
|
+
|
|
180
|
+
# Compute commitment u = g1^r1 * g2^r2 * ... * gn^rn
|
|
181
|
+
u = generators[0] ** self._r_values[0]
|
|
182
|
+
for i in range(1, self._n):
|
|
183
|
+
u = u * (generators[i] ** self._r_values[i])
|
|
184
|
+
|
|
185
|
+
logger.debug("Prover created commitment for %d witnesses", self._n)
|
|
186
|
+
return u
|
|
187
|
+
|
|
188
|
+
def create_response(self, challenge):
|
|
189
|
+
"""
|
|
190
|
+
Create responses to verifier's challenge: zi = ri + c*xi for each i.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
challenge: The challenge value c from verifier
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
List of responses [z1, z2, ..., zn] where zi = ri + c*xi
|
|
197
|
+
|
|
198
|
+
Raises:
|
|
199
|
+
ValueError: If create_commitment was not called first
|
|
200
|
+
"""
|
|
201
|
+
if self._r_values is None:
|
|
202
|
+
raise ValueError("Must call create_commitment before create_response")
|
|
203
|
+
|
|
204
|
+
# Compute zi = ri + c*xi for each witness
|
|
205
|
+
responses = []
|
|
206
|
+
for i in range(self._n):
|
|
207
|
+
z_i = self._r_values[i] + challenge * self._witnesses[i]
|
|
208
|
+
responses.append(z_i)
|
|
209
|
+
|
|
210
|
+
logger.debug("Prover created %d responses", self._n)
|
|
211
|
+
return responses
|
|
212
|
+
|
|
213
|
+
class Verifier:
|
|
214
|
+
"""Verifier for Representation protocol.
|
|
215
|
+
|
|
216
|
+
The verifier checks the proof without learning the secret witnesses.
|
|
217
|
+
"""
|
|
218
|
+
|
|
219
|
+
def __init__(self, group):
|
|
220
|
+
"""
|
|
221
|
+
Initialize verifier.
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
group: The pairing group object
|
|
225
|
+
"""
|
|
226
|
+
self.group = group
|
|
227
|
+
self._c = None # Challenge (stored for verification)
|
|
228
|
+
|
|
229
|
+
def create_challenge(self):
|
|
230
|
+
"""
|
|
231
|
+
Create random challenge c.
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
Random challenge c in ZR
|
|
235
|
+
"""
|
|
236
|
+
self._c = self.group.random(ZR)
|
|
237
|
+
logger.debug("Verifier created challenge")
|
|
238
|
+
return self._c
|
|
239
|
+
|
|
240
|
+
def verify(self, generators, h, commitment, responses):
|
|
241
|
+
"""
|
|
242
|
+
Verify proof: g1^z1 * g2^z2 * ... * gn^zn == u * h^c.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
generators: List of generator elements [g1, g2, ..., gn]
|
|
246
|
+
h: The public value h = g1^x1 * g2^x2 * ... * gn^xn
|
|
247
|
+
commitment: The prover's commitment u
|
|
248
|
+
responses: List of prover's responses [z1, z2, ..., zn]
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
True if proof is valid, False otherwise
|
|
252
|
+
|
|
253
|
+
Raises:
|
|
254
|
+
ValueError: If create_challenge was not called first
|
|
255
|
+
ValueError: If number of generators doesn't match number of responses
|
|
256
|
+
"""
|
|
257
|
+
if self._c is None:
|
|
258
|
+
raise ValueError("Must call create_challenge before verify")
|
|
259
|
+
|
|
260
|
+
if len(generators) != len(responses):
|
|
261
|
+
raise ValueError(
|
|
262
|
+
f"Number of generators ({len(generators)}) must match "
|
|
263
|
+
f"number of responses ({len(responses)})"
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
n = len(generators)
|
|
267
|
+
|
|
268
|
+
# Compute LHS: g1^z1 * g2^z2 * ... * gn^zn
|
|
269
|
+
lhs = generators[0] ** responses[0]
|
|
270
|
+
for i in range(1, n):
|
|
271
|
+
lhs = lhs * (generators[i] ** responses[i])
|
|
272
|
+
|
|
273
|
+
# Compute RHS: u * h^c
|
|
274
|
+
rhs = commitment * (h ** self._c)
|
|
275
|
+
|
|
276
|
+
result = lhs == rhs
|
|
277
|
+
logger.debug("Verification result: %s", result)
|
|
278
|
+
return result
|
|
279
|
+
|
|
280
|
+
@classmethod
|
|
281
|
+
def _compute_challenge_hash(cls, group, generators, h, commitment):
|
|
282
|
+
"""
|
|
283
|
+
Compute Fiat-Shamir challenge as hash of public values.
|
|
284
|
+
|
|
285
|
+
The challenge is computed as H(g1 || g2 || ... || gn || h || u)
|
|
286
|
+
where || denotes concatenation of serialized elements.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
group: The pairing group
|
|
290
|
+
generators: List of generators [g1, g2, ..., gn]
|
|
291
|
+
h: Public value h = g1^x1 * g2^x2 * ... * gn^xn
|
|
292
|
+
commitment: The commitment u
|
|
293
|
+
|
|
294
|
+
Returns:
|
|
295
|
+
Challenge c as element of ZR
|
|
296
|
+
"""
|
|
297
|
+
# Serialize all generators
|
|
298
|
+
data = b''
|
|
299
|
+
for g in generators:
|
|
300
|
+
data += objectToBytes(g, group)
|
|
301
|
+
|
|
302
|
+
# Add h and commitment
|
|
303
|
+
data += objectToBytes(h, group)
|
|
304
|
+
data += objectToBytes(commitment, group)
|
|
305
|
+
|
|
306
|
+
return group.hash(data, ZR)
|
|
307
|
+
|
|
308
|
+
@classmethod
|
|
309
|
+
def prove_non_interactive(cls, group: PairingGroup, generators: List[Any], h: Any, witnesses: List[Any]) -> 'RepresentationProofData':
|
|
310
|
+
"""
|
|
311
|
+
Generate non-interactive proof using Fiat-Shamir heuristic.
|
|
312
|
+
|
|
313
|
+
Creates a proof that the prover knows witnesses (x1, x2, ..., xn)
|
|
314
|
+
such that h = g1^x1 * g2^x2 * ... * gn^xn.
|
|
315
|
+
|
|
316
|
+
Args:
|
|
317
|
+
group: The pairing group
|
|
318
|
+
generators: List of generator elements [g1, g2, ..., gn]
|
|
319
|
+
h: The public value h = g1^x1 * g2^x2 * ... * gn^xn
|
|
320
|
+
witnesses: List of secret discrete log values [x1, x2, ..., xn]
|
|
321
|
+
|
|
322
|
+
Returns:
|
|
323
|
+
RepresentationProofData object containing commitment, challenge, and responses
|
|
324
|
+
|
|
325
|
+
Raises:
|
|
326
|
+
ValueError: If number of generators doesn't match number of witnesses
|
|
327
|
+
"""
|
|
328
|
+
n = len(generators)
|
|
329
|
+
if len(witnesses) != n:
|
|
330
|
+
raise ValueError(
|
|
331
|
+
f"Number of generators ({n}) must match number of witnesses ({len(witnesses)})"
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
# 1. Generate random values r1, r2, ..., rn
|
|
335
|
+
r_values = [group.random(ZR) for _ in range(n)]
|
|
336
|
+
|
|
337
|
+
# 2. Compute commitment u = g1^r1 * g2^r2 * ... * gn^rn
|
|
338
|
+
commitment = generators[0] ** r_values[0]
|
|
339
|
+
for i in range(1, n):
|
|
340
|
+
commitment = commitment * (generators[i] ** r_values[i])
|
|
341
|
+
|
|
342
|
+
# 3. Compute challenge c = hash(g1, g2, ..., gn, h, u)
|
|
343
|
+
challenge = cls._compute_challenge_hash(group, generators, h, commitment)
|
|
344
|
+
|
|
345
|
+
# 4. Compute responses zi = ri + c*xi for each i
|
|
346
|
+
responses = []
|
|
347
|
+
for i in range(n):
|
|
348
|
+
z_i = r_values[i] + challenge * witnesses[i]
|
|
349
|
+
responses.append(z_i)
|
|
350
|
+
|
|
351
|
+
logger.debug("Generated non-interactive representation proof for %d witnesses", n)
|
|
352
|
+
return RepresentationProofData(
|
|
353
|
+
commitment=commitment,
|
|
354
|
+
challenge=challenge,
|
|
355
|
+
responses=responses,
|
|
356
|
+
proof_type='representation'
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
@classmethod
|
|
360
|
+
def verify_non_interactive(cls, group: PairingGroup, generators: List[Any], h: Any, proof: 'RepresentationProofData') -> bool:
|
|
361
|
+
"""
|
|
362
|
+
Verify non-interactive representation proof.
|
|
363
|
+
|
|
364
|
+
Checks that the prover knows witnesses (x1, x2, ..., xn) such that
|
|
365
|
+
h = g1^x1 * g2^x2 * ... * gn^xn.
|
|
366
|
+
|
|
367
|
+
Args:
|
|
368
|
+
group: The pairing group
|
|
369
|
+
generators: List of generator elements [g1, g2, ..., gn]
|
|
370
|
+
h: The public value h = g1^x1 * g2^x2 * ... * gn^xn
|
|
371
|
+
proof: RepresentationProofData object containing commitment, challenge, responses
|
|
372
|
+
|
|
373
|
+
Returns:
|
|
374
|
+
True if proof is valid, False otherwise
|
|
375
|
+
|
|
376
|
+
Security Notes:
|
|
377
|
+
- Validates proof structure before verification
|
|
378
|
+
- Checks for identity element attacks
|
|
379
|
+
- Recomputes Fiat-Shamir challenge for consistency
|
|
380
|
+
"""
|
|
381
|
+
# Security: Validate proof structure
|
|
382
|
+
required_attrs = ['commitment', 'challenge', 'responses']
|
|
383
|
+
for attr in required_attrs:
|
|
384
|
+
if not hasattr(proof, attr):
|
|
385
|
+
logger.warning("Invalid Representation proof structure: missing '%s'. Ensure proof was created with RepresentationProof.prove_non_interactive()", attr)
|
|
386
|
+
return False
|
|
387
|
+
|
|
388
|
+
# Security: Check for identity element (potential attack vector)
|
|
389
|
+
try:
|
|
390
|
+
identity = group.init(G1, 1)
|
|
391
|
+
if proof.commitment == identity:
|
|
392
|
+
logger.warning("Security: Representation proof commitment is identity element")
|
|
393
|
+
return False
|
|
394
|
+
except Exception:
|
|
395
|
+
pass # Some groups may not support identity check
|
|
396
|
+
|
|
397
|
+
n = len(generators)
|
|
398
|
+
|
|
399
|
+
# Validate proof structure
|
|
400
|
+
if len(proof.responses) != n:
|
|
401
|
+
logger.debug(
|
|
402
|
+
"Proof response count (%d) doesn't match generator count (%d)",
|
|
403
|
+
len(proof.responses), n
|
|
404
|
+
)
|
|
405
|
+
return False
|
|
406
|
+
|
|
407
|
+
# Recompute challenge c = hash(g1, g2, ..., gn, h, commitment)
|
|
408
|
+
expected_challenge = cls._compute_challenge_hash(group, generators, h, proof.commitment)
|
|
409
|
+
|
|
410
|
+
# Verify challenge matches (Fiat-Shamir consistency check)
|
|
411
|
+
if expected_challenge != proof.challenge:
|
|
412
|
+
logger.debug("Challenge mismatch in non-interactive verification")
|
|
413
|
+
return False
|
|
414
|
+
|
|
415
|
+
# Check: g1^z1 * g2^z2 * ... * gn^zn == commitment * h^c
|
|
416
|
+
# LHS: g1^z1 * g2^z2 * ... * gn^zn
|
|
417
|
+
lhs = generators[0] ** proof.responses[0]
|
|
418
|
+
for i in range(1, n):
|
|
419
|
+
lhs = lhs * (generators[i] ** proof.responses[i])
|
|
420
|
+
|
|
421
|
+
# RHS: commitment * h^c
|
|
422
|
+
rhs = proof.commitment * (h ** proof.challenge)
|
|
423
|
+
|
|
424
|
+
result = lhs == rhs
|
|
425
|
+
logger.debug("Non-interactive verification result: %s", result)
|
|
426
|
+
return result
|
|
427
|
+
|
|
428
|
+
@classmethod
|
|
429
|
+
def serialize_proof(cls, proof: 'RepresentationProofData', group: PairingGroup) -> bytes:
|
|
430
|
+
"""
|
|
431
|
+
Serialize proof to bytes using Charm utilities.
|
|
432
|
+
|
|
433
|
+
Args:
|
|
434
|
+
proof: RepresentationProofData object to serialize
|
|
435
|
+
group: The pairing group
|
|
436
|
+
|
|
437
|
+
Returns:
|
|
438
|
+
Bytes representation of the proof
|
|
439
|
+
"""
|
|
440
|
+
proof_dict = {
|
|
441
|
+
'commitment': proof.commitment,
|
|
442
|
+
'challenge': proof.challenge,
|
|
443
|
+
'responses': proof.responses,
|
|
444
|
+
'proof_type': proof.proof_type
|
|
445
|
+
}
|
|
446
|
+
return objectToBytes(proof_dict, group)
|
|
447
|
+
|
|
448
|
+
@classmethod
|
|
449
|
+
def deserialize_proof(cls, data: bytes, group: PairingGroup) -> 'RepresentationProofData':
|
|
450
|
+
"""
|
|
451
|
+
Deserialize bytes to proof.
|
|
452
|
+
|
|
453
|
+
Args:
|
|
454
|
+
data: Bytes to deserialize
|
|
455
|
+
group: The pairing group
|
|
456
|
+
|
|
457
|
+
Returns:
|
|
458
|
+
RepresentationProofData object
|
|
459
|
+
"""
|
|
460
|
+
proof_dict = bytesToObject(data, group)
|
|
461
|
+
return RepresentationProofData(
|
|
462
|
+
commitment=proof_dict['commitment'],
|
|
463
|
+
challenge=proof_dict['challenge'],
|
|
464
|
+
responses=proof_dict['responses'],
|
|
465
|
+
proof_type=proof_dict.get('proof_type', 'representation')
|
|
466
|
+
)
|