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,417 @@
1
+ """
2
+ Range Proof implementation using bit decomposition.
3
+
4
+ This module provides a Zero-Knowledge Range Proof that proves a committed
5
+ value lies within a range [0, 2^n) without revealing the value itself.
6
+
7
+ === What This Proves ===
8
+ Given a Pedersen commitment C = g^v * h^r, the range proof proves that the
9
+ committed value v is in the range [0, 2^n) without revealing v or r.
10
+
11
+ === Bit Decomposition Approach ===
12
+ This implementation uses bit decomposition with O(n) proof size where n is
13
+ the number of bits in the range. The approach works as follows:
14
+
15
+ 1. Decompose the value v into n bits: v = b0 + 2*b1 + 4*b2 + ... + 2^(n-1)*b_{n-1}
16
+ 2. For each bit bi:
17
+ - Generate random ri
18
+ - Create bit commitment: Ci = g^bi * h^ri
19
+ - Create OR proof that bi ∈ {0, 1}:
20
+ Prove (Ci = h^ri) OR (Ci = g * h^ri)
21
+ 3. Prove that the weighted sum of bit commitments equals the original commitment:
22
+ - Product of Ci^(2^i) should equal C (with appropriate randomness adjustment)
23
+
24
+ === Security Properties ===
25
+ - Zero-Knowledge: Verifier learns nothing about v except that v ∈ [0, 2^n)
26
+ - Soundness: Prover cannot convince verifier of a false statement (except with
27
+ negligible probability)
28
+ - Completeness: Honest prover with valid v always convinces verifier
29
+
30
+ === Use Cases ===
31
+ 1. Confidential Transactions: Prove transaction amounts are non-negative
32
+ 2. Age Verification: Prove age >= 18 without revealing exact age
33
+ 3. Voting: Prove vote value is in valid range (e.g., 0 or 1)
34
+ 4. Auctions: Prove bid is within allowed range
35
+ 5. Credit Scoring: Prove score is above threshold without revealing exact score
36
+
37
+ === Limitations ===
38
+ This bit decomposition approach has O(n) proof size where n is the number of
39
+ bits. For logarithmic proof size, consider Bulletproofs which achieve O(log n)
40
+ proof size using inner product arguments.
41
+
42
+ Usage Example:
43
+ >>> group = PairingGroup('BN254')
44
+ >>> g, h = group.random(G1), group.random(G1)
45
+ >>>
46
+ >>> # Prove value is in range [0, 2^8) = [0, 256)
47
+ >>> value = 42
48
+ >>> randomness = group.random(ZR)
49
+ >>> commitment = RangeProof.create_pedersen_commitment(group, g, h, value, randomness)
50
+ >>> proof = RangeProof.prove(group, g, h, value, randomness, num_bits=8)
51
+ >>> valid = RangeProof.verify(group, g, h, commitment, proof)
52
+ >>> assert valid
53
+ """
54
+
55
+ from typing import Any, List, Dict
56
+
57
+ from charm.toolbox.pairinggroup import PairingGroup, ZR, G1
58
+ from charm.core.engine.util import objectToBytes, bytesToObject
59
+ import logging
60
+
61
+ logger = logging.getLogger(__name__)
62
+
63
+
64
+ class RangeProofData:
65
+ """Container for Range Proof data.
66
+
67
+ Holds all components of a range proof including bit commitments,
68
+ bit proofs (OR proofs), and the sum proof.
69
+ """
70
+
71
+ def __init__(self, bit_commitments: List[Any], bit_proofs: List[Dict[str, Any]], sum_proof: Dict[str, Any], num_bits: int, proof_type: str = 'range') -> None:
72
+ """
73
+ Initialize a range proof.
74
+
75
+ Args:
76
+ bit_commitments: List of commitments to each bit [C0, C1, ..., C_{n-1}]
77
+ bit_proofs: List of OR proofs proving each bit is 0 or 1
78
+ sum_proof: Proof that sum of bits equals the committed value
79
+ num_bits: Number of bits in the range (range is [0, 2^num_bits))
80
+ proof_type: Type identifier for the proof
81
+ """
82
+ self.bit_commitments = bit_commitments
83
+ self.bit_proofs = bit_proofs
84
+ self.sum_proof = sum_proof
85
+ self.num_bits = num_bits
86
+ self.proof_type = proof_type
87
+
88
+
89
+ class RangeProof:
90
+ """
91
+ Zero-Knowledge Range Proof using Bit Decomposition.
92
+
93
+ Proves that a Pedersen commitment C = g^v * h^r commits to a value v
94
+ in the range [0, 2^n) without revealing v.
95
+
96
+ The proof consists of:
97
+ 1. n bit commitments Ci = g^bi * h^ri
98
+ 2. n OR proofs showing each bi ∈ {0, 1}
99
+ 3. A sum proof showing that sum(2^i * bi) = v
100
+ """
101
+
102
+ @classmethod
103
+ def create_pedersen_commitment(cls, group, g, h, value, randomness):
104
+ """
105
+ Create a Pedersen commitment C = g^v * h^r.
106
+
107
+ Args:
108
+ group: The pairing group
109
+ g: First generator (for value)
110
+ h: Second generator (for randomness)
111
+ value: The value to commit to (integer or ZR element)
112
+ randomness: The randomness r (ZR element)
113
+
114
+ Returns:
115
+ Pedersen commitment C = g^v * h^r
116
+ """
117
+ if isinstance(value, int):
118
+ v = group.init(ZR, value)
119
+ else:
120
+ v = value
121
+ return (g ** v) * (h ** randomness)
122
+
123
+ @classmethod
124
+ def _create_bit_or_proof(cls, group, g, h, bit_commitment, bit, bit_randomness):
125
+ """
126
+ Create simplified OR proof that bit_commitment commits to 0 or 1.
127
+
128
+ Proves: (Ci = h^ri AND bi=0) OR (Ci = g * h^ri AND bi=1)
129
+
130
+ This uses a simplified Sigma-OR protocol (Cramer-Damgård-Schoenmakers).
131
+ """
132
+ # Generate random values for the proof
133
+ if bit == 0:
134
+ # We know bi = 0, so Ci = h^ri
135
+ # Real proof for branch 0, simulate branch 1
136
+ r0 = group.random(ZR)
137
+ a0 = h ** r0 # Real commitment for branch 0
138
+
139
+ # Simulate branch 1 (pretend Ci = g * h^ri but we don't know ri)
140
+ c1 = group.random(ZR)
141
+ z1 = group.random(ZR)
142
+ # a1 = g^z1 * h^z1 / (Ci/g)^c1 = g^z1 * h^z1 * g^c1 / Ci^c1
143
+ Ci_over_g = bit_commitment * (g ** (-group.init(ZR, 1)))
144
+ a1 = (h ** z1) * (Ci_over_g ** (-c1))
145
+
146
+ # Compute overall challenge
147
+ data = (objectToBytes(bit_commitment, group) +
148
+ objectToBytes(a0, group) + objectToBytes(a1, group))
149
+ c = group.hash(data, ZR)
150
+
151
+ # c0 = c - c1
152
+ c0 = c - c1
153
+ # z0 = r0 + c0 * ri
154
+ z0 = r0 + c0 * bit_randomness
155
+ else:
156
+ # We know bi = 1, so Ci = g * h^ri
157
+ # Simulate branch 0, real proof for branch 1
158
+ c0 = group.random(ZR)
159
+ z0 = group.random(ZR)
160
+ # a0 = h^z0 / Ci^c0
161
+ a0 = (h ** z0) * (bit_commitment ** (-c0))
162
+
163
+ # Real proof for branch 1
164
+ r1 = group.random(ZR)
165
+ Ci_over_g = bit_commitment * (g ** (-group.init(ZR, 1)))
166
+ a1 = h ** r1 # Real commitment for branch 1
167
+
168
+ # Compute overall challenge
169
+ data = (objectToBytes(bit_commitment, group) +
170
+ objectToBytes(a0, group) + objectToBytes(a1, group))
171
+ c = group.hash(data, ZR)
172
+
173
+ # c1 = c - c0
174
+ c1 = c - c0
175
+ # z1 = r1 + c1 * ri
176
+ z1 = r1 + c1 * bit_randomness
177
+
178
+ return {
179
+ 'a0': a0, 'a1': a1,
180
+ 'c0': c0, 'c1': c1,
181
+ 'z0': z0, 'z1': z1
182
+ }
183
+
184
+ @classmethod
185
+ def _verify_bit_or_proof(cls, group, g, h, bit_commitment, proof):
186
+ """
187
+ Verify OR proof that bit_commitment commits to 0 or 1.
188
+
189
+ Returns:
190
+ True if proof is valid, False otherwise
191
+ """
192
+ a0, a1 = proof['a0'], proof['a1']
193
+ c0, c1 = proof['c0'], proof['c1']
194
+ z0, z1 = proof['z0'], proof['z1']
195
+
196
+ # Recompute challenge
197
+ data = (objectToBytes(bit_commitment, group) +
198
+ objectToBytes(a0, group) + objectToBytes(a1, group))
199
+ c = group.hash(data, ZR)
200
+
201
+ # Verify c = c0 + c1
202
+ if c != c0 + c1:
203
+ return False
204
+
205
+ # Verify branch 0: h^z0 == a0 * Ci^c0 (if bi = 0, Ci = h^ri)
206
+ lhs0 = h ** z0
207
+ rhs0 = a0 * (bit_commitment ** c0)
208
+ if lhs0 != rhs0:
209
+ return False
210
+
211
+ # Verify branch 1: h^z1 == a1 * (Ci/g)^c1 (if bi = 1, Ci = g * h^ri)
212
+ Ci_over_g = bit_commitment * (g ** (-group.init(ZR, 1)))
213
+ lhs1 = h ** z1
214
+ rhs1 = a1 * (Ci_over_g ** c1)
215
+ if lhs1 != rhs1:
216
+ return False
217
+
218
+ return True
219
+
220
+ @classmethod
221
+ def prove(cls, group: PairingGroup, g: Any, h: Any, value: int, randomness: Any, num_bits: int = 32) -> 'RangeProofData':
222
+ """
223
+ Generate a range proof that value is in [0, 2^num_bits).
224
+
225
+ Args:
226
+ group: The pairing group
227
+ g: First generator for Pedersen commitment
228
+ h: Second generator for Pedersen commitment
229
+ value: The secret value to prove is in range (integer)
230
+ randomness: The randomness used in the original commitment
231
+ num_bits: Number of bits defining the range [0, 2^num_bits)
232
+
233
+ Returns:
234
+ RangeProofData object containing the complete proof
235
+
236
+ Raises:
237
+ ValueError: If value is not in the valid range
238
+ """
239
+ # Validate value is in range
240
+ if not isinstance(value, int):
241
+ raise ValueError("Value must be an integer")
242
+ if value < 0 or value >= (1 << num_bits):
243
+ raise ValueError(f"Value {value} not in range [0, 2^{num_bits})")
244
+
245
+ # Step 1: Decompose value into bits
246
+ bits = [(value >> i) & 1 for i in range(num_bits)]
247
+
248
+ # Step 2: Generate random values for bit commitments
249
+ # We need: sum(2^i * ri) = r (original randomness)
250
+ # So we pick random r0, r1, ..., r_{n-2} and compute r_{n-1}
251
+ bit_randomness = [group.random(ZR) for _ in range(num_bits - 1)]
252
+
253
+ # Compute last randomness so weighted sum equals original randomness
254
+ # r = sum(2^i * ri), so r_{n-1} = (r - sum(2^i * ri for i < n-1)) / 2^{n-1}
255
+ partial_sum = group.init(ZR, 0)
256
+ for i in range(num_bits - 1):
257
+ weight = group.init(ZR, 1 << i)
258
+ partial_sum = partial_sum + weight * bit_randomness[i]
259
+
260
+ last_weight = group.init(ZR, 1 << (num_bits - 1))
261
+ last_randomness = (randomness - partial_sum) * (last_weight ** (-1))
262
+ bit_randomness.append(last_randomness)
263
+
264
+ # Step 3: Create bit commitments Ci = g^bi * h^ri
265
+ bit_commitments = []
266
+ for i in range(num_bits):
267
+ bi = group.init(ZR, bits[i])
268
+ Ci = (g ** bi) * (h ** bit_randomness[i])
269
+ bit_commitments.append(Ci)
270
+
271
+ # Step 4: Create OR proofs for each bit
272
+ bit_proofs = []
273
+ for i in range(num_bits):
274
+ proof = cls._create_bit_or_proof(
275
+ group, g, h, bit_commitments[i], bits[i], bit_randomness[i]
276
+ )
277
+ bit_proofs.append(proof)
278
+
279
+ # Step 5: Create sum proof (commitment consistency)
280
+ # Product of Ci^(2^i) should equal C = g^v * h^r
281
+ # This is implicitly verified by checking bit OR proofs and the
282
+ # commitment structure, so we include a signature/hash for binding
283
+ sum_data = b''
284
+ for i, Ci in enumerate(bit_commitments):
285
+ sum_data += objectToBytes(Ci, group)
286
+ sum_proof = {
287
+ 'binding_hash': group.hash(sum_data, ZR)
288
+ }
289
+
290
+ logger.debug("Generated range proof for %d bits", num_bits)
291
+ return RangeProofData(
292
+ bit_commitments=bit_commitments,
293
+ bit_proofs=bit_proofs,
294
+ sum_proof=sum_proof,
295
+ num_bits=num_bits,
296
+ proof_type='range'
297
+ )
298
+
299
+ @classmethod
300
+ def verify(cls, group: PairingGroup, g: Any, h: Any, commitment: Any, proof: 'RangeProofData') -> bool:
301
+ """
302
+ Verify a range proof.
303
+
304
+ Checks that the commitment C commits to a value in [0, 2^num_bits).
305
+
306
+ Args:
307
+ group: The pairing group
308
+ g: First generator for Pedersen commitment
309
+ h: Second generator for Pedersen commitment
310
+ commitment: The Pedersen commitment C = g^v * h^r
311
+ proof: RangeProofData object containing the proof
312
+
313
+ Returns:
314
+ True if proof is valid, False otherwise
315
+
316
+ Security Notes:
317
+ - Validates proof structure before verification
318
+ - Verifies each bit commitment and OR proof
319
+ - Checks commitment reconstruction for consistency
320
+ """
321
+ # Security: Validate proof structure
322
+ required_attrs = ['num_bits', 'bit_commitments', 'bit_proofs']
323
+ for attr in required_attrs:
324
+ if not hasattr(proof, attr):
325
+ logger.warning("Invalid Range proof structure: missing '%s'. Ensure proof was created with RangeProof.prove()", attr)
326
+ return False
327
+
328
+ num_bits = proof.num_bits
329
+
330
+ # Validate proof structure
331
+ if len(proof.bit_commitments) != num_bits:
332
+ logger.debug("Invalid number of bit commitments")
333
+ return False
334
+ if len(proof.bit_proofs) != num_bits:
335
+ logger.debug("Invalid number of bit proofs")
336
+ return False
337
+
338
+ # Step 1: Verify each bit OR proof
339
+ for i in range(num_bits):
340
+ if not cls._verify_bit_or_proof(
341
+ group, g, h, proof.bit_commitments[i], proof.bit_proofs[i]
342
+ ):
343
+ logger.debug("Bit OR proof %d failed", i)
344
+ return False
345
+
346
+ # Step 2: Verify that weighted product of bit commitments equals C
347
+ # Product of Ci^(2^i) should equal C
348
+ # This works because: prod(Ci^(2^i)) = prod((g^bi * h^ri)^(2^i))
349
+ # = g^(sum(2^i * bi)) * h^(sum(2^i * ri))
350
+ # = g^v * h^r = C
351
+ reconstructed = None
352
+ for i in range(num_bits):
353
+ weight = group.init(ZR, 1 << i)
354
+ weighted_commitment = proof.bit_commitments[i] ** weight
355
+ if reconstructed is None:
356
+ reconstructed = weighted_commitment
357
+ else:
358
+ reconstructed = reconstructed * weighted_commitment
359
+
360
+ if reconstructed != commitment:
361
+ logger.debug("Commitment reconstruction failed")
362
+ return False
363
+
364
+ # Step 3: Verify sum proof binding hash
365
+ sum_data = b''
366
+ for Ci in proof.bit_commitments:
367
+ sum_data += objectToBytes(Ci, group)
368
+ expected_hash = group.hash(sum_data, ZR)
369
+ if proof.sum_proof.get('binding_hash') != expected_hash:
370
+ logger.debug("Sum proof binding hash mismatch")
371
+ return False
372
+
373
+ logger.debug("Range proof verification successful")
374
+ return True
375
+
376
+ @classmethod
377
+ def serialize_proof(cls, proof: 'RangeProofData', group: PairingGroup) -> bytes:
378
+ """
379
+ Serialize proof to bytes using Charm utilities.
380
+
381
+ Args:
382
+ proof: RangeProofData object to serialize
383
+ group: The pairing group
384
+
385
+ Returns:
386
+ Bytes representation of the proof
387
+ """
388
+ proof_dict = {
389
+ 'bit_commitments': proof.bit_commitments,
390
+ 'bit_proofs': proof.bit_proofs,
391
+ 'sum_proof': proof.sum_proof,
392
+ 'num_bits': proof.num_bits,
393
+ 'proof_type': proof.proof_type
394
+ }
395
+ return objectToBytes(proof_dict, group)
396
+
397
+ @classmethod
398
+ def deserialize_proof(cls, data: bytes, group: PairingGroup) -> 'RangeProofData':
399
+ """
400
+ Deserialize bytes to proof.
401
+
402
+ Args:
403
+ data: Bytes to deserialize
404
+ group: The pairing group
405
+
406
+ Returns:
407
+ RangeProofData object
408
+ """
409
+ proof_dict = bytesToObject(data, group)
410
+ return RangeProofData(
411
+ bit_commitments=proof_dict['bit_commitments'],
412
+ bit_proofs=proof_dict['bit_proofs'],
413
+ sum_proof=proof_dict['sum_proof'],
414
+ num_bits=proof_dict['num_bits'],
415
+ proof_type=proof_dict.get('proof_type', 'range')
416
+ )
417
+