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,231 @@
1
+ """
2
+ Unit tests for OR Composition proof (CDS94) implementation.
3
+
4
+ Tests cover:
5
+ - Non-interactive OR proof generation and verification
6
+ - Witness indistinguishability property
7
+ - Serialization and deserialization
8
+ """
9
+
10
+ import unittest
11
+ from charm.toolbox.pairinggroup import PairingGroup, ZR, G1
12
+ from charm.zkp_compiler.or_proof import ORProof, ORProofData
13
+
14
+
15
+ class TestORProofNonInteractive(unittest.TestCase):
16
+ """Tests for non-interactive OR proof (CDS94)."""
17
+
18
+ def setUp(self):
19
+ """Set up test fixtures."""
20
+ self.group = PairingGroup('BN254')
21
+ self.g = self.group.random(G1)
22
+ # Create two public values with known discrete logs
23
+ self.x1 = self.group.random(ZR)
24
+ self.x2 = self.group.random(ZR)
25
+ self.h1 = self.g ** self.x1
26
+ self.h2 = self.g ** self.x2
27
+
28
+ def test_prove_first_statement(self):
29
+ """Test proving h1 = g^x (which=0)."""
30
+ proof = ORProof.prove_non_interactive(
31
+ self.group, self.g, self.h1, self.h2, self.x1, which=0
32
+ )
33
+
34
+ self.assertIsNotNone(proof)
35
+ self.assertIsNotNone(proof.commitment1)
36
+ self.assertIsNotNone(proof.commitment2)
37
+ self.assertIsNotNone(proof.challenge1)
38
+ self.assertIsNotNone(proof.challenge2)
39
+ self.assertIsNotNone(proof.response1)
40
+ self.assertIsNotNone(proof.response2)
41
+
42
+ result = ORProof.verify_non_interactive(
43
+ self.group, self.g, self.h1, self.h2, proof
44
+ )
45
+ self.assertTrue(result)
46
+
47
+ def test_prove_second_statement(self):
48
+ """Test proving h2 = g^x (which=1)."""
49
+ proof = ORProof.prove_non_interactive(
50
+ self.group, self.g, self.h1, self.h2, self.x2, which=1
51
+ )
52
+
53
+ self.assertIsNotNone(proof)
54
+ result = ORProof.verify_non_interactive(
55
+ self.group, self.g, self.h1, self.h2, proof
56
+ )
57
+ self.assertTrue(result)
58
+
59
+ def test_wrong_secret_fails(self):
60
+ """Test that wrong secret fails verification."""
61
+ wrong_x = self.group.random(ZR)
62
+ proof = ORProof.prove_non_interactive(
63
+ self.group, self.g, self.h1, self.h2, wrong_x, which=0
64
+ )
65
+
66
+ result = ORProof.verify_non_interactive(
67
+ self.group, self.g, self.h1, self.h2, proof
68
+ )
69
+ self.assertFalse(result)
70
+
71
+ def test_wrong_which_fails(self):
72
+ """Test that claiming wrong branch fails."""
73
+ # x1 is secret for h1, but claim it's for h2 (which=1)
74
+ proof = ORProof.prove_non_interactive(
75
+ self.group, self.g, self.h1, self.h2, self.x1, which=1
76
+ )
77
+
78
+ result = ORProof.verify_non_interactive(
79
+ self.group, self.g, self.h1, self.h2, proof
80
+ )
81
+ self.assertFalse(result)
82
+
83
+ def test_tampered_proof_fails(self):
84
+ """Test that tampered proof fails verification."""
85
+ proof = ORProof.prove_non_interactive(
86
+ self.group, self.g, self.h1, self.h2, self.x1, which=0
87
+ )
88
+
89
+ # Tamper with response1
90
+ tampered = ORProofData(
91
+ commitment1=proof.commitment1,
92
+ commitment2=proof.commitment2,
93
+ challenge1=proof.challenge1,
94
+ challenge2=proof.challenge2,
95
+ response1=proof.response1 + self.group.random(ZR),
96
+ response2=proof.response2,
97
+ proof_type=proof.proof_type
98
+ )
99
+
100
+ result = ORProof.verify_non_interactive(
101
+ self.group, self.g, self.h1, self.h2, tampered
102
+ )
103
+ self.assertFalse(result)
104
+
105
+ def test_challenges_sum_correctly(self):
106
+ """Test that c1 + c2 equals main challenge."""
107
+ proof = ORProof.prove_non_interactive(
108
+ self.group, self.g, self.h1, self.h2, self.x1, which=0
109
+ )
110
+
111
+ # Recompute expected challenge
112
+ expected_c = ORProof._compute_challenge_hash(
113
+ self.group, self.g, self.h1, self.h2,
114
+ proof.commitment1, proof.commitment2
115
+ )
116
+
117
+ # Verify c1 + c2 = c
118
+ actual_c = proof.challenge1 + proof.challenge2
119
+ self.assertEqual(expected_c, actual_c)
120
+
121
+
122
+ class TestORProofWitnessIndistinguishability(unittest.TestCase):
123
+ """Tests for witness indistinguishability property."""
124
+
125
+ def setUp(self):
126
+ """Set up test fixtures."""
127
+ self.group = PairingGroup('BN254')
128
+ self.g = self.group.random(G1)
129
+ self.x1 = self.group.random(ZR)
130
+ self.x2 = self.group.random(ZR)
131
+ self.h1 = self.g ** self.x1
132
+ self.h2 = self.g ** self.x2
133
+
134
+ def test_proofs_look_similar(self):
135
+ """Test that both branches produce valid-looking proofs."""
136
+ proof0 = ORProof.prove_non_interactive(
137
+ self.group, self.g, self.h1, self.h2, self.x1, which=0
138
+ )
139
+ proof1 = ORProof.prove_non_interactive(
140
+ self.group, self.g, self.h1, self.h2, self.x2, which=1
141
+ )
142
+
143
+ # Both proofs should have same structure
144
+ self.assertEqual(proof0.proof_type, proof1.proof_type)
145
+ self.assertEqual(proof0.proof_type, 'or')
146
+
147
+ # Both should be valid
148
+ result0 = ORProof.verify_non_interactive(
149
+ self.group, self.g, self.h1, self.h2, proof0
150
+ )
151
+ result1 = ORProof.verify_non_interactive(
152
+ self.group, self.g, self.h1, self.h2, proof1
153
+ )
154
+ self.assertTrue(result0)
155
+ self.assertTrue(result1)
156
+
157
+ def test_verifier_cannot_distinguish(self):
158
+ """Test that verifier accepts both without knowing which."""
159
+ # Generate multiple proofs from each branch
160
+ proofs = []
161
+ for _ in range(3):
162
+ proof0 = ORProof.prove_non_interactive(
163
+ self.group, self.g, self.h1, self.h2, self.x1, which=0
164
+ )
165
+ proof1 = ORProof.prove_non_interactive(
166
+ self.group, self.g, self.h1, self.h2, self.x2, which=1
167
+ )
168
+ proofs.extend([proof0, proof1])
169
+
170
+ # Verifier should accept all proofs identically
171
+ for proof in proofs:
172
+ result = ORProof.verify_non_interactive(
173
+ self.group, self.g, self.h1, self.h2, proof
174
+ )
175
+ self.assertTrue(result)
176
+
177
+
178
+ class TestORProofSerialization(unittest.TestCase):
179
+ """Tests for OR proof serialization."""
180
+
181
+ def setUp(self):
182
+ """Set up test fixtures."""
183
+ self.group = PairingGroup('BN254')
184
+ self.g = self.group.random(G1)
185
+ self.x = self.group.random(ZR)
186
+ self.h1 = self.g ** self.x
187
+ self.h2 = self.g ** self.group.random(ZR)
188
+
189
+ def test_serialization_roundtrip(self):
190
+ """Test serialize and deserialize proof."""
191
+ proof = ORProof.prove_non_interactive(
192
+ self.group, self.g, self.h1, self.h2, self.x, which=0
193
+ )
194
+
195
+ # Serialize
196
+ serialized = ORProof.serialize_proof(proof, self.group)
197
+ self.assertIsInstance(serialized, bytes)
198
+ self.assertGreater(len(serialized), 0)
199
+
200
+ # Deserialize
201
+ deserialized = ORProof.deserialize_proof(serialized, self.group)
202
+
203
+ # Check all fields match
204
+ self.assertEqual(proof.commitment1, deserialized.commitment1)
205
+ self.assertEqual(proof.commitment2, deserialized.commitment2)
206
+ self.assertEqual(proof.challenge1, deserialized.challenge1)
207
+ self.assertEqual(proof.challenge2, deserialized.challenge2)
208
+ self.assertEqual(proof.response1, deserialized.response1)
209
+ self.assertEqual(proof.response2, deserialized.response2)
210
+ self.assertEqual(proof.proof_type, deserialized.proof_type)
211
+
212
+ def test_serialized_proof_verifies(self):
213
+ """Test that deserialized proof still verifies."""
214
+ proof = ORProof.prove_non_interactive(
215
+ self.group, self.g, self.h1, self.h2, self.x, which=0
216
+ )
217
+
218
+ # Serialize and deserialize
219
+ serialized = ORProof.serialize_proof(proof, self.group)
220
+ deserialized = ORProof.deserialize_proof(serialized, self.group)
221
+
222
+ # Deserialized proof should verify
223
+ result = ORProof.verify_non_interactive(
224
+ self.group, self.g, self.h1, self.h2, deserialized
225
+ )
226
+ self.assertTrue(result)
227
+
228
+
229
+ if __name__ == "__main__":
230
+ unittest.main()
231
+
@@ -0,0 +1,121 @@
1
+ """
2
+ Unit tests for ZK proof serialization.
3
+
4
+ Tests cover:
5
+ - Serializing proofs to bytes
6
+ - Deserializing bytes back to proofs
7
+ - Roundtrip preservation
8
+ - Error handling for invalid data
9
+ """
10
+
11
+ import unittest
12
+ from charm.toolbox.pairinggroup import PairingGroup, ZR, G1
13
+ from charm.zkp_compiler.schnorr_proof import SchnorrProof, Proof
14
+
15
+
16
+ class TestProofSerialization(unittest.TestCase):
17
+ """Tests for proof serialization."""
18
+
19
+ def setUp(self):
20
+ """Set up test fixtures."""
21
+ self.group = PairingGroup('BN254')
22
+ self.g = self.group.random(G1)
23
+ self.x = self.group.random(ZR)
24
+ self.h = self.g ** self.x
25
+
26
+ def test_serialize_deserialize_roundtrip(self):
27
+ """Test that proof survives serialization roundtrip."""
28
+ # Generate proof
29
+ proof = SchnorrProof.prove_non_interactive(
30
+ self.group, self.g, self.h, self.x
31
+ )
32
+
33
+ # Serialize
34
+ data = SchnorrProof.serialize_proof(proof, self.group)
35
+ self.assertIsInstance(data, bytes)
36
+ self.assertGreater(len(data), 0)
37
+
38
+ # Deserialize
39
+ recovered = SchnorrProof.deserialize_proof(data, self.group)
40
+ self.assertIsNotNone(recovered)
41
+
42
+ # Verify recovered proof still works
43
+ result = SchnorrProof.verify_non_interactive(
44
+ self.group, self.g, self.h, recovered
45
+ )
46
+ self.assertTrue(result)
47
+
48
+ def test_serialized_proof_is_bytes(self):
49
+ """Test that serialization produces bytes."""
50
+ proof = SchnorrProof.prove_non_interactive(
51
+ self.group, self.g, self.h, self.x
52
+ )
53
+ data = SchnorrProof.serialize_proof(proof, self.group)
54
+ self.assertIsInstance(data, bytes)
55
+
56
+ def test_different_proofs_different_serialization(self):
57
+ """Test that different proofs produce different serialized data."""
58
+ proof1 = SchnorrProof.prove_non_interactive(
59
+ self.group, self.g, self.h, self.x
60
+ )
61
+ proof2 = SchnorrProof.prove_non_interactive(
62
+ self.group, self.g, self.h, self.x
63
+ )
64
+
65
+ data1 = SchnorrProof.serialize_proof(proof1, self.group)
66
+ data2 = SchnorrProof.serialize_proof(proof2, self.group)
67
+
68
+ # Different proofs should have different serializations
69
+ # (due to different random commitments)
70
+ self.assertNotEqual(data1, data2)
71
+
72
+ def test_deserialize_preserves_proof_type(self):
73
+ """Test that proof_type is preserved through serialization."""
74
+ proof = SchnorrProof.prove_non_interactive(
75
+ self.group, self.g, self.h, self.x
76
+ )
77
+
78
+ data = SchnorrProof.serialize_proof(proof, self.group)
79
+ recovered = SchnorrProof.deserialize_proof(data, self.group)
80
+
81
+ self.assertEqual(recovered.proof_type, proof.proof_type)
82
+
83
+ def test_serialization_with_different_groups(self):
84
+ """Test serialization works with different pairing groups."""
85
+ for curve in ['BN254', 'MNT224']:
86
+ with self.subTest(curve=curve):
87
+ group = PairingGroup(curve)
88
+ g = group.random(G1)
89
+ x = group.random(ZR)
90
+ h = g ** x
91
+
92
+ proof = SchnorrProof.prove_non_interactive(group, g, h, x)
93
+ data = SchnorrProof.serialize_proof(proof, group)
94
+ recovered = SchnorrProof.deserialize_proof(data, group)
95
+
96
+ result = SchnorrProof.verify_non_interactive(
97
+ group, g, h, recovered
98
+ )
99
+ self.assertTrue(result)
100
+
101
+
102
+ class TestProofSerializationErrors(unittest.TestCase):
103
+ """Tests for serialization error handling."""
104
+
105
+ def setUp(self):
106
+ self.group = PairingGroup('BN254')
107
+
108
+ def test_deserialize_invalid_data_fails(self):
109
+ """Test that invalid data raises an exception."""
110
+ with self.assertRaises(Exception):
111
+ SchnorrProof.deserialize_proof(b"not valid data", self.group)
112
+
113
+ def test_deserialize_empty_data_fails(self):
114
+ """Test that empty data raises an exception."""
115
+ with self.assertRaises(Exception):
116
+ SchnorrProof.deserialize_proof(b"", self.group)
117
+
118
+
119
+ if __name__ == "__main__":
120
+ unittest.main()
121
+
@@ -0,0 +1,241 @@
1
+ """
2
+ Unit tests for Range Proof implementation.
3
+
4
+ Tests cover:
5
+ - Basic range proofs with boundary values
6
+ - Different bit sizes for ranges
7
+ - Pedersen commitment creation and properties
8
+ - Proof serialization and deserialization
9
+ """
10
+
11
+ import unittest
12
+ from charm.toolbox.pairinggroup import PairingGroup, ZR, G1
13
+ from charm.zkp_compiler.range_proof import RangeProof, RangeProofData
14
+
15
+
16
+ class TestRangeProofBasic(unittest.TestCase):
17
+ """Tests for basic range proof functionality with 8-bit range."""
18
+
19
+ def setUp(self):
20
+ """Set up test fixtures."""
21
+ self.group = PairingGroup('BN254')
22
+ self.g = self.group.random(G1)
23
+ self.h = self.group.random(G1)
24
+ self.num_bits = 8 # Range [0, 256)
25
+
26
+ def test_value_zero(self):
27
+ """Prove 0 is in range [0, 2^8)."""
28
+ value = 0
29
+ randomness = self.group.random(ZR)
30
+ commitment = RangeProof.create_pedersen_commitment(
31
+ self.group, self.g, self.h, value, randomness
32
+ )
33
+ proof = RangeProof.prove(
34
+ self.group, self.g, self.h, value, randomness, self.num_bits
35
+ )
36
+ result = RangeProof.verify(self.group, self.g, self.h, commitment, proof)
37
+ self.assertTrue(result)
38
+
39
+ def test_value_one(self):
40
+ """Prove 1 is in range [0, 2^8)."""
41
+ value = 1
42
+ randomness = self.group.random(ZR)
43
+ commitment = RangeProof.create_pedersen_commitment(
44
+ self.group, self.g, self.h, value, randomness
45
+ )
46
+ proof = RangeProof.prove(
47
+ self.group, self.g, self.h, value, randomness, self.num_bits
48
+ )
49
+ result = RangeProof.verify(self.group, self.g, self.h, commitment, proof)
50
+ self.assertTrue(result)
51
+
52
+ def test_value_max(self):
53
+ """Prove 255 (max value) is in range [0, 2^8)."""
54
+ value = 255 # 2^8 - 1
55
+ randomness = self.group.random(ZR)
56
+ commitment = RangeProof.create_pedersen_commitment(
57
+ self.group, self.g, self.h, value, randomness
58
+ )
59
+ proof = RangeProof.prove(
60
+ self.group, self.g, self.h, value, randomness, self.num_bits
61
+ )
62
+ result = RangeProof.verify(self.group, self.g, self.h, commitment, proof)
63
+ self.assertTrue(result)
64
+
65
+ def test_value_middle(self):
66
+ """Prove 42 is in range [0, 2^8)."""
67
+ value = 42
68
+ randomness = self.group.random(ZR)
69
+ commitment = RangeProof.create_pedersen_commitment(
70
+ self.group, self.g, self.h, value, randomness
71
+ )
72
+ proof = RangeProof.prove(
73
+ self.group, self.g, self.h, value, randomness, self.num_bits
74
+ )
75
+ result = RangeProof.verify(self.group, self.g, self.h, commitment, proof)
76
+ self.assertTrue(result)
77
+
78
+ def test_value_out_of_range_fails(self):
79
+ """Value >= 2^n should fail."""
80
+ value = 256 # 2^8, out of range
81
+ randomness = self.group.random(ZR)
82
+ with self.assertRaises(ValueError):
83
+ RangeProof.prove(
84
+ self.group, self.g, self.h, value, randomness, self.num_bits
85
+ )
86
+
87
+
88
+ class TestRangeProofDifferentBitSizes(unittest.TestCase):
89
+ """Tests for range proofs with different bit sizes."""
90
+
91
+ def setUp(self):
92
+ """Set up test fixtures."""
93
+ self.group = PairingGroup('BN254')
94
+ self.g = self.group.random(G1)
95
+ self.h = self.group.random(G1)
96
+
97
+ def test_4_bit_range(self):
98
+ """Test range [0, 16) with 4-bit proof."""
99
+ num_bits = 4
100
+ value = 15 # Max value in range
101
+ randomness = self.group.random(ZR)
102
+ commitment = RangeProof.create_pedersen_commitment(
103
+ self.group, self.g, self.h, value, randomness
104
+ )
105
+ proof = RangeProof.prove(
106
+ self.group, self.g, self.h, value, randomness, num_bits
107
+ )
108
+ self.assertEqual(proof.num_bits, 4)
109
+ result = RangeProof.verify(self.group, self.g, self.h, commitment, proof)
110
+ self.assertTrue(result)
111
+
112
+ def test_8_bit_range(self):
113
+ """Test range [0, 256) with 8-bit proof."""
114
+ num_bits = 8
115
+ value = 200
116
+ randomness = self.group.random(ZR)
117
+ commitment = RangeProof.create_pedersen_commitment(
118
+ self.group, self.g, self.h, value, randomness
119
+ )
120
+ proof = RangeProof.prove(
121
+ self.group, self.g, self.h, value, randomness, num_bits
122
+ )
123
+ self.assertEqual(proof.num_bits, 8)
124
+ result = RangeProof.verify(self.group, self.g, self.h, commitment, proof)
125
+ self.assertTrue(result)
126
+
127
+ def test_16_bit_range(self):
128
+ """Test range [0, 65536) with 16-bit proof."""
129
+ num_bits = 16
130
+ value = 50000
131
+ randomness = self.group.random(ZR)
132
+ commitment = RangeProof.create_pedersen_commitment(
133
+ self.group, self.g, self.h, value, randomness
134
+ )
135
+ proof = RangeProof.prove(
136
+ self.group, self.g, self.h, value, randomness, num_bits
137
+ )
138
+ self.assertEqual(proof.num_bits, 16)
139
+ result = RangeProof.verify(self.group, self.g, self.h, commitment, proof)
140
+ self.assertTrue(result)
141
+
142
+
143
+ class TestRangeProofPedersenCommitment(unittest.TestCase):
144
+ """Tests for Pedersen commitment creation and properties."""
145
+
146
+ def setUp(self):
147
+ """Set up test fixtures."""
148
+ self.group = PairingGroup('BN254')
149
+ self.g = self.group.random(G1)
150
+ self.h = self.group.random(G1)
151
+
152
+ def test_create_commitment(self):
153
+ """Test commitment creation helper."""
154
+ value = 42
155
+ randomness = self.group.random(ZR)
156
+ commitment = RangeProof.create_pedersen_commitment(
157
+ self.group, self.g, self.h, value, randomness
158
+ )
159
+ # Verify commitment is C = g^v * h^r
160
+ v = self.group.init(ZR, value)
161
+ expected = (self.g ** v) * (self.h ** randomness)
162
+ self.assertEqual(commitment, expected)
163
+
164
+ def test_commitment_hiding(self):
165
+ """Same value, different randomness = different commitment."""
166
+ value = 42
167
+ r1 = self.group.random(ZR)
168
+ r2 = self.group.random(ZR)
169
+ c1 = RangeProof.create_pedersen_commitment(
170
+ self.group, self.g, self.h, value, r1
171
+ )
172
+ c2 = RangeProof.create_pedersen_commitment(
173
+ self.group, self.g, self.h, value, r2
174
+ )
175
+ # Different randomness should produce different commitments
176
+ self.assertNotEqual(c1, c2)
177
+
178
+ def test_commitment_binding(self):
179
+ """Commitment is binding - different values produce different commitments."""
180
+ r = self.group.random(ZR)
181
+ c1 = RangeProof.create_pedersen_commitment(
182
+ self.group, self.g, self.h, 42, r
183
+ )
184
+ c2 = RangeProof.create_pedersen_commitment(
185
+ self.group, self.g, self.h, 43, r
186
+ )
187
+ # Different values with same randomness should produce different commitments
188
+ self.assertNotEqual(c1, c2)
189
+
190
+
191
+ class TestRangeProofSerialization(unittest.TestCase):
192
+ """Tests for proof serialization and deserialization."""
193
+
194
+ def setUp(self):
195
+ """Set up test fixtures."""
196
+ self.group = PairingGroup('BN254')
197
+ self.g = self.group.random(G1)
198
+ self.h = self.group.random(G1)
199
+ self.num_bits = 4 # Use small bit size for fast tests
200
+
201
+ def test_serialization_roundtrip(self):
202
+ """Serialize and deserialize proof."""
203
+ value = 10
204
+ randomness = self.group.random(ZR)
205
+ proof = RangeProof.prove(
206
+ self.group, self.g, self.h, value, randomness, self.num_bits
207
+ )
208
+ # Serialize
209
+ serialized = RangeProof.serialize_proof(proof, self.group)
210
+ self.assertIsInstance(serialized, bytes)
211
+ # Deserialize
212
+ deserialized = RangeProof.deserialize_proof(serialized, self.group)
213
+ # Check structure is preserved
214
+ self.assertEqual(deserialized.num_bits, proof.num_bits)
215
+ self.assertEqual(deserialized.proof_type, proof.proof_type)
216
+ self.assertEqual(len(deserialized.bit_commitments), len(proof.bit_commitments))
217
+ self.assertEqual(len(deserialized.bit_proofs), len(proof.bit_proofs))
218
+
219
+ def test_serialized_proof_verifies(self):
220
+ """Deserialized proof still verifies."""
221
+ value = 12
222
+ randomness = self.group.random(ZR)
223
+ commitment = RangeProof.create_pedersen_commitment(
224
+ self.group, self.g, self.h, value, randomness
225
+ )
226
+ proof = RangeProof.prove(
227
+ self.group, self.g, self.h, value, randomness, self.num_bits
228
+ )
229
+ # Serialize and deserialize
230
+ serialized = RangeProof.serialize_proof(proof, self.group)
231
+ deserialized = RangeProof.deserialize_proof(serialized, self.group)
232
+ # Verify deserialized proof
233
+ result = RangeProof.verify(
234
+ self.group, self.g, self.h, commitment, deserialized
235
+ )
236
+ self.assertTrue(result)
237
+
238
+
239
+ if __name__ == "__main__":
240
+ unittest.main()
241
+