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,305 @@
|
|
|
1
|
+
"""
|
|
2
|
+
OR Composition for Zero-Knowledge Proofs (CDS94).
|
|
3
|
+
|
|
4
|
+
This module implements the Cramer-Damgård-Schoenmakers (CDS94) technique for
|
|
5
|
+
composing zero-knowledge proofs with OR logic.
|
|
6
|
+
|
|
7
|
+
What OR Composition Proves:
|
|
8
|
+
Proves "I know the discrete log of h1 OR I know the discrete log of h2"
|
|
9
|
+
without revealing WHICH statement the prover actually knows. This is a
|
|
10
|
+
disjunctive proof of knowledge.
|
|
11
|
+
|
|
12
|
+
The CDS94 Technique:
|
|
13
|
+
The key insight is that for the statement the prover does NOT know, they
|
|
14
|
+
can simulate a valid-looking proof by choosing the challenge and response
|
|
15
|
+
first, then computing a fake commitment. For the known statement, they
|
|
16
|
+
create a real proof.
|
|
17
|
+
|
|
18
|
+
1. KNOWN statement (e.g., h1 = g^x, prover knows x):
|
|
19
|
+
- Generate random r, compute u1 = g^r (real commitment)
|
|
20
|
+
|
|
21
|
+
2. UNKNOWN statement (e.g., h2, prover doesn't know its DL):
|
|
22
|
+
- Simulate: pick random c2, z2
|
|
23
|
+
- Compute u2 = g^z2 * h2^(-c2) (fake commitment that will verify)
|
|
24
|
+
|
|
25
|
+
3. Challenge splitting: c = c1 + c2 (mod q)
|
|
26
|
+
- Compute main challenge: c = H(g, h1, h2, u1, u2)
|
|
27
|
+
- Set c1 = c - c2 (ensures c1 + c2 = c)
|
|
28
|
+
|
|
29
|
+
4. Real response: z1 = r + c1*x
|
|
30
|
+
|
|
31
|
+
5. Output: (u1, u2, c1, c2, z1, z2)
|
|
32
|
+
|
|
33
|
+
Security Properties:
|
|
34
|
+
- Witness Indistinguishability: A verifier cannot tell which branch the
|
|
35
|
+
prover actually knows, even with unbounded computational power.
|
|
36
|
+
- Soundness: A prover who knows neither discrete log cannot produce a
|
|
37
|
+
valid proof (except with negligible probability).
|
|
38
|
+
- Zero-Knowledge: The proof reveals nothing beyond the OR statement.
|
|
39
|
+
|
|
40
|
+
Use Cases:
|
|
41
|
+
- Anonymous Credentials: Prove membership in group A OR group B
|
|
42
|
+
- Voting Systems: Prove vote is for candidate A OR candidate B
|
|
43
|
+
- Deniable Authentication: Prove identity while maintaining deniability
|
|
44
|
+
- Ring Signatures: Prove one of several public keys is yours
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
>>> from charm.toolbox.pairinggroup import PairingGroup, ZR, G1
|
|
48
|
+
>>> group = PairingGroup('SS512')
|
|
49
|
+
>>> g = group.random(G1)
|
|
50
|
+
>>> x = group.random(ZR)
|
|
51
|
+
>>> h1 = g ** x # Prover knows DL of h1
|
|
52
|
+
>>> h2 = g ** group.random(ZR) # Prover does NOT know DL of h2
|
|
53
|
+
>>>
|
|
54
|
+
>>> # Prove knowledge of x such that h1 = g^x OR h2 = g^x (without revealing which)
|
|
55
|
+
>>> # Prover knows x for h1
|
|
56
|
+
>>> proof = ORProof.prove_non_interactive(group, g, h1, h2, x, which=0)
|
|
57
|
+
>>> valid = ORProof.verify_non_interactive(group, g, h1, h2, proof)
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
from typing import 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 ORProofData:
|
|
70
|
+
"""Container for OR proof data."""
|
|
71
|
+
|
|
72
|
+
def __init__(self, commitment1: Any, commitment2: Any, challenge1: Any, challenge2: Any,
|
|
73
|
+
response1: Any, response2: Any, proof_type: str = 'or') -> None:
|
|
74
|
+
"""
|
|
75
|
+
Initialize an OR proof.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
commitment1: Commitment for first branch (u1)
|
|
79
|
+
commitment2: Commitment for second branch (u2)
|
|
80
|
+
challenge1: Challenge for first branch (c1)
|
|
81
|
+
challenge2: Challenge for second branch (c2)
|
|
82
|
+
response1: Response for first branch (z1)
|
|
83
|
+
response2: Response for second branch (z2)
|
|
84
|
+
proof_type: Type identifier for the proof
|
|
85
|
+
"""
|
|
86
|
+
self.commitment1 = commitment1
|
|
87
|
+
self.commitment2 = commitment2
|
|
88
|
+
self.challenge1 = challenge1
|
|
89
|
+
self.challenge2 = challenge2
|
|
90
|
+
self.response1 = response1
|
|
91
|
+
self.response2 = response2
|
|
92
|
+
self.proof_type = proof_type
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class ORProof:
|
|
96
|
+
"""
|
|
97
|
+
OR Composition of Schnorr Proofs using CDS94.
|
|
98
|
+
|
|
99
|
+
Proves knowledge of discrete log for h1 = g^x OR h2 = g^x without
|
|
100
|
+
revealing which one the prover actually knows.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
@classmethod
|
|
104
|
+
def _compute_challenge_hash(cls, group, g, h1, h2, u1, u2):
|
|
105
|
+
"""
|
|
106
|
+
Compute Fiat-Shamir challenge as hash of all public values.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
group: The pairing group
|
|
110
|
+
g: Generator
|
|
111
|
+
h1: First public value
|
|
112
|
+
h2: Second public value
|
|
113
|
+
u1: First commitment
|
|
114
|
+
u2: Second commitment
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
Challenge c as element of ZR
|
|
118
|
+
"""
|
|
119
|
+
data = (objectToBytes(g, group) + objectToBytes(h1, group) +
|
|
120
|
+
objectToBytes(h2, group) + objectToBytes(u1, group) +
|
|
121
|
+
objectToBytes(u2, group))
|
|
122
|
+
return group.hash(data, ZR)
|
|
123
|
+
|
|
124
|
+
@classmethod
|
|
125
|
+
def prove_non_interactive(cls, group: PairingGroup, g: Any, h1: Any, h2: Any, x: Any, which: int) -> 'ORProofData':
|
|
126
|
+
"""
|
|
127
|
+
Generate non-interactive OR proof using CDS94 technique.
|
|
128
|
+
|
|
129
|
+
Proves knowledge of x such that h1 = g^x OR h2 = g^x.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
group: The pairing group
|
|
133
|
+
g: The generator element
|
|
134
|
+
h1: First public value
|
|
135
|
+
h2: Second public value
|
|
136
|
+
x: The secret discrete log (for h1 if which=0, for h2 if which=1)
|
|
137
|
+
which: 0 if prover knows x for h1, 1 if prover knows x for h2
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
ORProofData object containing commitments, challenges, and responses
|
|
141
|
+
"""
|
|
142
|
+
if which not in (0, 1):
|
|
143
|
+
raise ValueError("which must be 0 or 1")
|
|
144
|
+
|
|
145
|
+
if which == 0:
|
|
146
|
+
# Prover knows DL of h1, simulates proof for h2
|
|
147
|
+
# Real proof for h1
|
|
148
|
+
r = group.random(ZR)
|
|
149
|
+
u1 = g ** r
|
|
150
|
+
|
|
151
|
+
# Simulate proof for h2: pick c2, z2, compute u2
|
|
152
|
+
c2 = group.random(ZR)
|
|
153
|
+
z2 = group.random(ZR)
|
|
154
|
+
# u2 = g^z2 * h2^(-c2) so that g^z2 = u2 * h2^c2
|
|
155
|
+
u2 = (g ** z2) * (h2 ** (-c2))
|
|
156
|
+
|
|
157
|
+
# Compute main challenge
|
|
158
|
+
c = cls._compute_challenge_hash(group, g, h1, h2, u1, u2)
|
|
159
|
+
|
|
160
|
+
# Split challenge: c1 = c - c2
|
|
161
|
+
c1 = c - c2
|
|
162
|
+
|
|
163
|
+
# Real response: z1 = r + c1*x
|
|
164
|
+
z1 = r + c1 * x
|
|
165
|
+
|
|
166
|
+
else: # which == 1
|
|
167
|
+
# Prover knows DL of h2, simulates proof for h1
|
|
168
|
+
# Simulate proof for h1: pick c1, z1, compute u1
|
|
169
|
+
c1 = group.random(ZR)
|
|
170
|
+
z1 = group.random(ZR)
|
|
171
|
+
# u1 = g^z1 * h1^(-c1) so that g^z1 = u1 * h1^c1
|
|
172
|
+
u1 = (g ** z1) * (h1 ** (-c1))
|
|
173
|
+
|
|
174
|
+
# Real proof for h2
|
|
175
|
+
r = group.random(ZR)
|
|
176
|
+
u2 = g ** r
|
|
177
|
+
|
|
178
|
+
# Compute main challenge
|
|
179
|
+
c = cls._compute_challenge_hash(group, g, h1, h2, u1, u2)
|
|
180
|
+
|
|
181
|
+
# Split challenge: c2 = c - c1
|
|
182
|
+
c2 = c - c1
|
|
183
|
+
|
|
184
|
+
# Real response: z2 = r + c2*x
|
|
185
|
+
z2 = r + c2 * x
|
|
186
|
+
|
|
187
|
+
logger.debug("Generated OR proof (which=%d)", which)
|
|
188
|
+
return ORProofData(
|
|
189
|
+
commitment1=u1, commitment2=u2,
|
|
190
|
+
challenge1=c1, challenge2=c2,
|
|
191
|
+
response1=z1, response2=z2,
|
|
192
|
+
proof_type='or'
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
@classmethod
|
|
196
|
+
def verify_non_interactive(cls, group: PairingGroup, g: Any, h1: Any, h2: Any, proof: 'ORProofData') -> bool:
|
|
197
|
+
"""
|
|
198
|
+
Verify non-interactive OR proof.
|
|
199
|
+
|
|
200
|
+
Verifies that the prover knows the discrete log of h1 OR h2.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
group: The pairing group
|
|
204
|
+
g: The generator element
|
|
205
|
+
h1: First public value
|
|
206
|
+
h2: Second public value
|
|
207
|
+
proof: ORProofData object containing commitments, challenges, responses
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
True if proof is valid, False otherwise
|
|
211
|
+
|
|
212
|
+
Security Notes:
|
|
213
|
+
- Validates proof structure before verification
|
|
214
|
+
- Checks for identity element attacks
|
|
215
|
+
- Recomputes Fiat-Shamir challenge for consistency
|
|
216
|
+
"""
|
|
217
|
+
# Security: Validate proof structure
|
|
218
|
+
required_attrs = ['commitment1', 'commitment2', 'challenge1', 'challenge2', 'response1', 'response2']
|
|
219
|
+
for attr in required_attrs:
|
|
220
|
+
if not hasattr(proof, attr):
|
|
221
|
+
logger.warning("Invalid OR proof structure: missing '%s'. Ensure proof was created with ORProof.prove_non_interactive()", attr)
|
|
222
|
+
return False
|
|
223
|
+
|
|
224
|
+
# Security: Check for identity element (potential attack vector)
|
|
225
|
+
try:
|
|
226
|
+
identity = group.init(G1, 1)
|
|
227
|
+
if proof.commitment1 == identity or proof.commitment2 == identity:
|
|
228
|
+
logger.warning("Security: OR proof commitment is identity element")
|
|
229
|
+
return False
|
|
230
|
+
except Exception:
|
|
231
|
+
pass # Some groups may not support identity check
|
|
232
|
+
|
|
233
|
+
# Recompute main challenge: c = H(g, h1, h2, u1, u2)
|
|
234
|
+
expected_c = cls._compute_challenge_hash(
|
|
235
|
+
group, g, h1, h2, proof.commitment1, proof.commitment2
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
# Check c1 + c2 = c (challenge splitting)
|
|
239
|
+
actual_c = proof.challenge1 + proof.challenge2
|
|
240
|
+
if expected_c != actual_c:
|
|
241
|
+
logger.debug("Challenge sum mismatch in OR verification")
|
|
242
|
+
return False
|
|
243
|
+
|
|
244
|
+
# Check first branch: g^z1 = u1 * h1^c1
|
|
245
|
+
lhs1 = g ** proof.response1
|
|
246
|
+
rhs1 = proof.commitment1 * (h1 ** proof.challenge1)
|
|
247
|
+
if lhs1 != rhs1:
|
|
248
|
+
logger.debug("First branch verification failed")
|
|
249
|
+
return False
|
|
250
|
+
|
|
251
|
+
# Check second branch: g^z2 = u2 * h2^c2
|
|
252
|
+
lhs2 = g ** proof.response2
|
|
253
|
+
rhs2 = proof.commitment2 * (h2 ** proof.challenge2)
|
|
254
|
+
if lhs2 != rhs2:
|
|
255
|
+
logger.debug("Second branch verification failed")
|
|
256
|
+
return False
|
|
257
|
+
|
|
258
|
+
logger.debug("OR proof verification succeeded")
|
|
259
|
+
return True
|
|
260
|
+
|
|
261
|
+
@classmethod
|
|
262
|
+
def serialize_proof(cls, proof: 'ORProofData', group: PairingGroup) -> bytes:
|
|
263
|
+
"""
|
|
264
|
+
Serialize OR proof to bytes using Charm utilities.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
proof: ORProofData object to serialize
|
|
268
|
+
group: The pairing group
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
Bytes representation of the proof
|
|
272
|
+
"""
|
|
273
|
+
proof_dict = {
|
|
274
|
+
'commitment1': proof.commitment1,
|
|
275
|
+
'commitment2': proof.commitment2,
|
|
276
|
+
'challenge1': proof.challenge1,
|
|
277
|
+
'challenge2': proof.challenge2,
|
|
278
|
+
'response1': proof.response1,
|
|
279
|
+
'response2': proof.response2,
|
|
280
|
+
'proof_type': proof.proof_type
|
|
281
|
+
}
|
|
282
|
+
return objectToBytes(proof_dict, group)
|
|
283
|
+
|
|
284
|
+
@classmethod
|
|
285
|
+
def deserialize_proof(cls, data: bytes, group: PairingGroup) -> 'ORProofData':
|
|
286
|
+
"""
|
|
287
|
+
Deserialize bytes to OR proof.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
data: Bytes to deserialize
|
|
291
|
+
group: The pairing group
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
ORProofData object
|
|
295
|
+
"""
|
|
296
|
+
proof_dict = bytesToObject(data, group)
|
|
297
|
+
return ORProofData(
|
|
298
|
+
commitment1=proof_dict['commitment1'],
|
|
299
|
+
commitment2=proof_dict['commitment2'],
|
|
300
|
+
challenge1=proof_dict['challenge1'],
|
|
301
|
+
challenge2=proof_dict['challenge2'],
|
|
302
|
+
response1=proof_dict['response1'],
|
|
303
|
+
response2=proof_dict['response2'],
|
|
304
|
+
proof_type=proof_dict.get('proof_type', 'or')
|
|
305
|
+
)
|