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,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
+ )