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.
Files changed (323) hide show
  1. charm/__init__.py +5 -0
  2. charm/adapters/__init__.py +0 -0
  3. charm/adapters/abenc_adapt_hybrid.py +90 -0
  4. charm/adapters/dabenc_adapt_hybrid.py +145 -0
  5. charm/adapters/ibenc_adapt_hybrid.py +72 -0
  6. charm/adapters/ibenc_adapt_identityhash.py +80 -0
  7. charm/adapters/kpabenc_adapt_hybrid.py +91 -0
  8. charm/adapters/pkenc_adapt_bchk05.py +121 -0
  9. charm/adapters/pkenc_adapt_chk04.py +91 -0
  10. charm/adapters/pkenc_adapt_hybrid.py +98 -0
  11. charm/adapters/pksig_adapt_naor01.py +89 -0
  12. charm/config.py +7 -0
  13. charm/core/__init__.py +0 -0
  14. charm/core/benchmark/benchmark_util.c +353 -0
  15. charm/core/benchmark/benchmark_util.h +61 -0
  16. charm/core/benchmark/benchmarkmodule.c +476 -0
  17. charm/core/benchmark/benchmarkmodule.h +162 -0
  18. charm/core/benchmark.cpython-313-darwin.so +0 -0
  19. charm/core/crypto/AES/AES.c +1464 -0
  20. charm/core/crypto/AES.cpython-313-darwin.so +0 -0
  21. charm/core/crypto/DES/DES.c +113 -0
  22. charm/core/crypto/DES.cpython-313-darwin.so +0 -0
  23. charm/core/crypto/DES3/DES3.c +26 -0
  24. charm/core/crypto/DES3.cpython-313-darwin.so +0 -0
  25. charm/core/crypto/__init__.py +0 -0
  26. charm/core/crypto/cryptobase/XOR.c +80 -0
  27. charm/core/crypto/cryptobase/_counter.c +496 -0
  28. charm/core/crypto/cryptobase/_counter.h +54 -0
  29. charm/core/crypto/cryptobase/block_template.c +900 -0
  30. charm/core/crypto/cryptobase/block_template.h +69 -0
  31. charm/core/crypto/cryptobase/cryptobasemodule.c +220 -0
  32. charm/core/crypto/cryptobase/libtom/tomcrypt.h +90 -0
  33. charm/core/crypto/cryptobase/libtom/tomcrypt_argchk.h +44 -0
  34. charm/core/crypto/cryptobase/libtom/tomcrypt_cfg.h +186 -0
  35. charm/core/crypto/cryptobase/libtom/tomcrypt_cipher.h +941 -0
  36. charm/core/crypto/cryptobase/libtom/tomcrypt_custom.h +556 -0
  37. charm/core/crypto/cryptobase/libtom/tomcrypt_des.c +1912 -0
  38. charm/core/crypto/cryptobase/libtom/tomcrypt_hash.h +407 -0
  39. charm/core/crypto/cryptobase/libtom/tomcrypt_mac.h +496 -0
  40. charm/core/crypto/cryptobase/libtom/tomcrypt_macros.h +435 -0
  41. charm/core/crypto/cryptobase/libtom/tomcrypt_math.h +534 -0
  42. charm/core/crypto/cryptobase/libtom/tomcrypt_misc.h +103 -0
  43. charm/core/crypto/cryptobase/libtom/tomcrypt_pk.h +653 -0
  44. charm/core/crypto/cryptobase/libtom/tomcrypt_pkcs.h +90 -0
  45. charm/core/crypto/cryptobase/libtom/tomcrypt_prng.h +199 -0
  46. charm/core/crypto/cryptobase/stream_template.c +271 -0
  47. charm/core/crypto/cryptobase/strxor.c +229 -0
  48. charm/core/crypto/cryptobase.cpython-313-darwin.so +0 -0
  49. charm/core/engine/__init__.py +5 -0
  50. charm/core/engine/protocol.py +293 -0
  51. charm/core/engine/util.py +174 -0
  52. charm/core/math/__init__.py +0 -0
  53. charm/core/math/elliptic_curve/ecmodule.c +1986 -0
  54. charm/core/math/elliptic_curve/ecmodule.h +230 -0
  55. charm/core/math/elliptic_curve.cpython-313-darwin.so +0 -0
  56. charm/core/math/elliptic_curve.pyi +63 -0
  57. charm/core/math/integer/integermodule.c +2539 -0
  58. charm/core/math/integer/integermodule.h +145 -0
  59. charm/core/math/integer.cpython-313-darwin.so +0 -0
  60. charm/core/math/integer.pyi +76 -0
  61. charm/core/math/pairing/miracl/miracl_config.h +37 -0
  62. charm/core/math/pairing/miracl/miracl_interface.h +118 -0
  63. charm/core/math/pairing/miracl/miracl_interface2.h +126 -0
  64. charm/core/math/pairing/miracl/pairingmodule2.c +2094 -0
  65. charm/core/math/pairing/miracl/pairingmodule2.h +307 -0
  66. charm/core/math/pairing/pairingmodule.c +2230 -0
  67. charm/core/math/pairing/pairingmodule.h +241 -0
  68. charm/core/math/pairing/relic/pairingmodule3.c +1853 -0
  69. charm/core/math/pairing/relic/pairingmodule3.h +233 -0
  70. charm/core/math/pairing/relic/relic_interface.c +1337 -0
  71. charm/core/math/pairing/relic/relic_interface.h +217 -0
  72. charm/core/math/pairing/relic/test_relic.c +171 -0
  73. charm/core/math/pairing.cpython-313-darwin.so +0 -0
  74. charm/core/math/pairing.pyi +69 -0
  75. charm/core/utilities/base64.c +248 -0
  76. charm/core/utilities/base64.h +15 -0
  77. charm/schemes/__init__.py +0 -0
  78. charm/schemes/abenc/__init__.py +0 -0
  79. charm/schemes/abenc/abenc_accountability_jyjxgd20.py +647 -0
  80. charm/schemes/abenc/abenc_bsw07.py +146 -0
  81. charm/schemes/abenc/abenc_ca_cpabe_ar17.py +684 -0
  82. charm/schemes/abenc/abenc_dacmacs_yj14.py +298 -0
  83. charm/schemes/abenc/abenc_lsw08.py +159 -0
  84. charm/schemes/abenc/abenc_maabe_rw15.py +236 -0
  85. charm/schemes/abenc/abenc_maabe_yj14.py +297 -0
  86. charm/schemes/abenc/abenc_tbpre_lww14.py +309 -0
  87. charm/schemes/abenc/abenc_unmcpabe_yahk14.py +223 -0
  88. charm/schemes/abenc/abenc_waters09.py +144 -0
  89. charm/schemes/abenc/abenc_yct14.py +208 -0
  90. charm/schemes/abenc/abenc_yllc15.py +178 -0
  91. charm/schemes/abenc/ac17.py +248 -0
  92. charm/schemes/abenc/bsw07.py +141 -0
  93. charm/schemes/abenc/cgw15.py +277 -0
  94. charm/schemes/abenc/dabe_aw11.py +204 -0
  95. charm/schemes/abenc/dfa_fe12.py +144 -0
  96. charm/schemes/abenc/pk_hve08.py +179 -0
  97. charm/schemes/abenc/waters11.py +143 -0
  98. charm/schemes/aggrsign_MuSig.py +150 -0
  99. charm/schemes/aggrsign_bls.py +267 -0
  100. charm/schemes/blindsig_ps16.py +654 -0
  101. charm/schemes/chamhash_adm05.py +113 -0
  102. charm/schemes/chamhash_rsa_hw09.py +100 -0
  103. charm/schemes/commit/__init__.py +0 -0
  104. charm/schemes/commit/commit_gs08.py +77 -0
  105. charm/schemes/commit/commit_pedersen92.py +53 -0
  106. charm/schemes/encap_bchk05.py +62 -0
  107. charm/schemes/grpsig/__init__.py +0 -0
  108. charm/schemes/grpsig/groupsig_bgls04.py +114 -0
  109. charm/schemes/grpsig/groupsig_bgls04_var.py +115 -0
  110. charm/schemes/hibenc/__init__.py +0 -0
  111. charm/schemes/hibenc/hibenc_bb04.py +105 -0
  112. charm/schemes/hibenc/hibenc_lew11.py +193 -0
  113. charm/schemes/ibenc/__init__.py +0 -0
  114. charm/schemes/ibenc/clpkc_rp03.py +119 -0
  115. charm/schemes/ibenc/ibenc_CW13_z.py +168 -0
  116. charm/schemes/ibenc/ibenc_bb03.py +94 -0
  117. charm/schemes/ibenc/ibenc_bf01.py +121 -0
  118. charm/schemes/ibenc/ibenc_ckrs09.py +120 -0
  119. charm/schemes/ibenc/ibenc_cllww12_z.py +172 -0
  120. charm/schemes/ibenc/ibenc_lsw08.py +120 -0
  121. charm/schemes/ibenc/ibenc_sw05.py +238 -0
  122. charm/schemes/ibenc/ibenc_waters05.py +144 -0
  123. charm/schemes/ibenc/ibenc_waters05_z.py +164 -0
  124. charm/schemes/ibenc/ibenc_waters09.py +107 -0
  125. charm/schemes/ibenc/ibenc_waters09_z.py +147 -0
  126. charm/schemes/joye_scheme.py +106 -0
  127. charm/schemes/lem_scheme.py +207 -0
  128. charm/schemes/pk_fre_ccv11.py +107 -0
  129. charm/schemes/pk_vrf.py +127 -0
  130. charm/schemes/pkenc/__init__.py +0 -0
  131. charm/schemes/pkenc/pkenc_cs98.py +108 -0
  132. charm/schemes/pkenc/pkenc_elgamal85.py +122 -0
  133. charm/schemes/pkenc/pkenc_gm82.py +98 -0
  134. charm/schemes/pkenc/pkenc_paillier99.py +118 -0
  135. charm/schemes/pkenc/pkenc_rabin.py +254 -0
  136. charm/schemes/pkenc/pkenc_rsa.py +186 -0
  137. charm/schemes/pksig/__init__.py +0 -0
  138. charm/schemes/pksig/pksig_CW13_z.py +135 -0
  139. charm/schemes/pksig/pksig_bls04.py +87 -0
  140. charm/schemes/pksig/pksig_boyen.py +156 -0
  141. charm/schemes/pksig/pksig_chch.py +97 -0
  142. charm/schemes/pksig/pksig_chp.py +70 -0
  143. charm/schemes/pksig/pksig_cl03.py +150 -0
  144. charm/schemes/pksig/pksig_cl04.py +87 -0
  145. charm/schemes/pksig/pksig_cllww12_z.py +142 -0
  146. charm/schemes/pksig/pksig_cyh.py +132 -0
  147. charm/schemes/pksig/pksig_dsa.py +76 -0
  148. charm/schemes/pksig/pksig_ecdsa.py +71 -0
  149. charm/schemes/pksig/pksig_hess.py +104 -0
  150. charm/schemes/pksig/pksig_hw.py +110 -0
  151. charm/schemes/pksig/pksig_lamport.py +63 -0
  152. charm/schemes/pksig/pksig_ps01.py +135 -0
  153. charm/schemes/pksig/pksig_ps02.py +124 -0
  154. charm/schemes/pksig/pksig_ps03.py +119 -0
  155. charm/schemes/pksig/pksig_rsa_hw09.py +206 -0
  156. charm/schemes/pksig/pksig_schnorr91.py +77 -0
  157. charm/schemes/pksig/pksig_waters.py +115 -0
  158. charm/schemes/pksig/pksig_waters05.py +121 -0
  159. charm/schemes/pksig/pksig_waters09.py +121 -0
  160. charm/schemes/pre_mg07.py +150 -0
  161. charm/schemes/prenc/pre_afgh06.py +126 -0
  162. charm/schemes/prenc/pre_bbs98.py +123 -0
  163. charm/schemes/prenc/pre_nal16.py +216 -0
  164. charm/schemes/protocol_a01.py +272 -0
  165. charm/schemes/protocol_ao00.py +215 -0
  166. charm/schemes/protocol_cns07.py +274 -0
  167. charm/schemes/protocol_schnorr91.py +125 -0
  168. charm/schemes/sigma1.py +64 -0
  169. charm/schemes/sigma2.py +129 -0
  170. charm/schemes/sigma3.py +126 -0
  171. charm/schemes/threshold/__init__.py +59 -0
  172. charm/schemes/threshold/dkls23_dkg.py +556 -0
  173. charm/schemes/threshold/dkls23_presign.py +1089 -0
  174. charm/schemes/threshold/dkls23_sign.py +761 -0
  175. charm/schemes/threshold/xrpl_wallet.py +967 -0
  176. charm/test/__init__.py +0 -0
  177. charm/test/adapters/__init__.py +0 -0
  178. charm/test/adapters/abenc_adapt_hybrid_test.py +29 -0
  179. charm/test/adapters/dabenc_adapt_hybrid_test.py +56 -0
  180. charm/test/adapters/ibenc_adapt_hybrid_test.py +36 -0
  181. charm/test/adapters/ibenc_adapt_identityhash_test.py +32 -0
  182. charm/test/adapters/kpabenc_adapt_hybrid_test.py +30 -0
  183. charm/test/benchmark/abenc_yllc15_bench.py +92 -0
  184. charm/test/benchmark/benchmark_test.py +148 -0
  185. charm/test/benchmark_threshold.py +260 -0
  186. charm/test/conftest.py +38 -0
  187. charm/test/fuzz/__init__.py +1 -0
  188. charm/test/fuzz/conftest.py +5 -0
  189. charm/test/fuzz/fuzz_policy_parser.py +76 -0
  190. charm/test/fuzz/fuzz_serialization.py +83 -0
  191. charm/test/schemes/__init__.py +0 -0
  192. charm/test/schemes/abenc/__init__.py +0 -0
  193. charm/test/schemes/abenc/abenc_bsw07_test.py +39 -0
  194. charm/test/schemes/abenc/abenc_dacmacs_yj14_test.py +16 -0
  195. charm/test/schemes/abenc/abenc_lsw08_test.py +33 -0
  196. charm/test/schemes/abenc/abenc_maabe_yj14_test.py +16 -0
  197. charm/test/schemes/abenc/abenc_tbpre_lww14_test.py +16 -0
  198. charm/test/schemes/abenc/abenc_waters09_test.py +38 -0
  199. charm/test/schemes/abenc/abenc_yllc15_test.py +74 -0
  200. charm/test/schemes/chamhash_adm05_test.py +31 -0
  201. charm/test/schemes/chamhash_rsa_hw09_test.py +29 -0
  202. charm/test/schemes/commit/__init__.py +0 -0
  203. charm/test/schemes/commit/commit_gs08_test.py +24 -0
  204. charm/test/schemes/commit/commit_pedersen92_test.py +26 -0
  205. charm/test/schemes/dabe_aw11_test.py +45 -0
  206. charm/test/schemes/encap_bchk05_test.py +21 -0
  207. charm/test/schemes/grpsig/__init__.py +0 -0
  208. charm/test/schemes/grpsig/groupsig_bgls04_test.py +35 -0
  209. charm/test/schemes/grpsig/groupsig_bgls04_var_test.py +39 -0
  210. charm/test/schemes/hibenc/__init__.py +0 -0
  211. charm/test/schemes/hibenc/hibenc_bb04_test.py +28 -0
  212. charm/test/schemes/ibenc/__init__.py +0 -0
  213. charm/test/schemes/ibenc/ibenc_bb03_test.py +26 -0
  214. charm/test/schemes/ibenc/ibenc_bf01_test.py +24 -0
  215. charm/test/schemes/ibenc/ibenc_ckrs09_test.py +25 -0
  216. charm/test/schemes/ibenc/ibenc_lsw08_test.py +31 -0
  217. charm/test/schemes/ibenc/ibenc_sw05_test.py +32 -0
  218. charm/test/schemes/ibenc/ibenc_waters05_test.py +31 -0
  219. charm/test/schemes/ibenc/ibenc_waters09_test.py +27 -0
  220. charm/test/schemes/pk_vrf_test.py +29 -0
  221. charm/test/schemes/pkenc/__init__.py +0 -0
  222. charm/test/schemes/pkenc_test.py +255 -0
  223. charm/test/schemes/pksig/__init__.py +0 -0
  224. charm/test/schemes/pksig_test.py +376 -0
  225. charm/test/schemes/rsa_alg_test.py +340 -0
  226. charm/test/schemes/threshold_test.py +1792 -0
  227. charm/test/serialize/__init__.py +0 -0
  228. charm/test/serialize/serialize_test.py +40 -0
  229. charm/test/toolbox/__init__.py +0 -0
  230. charm/test/toolbox/conversion_test.py +30 -0
  231. charm/test/toolbox/ecgroup_test.py +53 -0
  232. charm/test/toolbox/integer_arithmetic_test.py +441 -0
  233. charm/test/toolbox/paddingschemes_test.py +238 -0
  234. charm/test/toolbox/policy_parser_stress_test.py +969 -0
  235. charm/test/toolbox/secretshare_test.py +28 -0
  236. charm/test/toolbox/symcrypto_test.py +108 -0
  237. charm/test/toolbox/test_policy_expression.py +16 -0
  238. charm/test/vectors/__init__.py +1 -0
  239. charm/test/vectors/test_bls_vectors.py +289 -0
  240. charm/test/vectors/test_pedersen_vectors.py +315 -0
  241. charm/test/vectors/test_schnorr_vectors.py +368 -0
  242. charm/test/zkp_compiler/__init__.py +9 -0
  243. charm/test/zkp_compiler/benchmark_zkp.py +258 -0
  244. charm/test/zkp_compiler/test_and_proof.py +240 -0
  245. charm/test/zkp_compiler/test_batch_verify.py +248 -0
  246. charm/test/zkp_compiler/test_dleq_proof.py +264 -0
  247. charm/test/zkp_compiler/test_or_proof.py +231 -0
  248. charm/test/zkp_compiler/test_proof_serialization.py +121 -0
  249. charm/test/zkp_compiler/test_range_proof.py +241 -0
  250. charm/test/zkp_compiler/test_representation_proof.py +325 -0
  251. charm/test/zkp_compiler/test_schnorr_proof.py +221 -0
  252. charm/test/zkp_compiler/test_thread_safety.py +169 -0
  253. charm/test/zkp_compiler/test_zkp_parser.py +139 -0
  254. charm/toolbox/ABEnc.py +26 -0
  255. charm/toolbox/ABEncMultiAuth.py +66 -0
  256. charm/toolbox/ABEnumeric.py +800 -0
  257. charm/toolbox/Commit.py +24 -0
  258. charm/toolbox/DFA.py +89 -0
  259. charm/toolbox/FSA.py +1254 -0
  260. charm/toolbox/Hash.py +39 -0
  261. charm/toolbox/IBEnc.py +62 -0
  262. charm/toolbox/IBSig.py +64 -0
  263. charm/toolbox/PKEnc.py +66 -0
  264. charm/toolbox/PKSig.py +56 -0
  265. charm/toolbox/PREnc.py +32 -0
  266. charm/toolbox/ZKProof.py +289 -0
  267. charm/toolbox/__init__.py +0 -0
  268. charm/toolbox/bitstring.py +49 -0
  269. charm/toolbox/broadcast.py +220 -0
  270. charm/toolbox/conversion.py +100 -0
  271. charm/toolbox/eccurve.py +149 -0
  272. charm/toolbox/ecgroup.py +143 -0
  273. charm/toolbox/enum.py +60 -0
  274. charm/toolbox/hash_module.py +91 -0
  275. charm/toolbox/integergroup.py +323 -0
  276. charm/toolbox/iterate.py +22 -0
  277. charm/toolbox/matrixops.py +76 -0
  278. charm/toolbox/mpc_utils.py +296 -0
  279. charm/toolbox/msp.py +175 -0
  280. charm/toolbox/mta.py +985 -0
  281. charm/toolbox/node.py +120 -0
  282. charm/toolbox/ot/__init__.py +22 -0
  283. charm/toolbox/ot/base_ot.py +374 -0
  284. charm/toolbox/ot/dpf.py +642 -0
  285. charm/toolbox/ot/mpfss.py +228 -0
  286. charm/toolbox/ot/ot_extension.py +589 -0
  287. charm/toolbox/ot/silent_ot.py +378 -0
  288. charm/toolbox/paddingschemes.py +423 -0
  289. charm/toolbox/paddingschemes_test.py +238 -0
  290. charm/toolbox/pairingcurves.py +85 -0
  291. charm/toolbox/pairinggroup.py +186 -0
  292. charm/toolbox/policy_expression_spec.py +70 -0
  293. charm/toolbox/policytree.py +189 -0
  294. charm/toolbox/reCompiler.py +346 -0
  295. charm/toolbox/redundancyschemes.py +65 -0
  296. charm/toolbox/schemebase.py +188 -0
  297. charm/toolbox/secretshare.py +104 -0
  298. charm/toolbox/secretutil.py +174 -0
  299. charm/toolbox/securerandom.py +73 -0
  300. charm/toolbox/sigmaprotocol.py +46 -0
  301. charm/toolbox/specialprimes.py +45 -0
  302. charm/toolbox/symcrypto.py +279 -0
  303. charm/toolbox/threshold_sharing.py +553 -0
  304. charm/toolbox/xmlserialize.py +94 -0
  305. charm/toolbox/zknode.py +105 -0
  306. charm/zkp_compiler/__init__.py +89 -0
  307. charm/zkp_compiler/and_proof.py +460 -0
  308. charm/zkp_compiler/batch_verify.py +324 -0
  309. charm/zkp_compiler/dleq_proof.py +423 -0
  310. charm/zkp_compiler/or_proof.py +305 -0
  311. charm/zkp_compiler/range_proof.py +417 -0
  312. charm/zkp_compiler/representation_proof.py +466 -0
  313. charm/zkp_compiler/schnorr_proof.py +273 -0
  314. charm/zkp_compiler/thread_safe.py +150 -0
  315. charm/zkp_compiler/zk_demo.py +489 -0
  316. charm/zkp_compiler/zkp_factory.py +330 -0
  317. charm/zkp_compiler/zkp_generator.py +370 -0
  318. charm/zkp_compiler/zkparser.py +269 -0
  319. charm_crypto_framework-0.61.1.dist-info/METADATA +337 -0
  320. charm_crypto_framework-0.61.1.dist-info/RECORD +323 -0
  321. charm_crypto_framework-0.61.1.dist-info/WHEEL +5 -0
  322. charm_crypto_framework-0.61.1.dist-info/licenses/LICENSE.txt +165 -0
  323. 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
+ )