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,2094 @@
1
+ /*
2
+ * Charm-Crypto is a framework for rapidly prototyping cryptosystems.
3
+ *
4
+ * Charm-Crypto is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2.1 of the License, or (at your option) any later version.
8
+ *
9
+ * Charm-Crypto is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public License
15
+ * along with Charm-Crypto. If not, see <http://www.gnu.org/licenses/>.
16
+ *
17
+ * Please contact the charm-crypto dev team at support@charm-crypto.com
18
+ * for any questions.
19
+ */
20
+
21
+ /*
22
+ * @file pairingmodule2.c
23
+ *
24
+ * @brief charm interface over MIRACL's pairing-based operations
25
+ *
26
+ * @author jakinye3@jhu.edu
27
+ * @remark this version of the pairing module uses the MIRACL library (www.shamus.ie).
28
+ * At the moment, only useful for academic purposes and should be treated as such.
29
+ * To build into Charm, you'll need to acquire the MIRACL source and compile with the
30
+ * build script located in the miracl dir. See the online documentation at charm-crypto.com
31
+ * for how to install.
32
+ *
33
+ ************************************************************************/
34
+
35
+ #include "pairingmodule2.h"
36
+
37
+ /*
38
+ * Python 3.13+ made Py_IsFinalizing() public and removed _Py_IsFinalizing().
39
+ * For older versions, we need to use the private _Py_IsFinalizing().
40
+ */
41
+ #if PY_MINOR_VERSION >= 13
42
+ #define CHARM_PY_IS_FINALIZING() Py_IsFinalizing()
43
+ #else
44
+ #define CHARM_PY_IS_FINALIZING() _Py_IsFinalizing()
45
+ #endif
46
+
47
+ int exp_rule(Group_t lhs, Group_t rhs)
48
+ {
49
+ if(lhs == pyZR_t && rhs == pyZR_t) return TRUE;
50
+ if(lhs == pyG1_t && rhs == pyZR_t) return TRUE;
51
+ if(lhs == pyG2_t && rhs == pyZR_t) return TRUE;
52
+ if(lhs == pyGT_t && rhs == pyZR_t) return TRUE;
53
+ return FALSE; /* Fail all other cases */
54
+ }
55
+
56
+ int mul_rule(Group_t lhs, Group_t rhs)
57
+ {
58
+ if(lhs == rhs) return TRUE;
59
+ if(lhs == pyZR_t || rhs == pyZR_t) return TRUE;
60
+ return FALSE; /* Fail all other cases */
61
+ }
62
+
63
+ int add_rule(Group_t lhs, Group_t rhs)
64
+ {
65
+ if(lhs == rhs && lhs != pyGT_t) return TRUE;
66
+ return FALSE; /* Fail all other cases */
67
+ }
68
+
69
+ int sub_rule(Group_t lhs, Group_t rhs)
70
+ {
71
+ if(lhs == rhs && lhs != pyGT_t) return TRUE;
72
+ return FALSE; /* Fail all other cases */
73
+ }
74
+
75
+ int div_rule(Group_t lhs, Group_t rhs)
76
+ {
77
+ if(lhs == rhs) return TRUE;
78
+ return FALSE; /* Fail all other cases */
79
+ }
80
+
81
+ int pair_rule(Group_t lhs, Group_t rhs)
82
+ {
83
+ if(lhs == pyG1_t && rhs == pyG2_t) return TRUE;
84
+ else if(lhs == pyG2_t && rhs == pyG1_t) return TRUE;
85
+ return FALSE; /* Fall all other cases : assume MNT? */
86
+ }
87
+
88
+ int check_type(Group_t type) {
89
+ if(type == pyZR_t || type == pyG1_t || type == pyG2_t || type == pyGT_t) return TRUE;
90
+ return FALSE;
91
+ }
92
+
93
+ #define ERROR_TYPE(operand, ...) "unsupported "#operand" operand types: "#__VA_ARGS__
94
+
95
+ #define UNARY(f, m, n) \
96
+ static PyObject *f(PyObject *v) { \
97
+ if(PyElement_Check(v)) { \
98
+ Element *obj1 = (Element *) v; \
99
+ return (n)(obj1); \
100
+ } return NULL; \
101
+ }
102
+
103
+ #define BINARY(f, m, n) \
104
+ static PyObject *f(PyObject *v, PyObject *w) { \
105
+ Element *obj1 = NULL, *obj2 = NULL; \
106
+ int obj1_long = FALSE, obj2_long = FALSE; \
107
+ debug("Performing the '%s' operation.\n", __func__); \
108
+ if(PyElement_Check(v)) { \
109
+ obj1 = (Element *) v; } \
110
+ else if(PyNumber_Check(v)) { obj1 = convertToZR(v, w); obj1_long = TRUE; } \
111
+ else { PyErr_SetString(ElementError, ERROR_TYPE(left, int,bytes,str)); \
112
+ return NULL; } \
113
+ if(PyElement_Check(w)) { \
114
+ obj2 = (Element *) w; } \
115
+ else if(PyNumber_Check(w)) { obj2 = convertToZR(w, v); obj2_long = TRUE; } \
116
+ else { PyErr_SetString(ElementError, ERROR_TYPE(right, int,bytes,str)); \
117
+ return NULL; } \
118
+ if(Check_Types(obj1->element_type, obj2->element_type, m)) \
119
+ return (n)(obj1, obj2); \
120
+ return NULL; \
121
+ }
122
+
123
+ PyObject *mpzToLongObj(mpz_t m) {
124
+ /* borrowed from gmpy - then modified */
125
+ int size = (mpz_sizeinbase(m, 2) + PyLong_SHIFT - 1) / PyLong_SHIFT;
126
+ int i, isNeg = (mpz_sgn(m) < 0) ? TRUE : FALSE;
127
+ mpz_t temp;
128
+ PyLongObject *l = _PyLong_New(size);
129
+ if (!l)
130
+ return NULL;
131
+ mpz_init_set(temp, m);
132
+ for (i = 0; i < size; i++) {
133
+ l->ob_digit[i] = (digit)(mpz_get_ui(temp) & PyLong_MASK);
134
+ mpz_fdiv_q_2exp(temp, temp, PyLong_SHIFT);
135
+ }
136
+ i = size;
137
+ while ((i > 0) && (l->ob_digit[i - 1] == 0))
138
+ i--;
139
+ if(isNeg) {
140
+ Py_SIZE(l) = -i;
141
+ }
142
+ else {
143
+ Py_SIZE(l) = i;
144
+ }
145
+ mpz_clear(temp);
146
+ return (PyObject *) l;
147
+ }
148
+
149
+ void longObjToMPZ (mpz_t m, PyLongObject * p)
150
+ {
151
+ int size, i, tmp = Py_SIZE(p);
152
+ int isNeg = FALSE;
153
+ mpz_t temp, temp2;
154
+ mpz_init (temp);
155
+ mpz_init (temp2);
156
+ if (tmp > 0)
157
+ size = tmp;
158
+ else {
159
+ size = -tmp;
160
+ isNeg = TRUE;
161
+ }
162
+ mpz_set_ui (m, 0);
163
+ for (i = 0; i < size; i++)
164
+ {
165
+ mpz_set_ui (temp, p->ob_digit[i]);
166
+ mpz_mul_2exp (temp2, temp, PyLong_SHIFT * i);
167
+ mpz_add (m, m, temp2);
168
+ }
169
+ mpz_clear (temp);
170
+ mpz_clear (temp2);
171
+ if(isNeg) mpz_neg(m, m);
172
+ }
173
+
174
+ char *convert_buffer_to_hex(uint8_t * data, size_t len)
175
+ {
176
+ size_t i;
177
+ char tmp1[3];
178
+ char *tmp = (char *) malloc(len * 3);
179
+ memset(tmp, 0, len*3 - 1);
180
+
181
+ for (i = 0; i < len; i++) {
182
+ snprintf(tmp1, 3, "%02X ", data[i]);
183
+ strcat(tmp, tmp1);
184
+ }
185
+
186
+ return tmp;
187
+ }
188
+
189
+ void printf_buffer_as_hex(uint8_t * data, size_t len)
190
+ {
191
+ #ifdef DEBUG
192
+ size_t i;
193
+
194
+ for (i = 0; i < len; i++) {
195
+ printf("%02x ", data[i]);
196
+ }
197
+ printf("\n");
198
+ #endif
199
+ }
200
+
201
+ // simply checks that the elements satisfy the properties for the given
202
+ // binary operation. Whitelist approach: only return TRUE for valid cases, otherwise FALSE
203
+ int Check_Types(Group_t l_type, Group_t r_type, char op)
204
+ {
205
+ switch (op) {
206
+ // Rules: elements must be of the same type, multiplicative operations should be only used for
207
+ // elements in field GT
208
+ case 'a':
209
+ if(l_type == pyGT_t || r_type == pyGT_t) { return FALSE; }
210
+ break;
211
+ case 's':
212
+ if(l_type == pyGT_t || r_type == pyGT_t) { return FALSE; }
213
+ break;
214
+ case 'e':
215
+ if(l_type != pyG1_t && r_type != pyG2_t) { return FALSE; }
216
+ break;
217
+ case 'p':
218
+ // rule for exponentiation for types
219
+ if(l_type != pyG1_t && l_type != pyG2_t && l_type != pyGT_t && l_type != pyZR_t) { return FALSE; }
220
+ // && r_type != ZR)
221
+ // else {
222
+ // PyErr_SetString(ElementError, "Only fields => [G1_t,G2,GT,Zr] ** Zr");
223
+ // return FALSE;
224
+ //}
225
+ break;
226
+ default:
227
+ break;
228
+ }
229
+
230
+ return TRUE;
231
+
232
+ }
233
+
234
+ // assumes that pairing structure has been initialized
235
+ static Element *createNewElement(Group_t element_type, Pairing *pairing) {
236
+ debug("Create an object of type Element\n");
237
+ Element *retObject = PyObject_New(Element, &ElementType);
238
+ if(element_type == pyZR_t) {
239
+ retObject->e = element_init_ZR(0);
240
+ retObject->element_type = pyZR_t;
241
+ }
242
+ else if(element_type == pyG1_t) {
243
+ retObject->e = element_init_G1();
244
+ retObject->element_type = pyG1_t;
245
+ }
246
+ else if(element_type == pyG2_t) {
247
+ retObject->e = element_init_G2();
248
+ retObject->element_type = pyG2_t;
249
+ }
250
+ else if(element_type == pyGT_t) {
251
+ retObject->e = element_init_GT(pairing);
252
+ retObject->element_type = pyGT_t;
253
+ }
254
+ else {
255
+ // init without a type -- caller must set e and element_type
256
+ }
257
+
258
+ retObject->elem_initialized = TRUE;
259
+ retObject->elem_initPP = FALSE;
260
+ retObject->pairing = pairing;
261
+ Py_INCREF(retObject->pairing);
262
+ return retObject;
263
+ }
264
+
265
+ Element *convertToZR(PyObject *longObj, PyObject *elemObj) {
266
+ Element *self = (Element *) elemObj;
267
+ Element *new = createNewElement(pyZR_t, self->pairing);
268
+
269
+ mpz_t x;
270
+ mpz_init(x);
271
+ #if PY_MAJOR_VERSION < 3
272
+ PyObject *longObj2 = PyNumber_Long(longObj);
273
+ longObjToMPZ(x, (PyLongObject *) longObj2);
274
+ Py_DECREF(longObj2);
275
+ #else
276
+ longObjToMPZ(x, (PyLongObject *) longObj);
277
+ #endif
278
+ element_set_mpz(new, x);
279
+ mpz_clear(x);
280
+ return new;
281
+ }
282
+
283
+ void Pairing_dealloc(Pairing *self)
284
+ {
285
+ if(self->group_init) {
286
+ element_delete(pyZR_t, self->order);
287
+ pairing_clear(self->pair_obj);
288
+ self->pair_obj = NULL;
289
+ self->order = NULL;
290
+ }
291
+
292
+ #ifdef BENCHMARK_ENABLED
293
+ if(self->dBench != NULL) {
294
+ // PrintPyRef("releasing benchmark object", self->dBench);
295
+ Py_CLEAR(self->dBench);
296
+ if(self->gBench != NULL) {
297
+ // PrintPyRef("releasing operations object", self->gBench);
298
+ Py_CLEAR(self->gBench);
299
+ }
300
+ }
301
+ #endif
302
+ Py_TYPE(self)->tp_free((PyObject *) self);
303
+ }
304
+
305
+ void Element_dealloc(Element* self)
306
+ {
307
+ // add reference count to objects
308
+ if(self->elem_initialized) {
309
+ element_delete(self->element_type, self->e);
310
+ // Defensive: Use Py_XDECREF instead of Py_DECREF to handle NULL safely
311
+ // and check if pairing object is valid before decrementing
312
+ // This prevents crashes with immortal objects in Python 3.12+ (PEP 683)
313
+ if(self->pairing != NULL) {
314
+ Py_XDECREF(self->pairing);
315
+ }
316
+ }
317
+
318
+ Py_TYPE(self)->tp_free((PyObject*)self);
319
+ }
320
+
321
+ /*!
322
+ * Hash a null-terminated string to a byte array.
323
+ *
324
+ * @param input_buf The input buffer.
325
+ * @param input_len The input buffer length (in bytes).
326
+ * @param output_buf A pre-allocated output buffer of size hash_len.
327
+ * @param hash_len Length of the output hash (in bytes). Should be approximately bit size of curve group order.
328
+ * @param hash_prefix prefix for hash function.
329
+ */
330
+ int hash_to_bytes(uint8_t *input_buf, int input_len, uint8_t *output_buf, int hash_len, uint8_t hash_prefix)
331
+ {
332
+ EVP_MD_CTX *ctx;
333
+ unsigned int md_len;
334
+ int i, new_input_len = input_len + 2; // extra byte for prefix
335
+ uint8_t first_block = 0;
336
+ uint8_t new_input[new_input_len+1];
337
+ // printf("orig input => \n");
338
+ // printf_buffer_as_hex(input_buf, input_len);
339
+
340
+ memset(new_input, 0, new_input_len+1);
341
+ new_input[0] = first_block; // block number (always 0 by default)
342
+ new_input[1] = hash_prefix; // set hash prefix
343
+ memcpy((uint8_t *)(new_input+2), input_buf, input_len); // copy input bytes
344
+
345
+ // printf("new input => \n");
346
+ // printf_buffer_as_hex(new_input, new_input_len);
347
+ // prepare output buf
348
+ memset(output_buf, 0, hash_len);
349
+
350
+ ctx = EVP_MD_CTX_new();
351
+ if (ctx == NULL) return FALSE;
352
+
353
+ if (hash_len <= HASH_LEN) {
354
+ EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
355
+ EVP_DigestUpdate(ctx, new_input, new_input_len);
356
+ uint8_t md[HASH_LEN+1];
357
+ EVP_DigestFinal_ex(ctx, md, &md_len);
358
+ memcpy(output_buf, md, hash_len);
359
+ }
360
+ else {
361
+ // apply variable-size hash technique to get desired size
362
+ // determine block count.
363
+ int blocks = (int) ceil(((double) hash_len) / HASH_LEN);
364
+ debug("Num blocks needed: %d\n", blocks);
365
+ uint8_t md[HASH_LEN+1];
366
+ uint8_t md2[(blocks * HASH_LEN)+1];
367
+ uint8_t *target_buf = md2;
368
+ for(i = 0; i < blocks; i++) {
369
+ /* compute digest = SHA-2( i || prefix || input_buf ) || ... || SHA-2( n-1 || prefix || input_buf ) */
370
+ target_buf += (i * HASH_LEN);
371
+ new_input[0] = (uint8_t) i;
372
+ EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
373
+ debug("input %d => ", i);
374
+ printf_buffer_as_hex(new_input, new_input_len);
375
+ EVP_DigestUpdate(ctx, new_input, new_input_len);
376
+ EVP_DigestFinal_ex(ctx, md, &md_len);
377
+ memcpy(target_buf, md, hash_len);
378
+ debug("block %d => ", i);
379
+ printf_buffer_as_hex(md, HASH_LEN);
380
+ memset(md, 0, HASH_LEN);
381
+ }
382
+ // copy back to caller
383
+ memcpy(output_buf, md2, hash_len);
384
+ }
385
+
386
+ EVP_MD_CTX_free(ctx);
387
+ return TRUE;
388
+ }
389
+
390
+ /*!
391
+ * Hash a group element to a byte array. This calls hash_to_bytes().
392
+ *
393
+ * @param element The input element.
394
+ * @param hash_len Length of the output hash (in bytes).
395
+ * @param output_buf A pre-allocated output buffer.
396
+ * @param hash_num Index number of the hash function to use (changes the output).
397
+ * @return FENC_ERROR_NONE or an error code.
398
+ */
399
+ int hash_element_to_bytes(Element *element, int hash_size, uint8_t* output_buf, int prefix)
400
+ {
401
+ int result = TRUE;
402
+ unsigned int buf_len;
403
+
404
+ buf_len = element_length_in_bytes(element);
405
+ uint8_t *temp_buf = (uint8_t *)malloc(buf_len+1);
406
+ if (temp_buf == NULL) {
407
+ return FALSE;
408
+ }
409
+
410
+ element_to_bytes(temp_buf, element);
411
+ result = hash_to_bytes(temp_buf, buf_len, output_buf, hash_size, prefix);
412
+ free(temp_buf);
413
+
414
+ return TRUE;
415
+ }
416
+
417
+ PyObject *Element_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
418
+ {
419
+ Element *self;
420
+
421
+ self = (Element *)type->tp_alloc(type, 0);
422
+ if (self != NULL) {
423
+ self->elem_initialized = FALSE;
424
+ self->pairing = NULL;
425
+ self->element_type = NONE_G;
426
+ }
427
+
428
+ return (PyObject *)self;
429
+ }
430
+
431
+ PyObject *Pairing_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
432
+ {
433
+ Pairing *self = (Pairing *) type->tp_alloc(type, 0);
434
+ if(self != NULL) {
435
+ self->group_init = FALSE;
436
+ self->curve = -1;
437
+ #ifdef BENCHMARK_ENABLED
438
+ memset(self->bench_id, 0, ID_LEN);
439
+ self->dBench = NULL;
440
+ self->gBench = NULL;
441
+ #endif
442
+ }
443
+
444
+ return (PyObject *) self;
445
+ }
446
+
447
+ int Element_init(Element *self, PyObject *args, PyObject *kwds)
448
+ {
449
+ return -1;
450
+ }
451
+
452
+
453
+ int Pairing_init(Pairing *self, PyObject *args, PyObject *kwds)
454
+ {
455
+ char *params = NULL, *param_string = NULL;
456
+ Py_ssize_t b_len = 0;
457
+ int aes_sec = -1;
458
+ static char *kwlist[] = {"aes_sec", "params", "param_string", NULL};
459
+
460
+ if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iss#", kwlist,
461
+ &aes_sec, &params, &param_string, &b_len)) {
462
+ PyErr_SetString(ElementError, "invalid arguments");
463
+ return -1;
464
+ }
465
+
466
+ if(aes_sec != -1) {
467
+ if(aes_sec == MNT160) {
468
+ self->pair_obj = pairing_init(aes_sec);
469
+ self->order = order(self->pair_obj);
470
+ self->curve = MNT; // only supported at this point
471
+ pairing_init_finished = FALSE;
472
+ }
473
+ else if(aes_sec == BN256) {
474
+ self->pair_obj = pairing_init(aes_sec);
475
+ self->order = order(self->pair_obj);
476
+ self->curve = BN; // only supported at this point
477
+ pairing_init_finished = FALSE;
478
+ }
479
+ else if(aes_sec == SS512) {
480
+ self->pair_obj = pairing_init(aes_sec);
481
+ self->order = order(self->pair_obj);
482
+ self->curve = SS; // only supported at this point
483
+ pairing_init_finished = FALSE;
484
+ }
485
+ }
486
+
487
+ self->group_init = TRUE;
488
+ return 0;
489
+ }
490
+
491
+ /*
492
+ PyObject *Element_call(Element *elem, PyObject *args, PyObject *kwds)
493
+ {
494
+ PyObject *object;
495
+ Element *newObject;
496
+
497
+ if(!PyArg_ParseTuple(args, "O:ref", &object)) {
498
+ printf("Could not retrieve object.\n");
499
+ return NULL;
500
+ }
501
+
502
+ newObject = (Element *) object;
503
+ print("Elment->e => \n", newObject->element_type, newObject->e);
504
+ debug("Element->type => '%d'\n", newObject->element_type);
505
+
506
+ return NULL;
507
+ }
508
+ */
509
+
510
+ static PyObject *Element_elem(Element* self, PyObject* args)
511
+ {
512
+ Element *retObject, *group = NULL;
513
+ int type;
514
+ PyObject *long_obj = NULL;
515
+
516
+ if(!PyArg_ParseTuple(args, "Oi|O", &group, &type, &long_obj)) {
517
+ PyErr_SetString(ElementError, "invalid arguments.\n");
518
+ return NULL;
519
+ }
520
+
521
+ debug("init an element.\n");
522
+
523
+ if(type >= pyZR_t && type <= pyGT_t) {
524
+ retObject = createNewElement(type, group->pairing);
525
+ }
526
+ else {
527
+ PyErr_SetString(ElementError, "unrecognized group type.");
528
+ return NULL;
529
+ }
530
+
531
+ if(long_obj != NULL && _PyLong_Check(long_obj)) {
532
+ mpz_t m;
533
+ mpz_init(m);
534
+ #if PY_MAJOR_VERSION < 3
535
+ PyObject *longObj2 = PyNumber_Long(long_obj);
536
+ longObjToMPZ(m, (PyLongObject *) longObj2);
537
+ Py_DECREF(longObj2);
538
+ #else
539
+ longObjToMPZ(m, (PyLongObject *) long_obj);
540
+ #endif
541
+ element_set_mpz(retObject, m);
542
+ mpz_clear(m);
543
+ }
544
+
545
+ /* return Element object */
546
+ return (PyObject *) retObject;
547
+ }
548
+
549
+ PyObject *Pairing_print(Element* self)
550
+ {
551
+ return PyUnicode_FromString("");
552
+ }
553
+
554
+ // TODO: use element_vnprintf to copy the result into element type
555
+ PyObject *Element_print(Element* self)
556
+ {
557
+ PyObject *strObj;
558
+ debug("Contents of element object\n");
559
+
560
+ if(check_type(self->element_type) && self->elem_initialized) {
561
+ int len = element_length_to_str(self);
562
+ unsigned char *tmp = (unsigned char *) malloc(len + 1);
563
+ memset(tmp, 0, len);
564
+ element_to_str(&tmp, self);
565
+ tmp[len] = '\0';
566
+
567
+ strObj = PyUnicode_FromString((const char *) tmp);
568
+ free(tmp);
569
+ return strObj;
570
+ }
571
+
572
+ return PyUnicode_FromString("");
573
+ }
574
+
575
+ static PyObject *Element_random(Element* self, PyObject* args)
576
+ {
577
+ Element *retObject;
578
+ Pairing *group = NULL;
579
+ int arg1;
580
+ int seed = -1;
581
+
582
+ /* create a new object */
583
+ if(!PyArg_ParseTuple(args, "Oi|i", &group, &arg1, &seed))
584
+ return NULL;
585
+
586
+ VERIFY_GROUP(group);
587
+ retObject = PyObject_New(Element, &ElementType);
588
+ debug("init random element in '%d'\n", arg1);
589
+ if(arg1 == pyZR_t) {
590
+ retObject->e = element_init_ZR(0);
591
+ retObject->element_type = pyZR_t;
592
+ }
593
+ else if(arg1 == pyG1_t) {
594
+ retObject->e = element_init_G1();
595
+ retObject->element_type = pyG1_t;
596
+ }
597
+ else if(arg1 == pyG2_t) {
598
+ retObject->e = element_init_G2();
599
+ retObject->element_type = pyG2_t;
600
+ }
601
+ else if(arg1 == pyGT_t) {
602
+ PyErr_SetString(ElementError, "cannot generate random element in GT directly.");
603
+ return NULL;
604
+ }
605
+ else {
606
+ PyErr_SetString(ElementError, "unrecognized group type.");
607
+ return NULL;
608
+ }
609
+
610
+ if(seed > -1) {
611
+ // pbc_random_set_deterministic((uint32_t) seed);
612
+ }
613
+ /* create new Element object */
614
+ element_random(retObject->element_type, group->pair_obj, retObject->e);
615
+
616
+ retObject->elem_initialized = TRUE;
617
+ retObject->elem_initPP = FALSE;
618
+ retObject->pairing = group;
619
+ Py_INCREF(retObject->pairing);
620
+ return (PyObject *) retObject;
621
+ }
622
+
623
+ static PyObject *Element_add(Element *self, Element *other)
624
+ {
625
+ Element *newObject = NULL;
626
+
627
+ debug("Starting '%s'\n", __func__);
628
+ #ifdef DEBUG
629
+ if(self->e) {
630
+ // element_printf("Left: e => '%B'\n", self->e);
631
+ }
632
+
633
+ if(other->e) {
634
+ // element_printf("Right: e => '%B'\n", other->e);
635
+ }
636
+ #endif
637
+
638
+ if( add_rule(self->element_type, other->element_type) == FALSE) {
639
+ PyErr_SetString(ElementError, "invalid add operation");
640
+ return NULL;
641
+ }
642
+ // start micro benchmark
643
+
644
+ newObject = createNewElement(self->element_type, self->pairing);
645
+ element_add(newObject, self, other);
646
+ #ifdef BENCHMARK_ENABLED
647
+ UPDATE_BENCH(ADDITION, newObject->element_type, newObject->pairing);
648
+ #endif
649
+ return (PyObject *) newObject;
650
+ }
651
+
652
+ static PyObject *Element_sub(Element *self, Element *other)
653
+ {
654
+ Element *newObject = NULL;
655
+
656
+ debug("Starting '%s'\n", __func__);
657
+ #ifdef DEBUG
658
+ if(self->e) {
659
+ // element_printf("Left: e => '%B'\n", self->e);
660
+ }
661
+
662
+ if(other->e) {
663
+ // element_printf("Right: e => '%B'\n", other->e);
664
+ }
665
+ #endif
666
+ if( sub_rule(self->element_type, other->element_type) == FALSE) {
667
+ PyErr_SetString(ElementError, "invalid sub operation");
668
+ return NULL;
669
+ }
670
+
671
+
672
+ newObject = createNewElement(self->element_type, self->pairing);
673
+ element_sub(newObject, self, other);
674
+ #ifdef BENCHMARK_ENABLED
675
+ UPDATE_BENCH(SUBTRACTION, newObject->element_type, newObject->pairing);
676
+ #endif
677
+ return (PyObject *) newObject;
678
+ }
679
+
680
+
681
+ static PyObject *Element_mul(PyObject *lhs, PyObject *rhs)
682
+ {
683
+ Element *self = NULL, *other = NULL, *newObject = NULL;
684
+ signed long int z;
685
+ int found_int = FALSE;
686
+
687
+ // lhs or rhs must be an element type
688
+ if(PyElement_Check(lhs)) {
689
+ self = (Element *) lhs;
690
+ }
691
+ else if(PyNumber_Check(lhs)) {
692
+ if(PyArg_Parse(lhs, "l", &z)) {
693
+ debug("Integer lhs: '%li'\n", z);
694
+ }
695
+ found_int = TRUE;
696
+ }
697
+
698
+ if(PyElement_Check(rhs)) {
699
+ other = (Element *) rhs;
700
+ }
701
+ else if(PyNumber_Check(rhs)) {
702
+ if(PyArg_Parse(rhs, "l", &z)) {
703
+ debug("Integer rhs: '%li'\n", z);
704
+ }
705
+ found_int = TRUE;
706
+ }
707
+
708
+ debug("Starting '%s'\n", __func__);
709
+ if(PyElement_Check(lhs) && found_int) {
710
+ // lhs is the element type
711
+ //
712
+ newObject = createNewElement(self->element_type, self->pairing);
713
+ element_mul_si(newObject, self, z);
714
+ //
715
+ }
716
+ else if(PyElement_Check(rhs) && found_int) {
717
+ // rhs is the element type
718
+ //
719
+ newObject = createNewElement(other->element_type, other->pairing);
720
+ element_mul_si(newObject, other, z);
721
+ //
722
+ }
723
+ else if(PyElement_Check(lhs) && PyElement_Check(rhs)) {
724
+ // both are element types
725
+ if( mul_rule(self->element_type, other->element_type) == FALSE) {
726
+ PyErr_SetString(ElementError, "invalid mul operation");
727
+ return NULL;
728
+ }
729
+
730
+ if(self->element_type != pyZR_t && other->element_type == pyZR_t) {
731
+ newObject = createNewElement(self->element_type, self->pairing);
732
+ element_mul_zn(newObject, self, other);
733
+ }
734
+ else if(other->element_type != pyZR_t && self->element_type == pyZR_t) {
735
+ newObject = createNewElement(other->element_type, self->pairing);
736
+ element_mul_zn(newObject, other, self);
737
+ }
738
+ else { // all other cases
739
+ newObject = createNewElement(self->element_type, self->pairing);
740
+ element_mul(newObject, self, other);
741
+ }
742
+ }
743
+ else {
744
+ PyErr_SetString(ElementError, "invalid types");
745
+ return NULL;
746
+ }
747
+ #ifdef BENCHMARK_ENABLED
748
+ UPDATE_BENCH(MULTIPLICATION, newObject->element_type, newObject->pairing);
749
+ #endif
750
+ return (PyObject *) newObject;
751
+ }
752
+
753
+ static PyObject *Element_div(PyObject *lhs, PyObject *rhs)
754
+ {
755
+ Element *self = NULL, *other = NULL, *newObject = NULL;
756
+ signed long int z;
757
+ int found_int = FALSE;
758
+
759
+ // lhs or rhs must be an element type
760
+ if(PyElement_Check(lhs)) {
761
+ self = (Element *) lhs;
762
+ }
763
+ else if(PyNumber_Check(lhs)) {
764
+ if(PyArg_Parse(lhs, "l", &z)) {
765
+ debug("Integer lhs: '%li'\n", z);
766
+ }
767
+ found_int = TRUE;
768
+ }
769
+
770
+ if(PyElement_Check(rhs)) {
771
+ other = (Element *) rhs;
772
+ }
773
+ else if(PyNumber_Check(rhs)) {
774
+ if(PyArg_Parse(rhs, "l", &z)) {
775
+ debug("Integer rhs: '%li'\n", z);
776
+ }
777
+ found_int = TRUE;
778
+ }
779
+
780
+ debug("Starting '%s'\n", __func__);
781
+ if(PyElement_Check(lhs) && found_int) {
782
+ // lhs is the element type
783
+
784
+ if(z != 0) {
785
+ newObject = createNewElement(self->element_type, self->pairing);
786
+ other = createNewElement(self->element_type, self->pairing);
787
+ element_set_si(other, z);
788
+ element_div(newObject, self, other);
789
+ }
790
+ else {
791
+ PyErr_SetString(ElementError, "divide by zero exception!");
792
+ goto divbyzero;
793
+ }
794
+
795
+ }
796
+ else if(PyElement_Check(rhs) && found_int) {
797
+ // rhs is the element type
798
+
799
+ if(z > 1 || z <= 0) {
800
+ newObject = createNewElement(other->element_type, other->pairing);
801
+ self = createNewElement(other->element_type, other->pairing);
802
+ element_set_si(self, z);
803
+ element_div(newObject, self, other); // come back to this (not working)
804
+ }
805
+ else if(z == 1) {
806
+ newObject = createNewElement(other->element_type, other->pairing);
807
+ element_invert(newObject, other);
808
+ }
809
+
810
+ }
811
+ else if(PyElement_Check(lhs) && PyElement_Check(rhs)) {
812
+ // both are element types
813
+ if( div_rule(self->element_type, other->element_type) == FALSE) {
814
+ PyErr_SetString(ElementError, "invalid div operation");
815
+ return NULL;
816
+ }
817
+
818
+
819
+ newObject = createNewElement(self->element_type, self->pairing);
820
+ element_div(newObject, self, other);
821
+
822
+ }
823
+ else {
824
+ PyErr_SetString(ElementError, "invalid types");
825
+ return NULL;
826
+ }
827
+
828
+ #ifdef BENCHMARK_ENABLED
829
+ UPDATE_BENCH(DIVISION, newObject->element_type, newObject->pairing);
830
+ #endif
831
+
832
+ divbyzero:
833
+ return (PyObject *) newObject;
834
+ }
835
+
836
+
837
+ static PyObject *Element_invert(Element *self)
838
+ {
839
+ Element *newObject = NULL;
840
+
841
+ // debug("Starting '%s'\n", __func__);
842
+ //#ifdef DEBUG
843
+ // if(self->e) {
844
+ // element_printf("e => '%B'\n", self->e);
845
+ // }
846
+ //#endif
847
+
848
+
849
+ if(check_type(self->element_type)) {
850
+ newObject = createNewElement(self->element_type, self->pairing);
851
+ element_invert(newObject, self);
852
+ }
853
+
854
+ return (PyObject *) newObject;
855
+ }
856
+
857
+ static PyObject *Element_negate(Element *self)
858
+ {
859
+ Element *newObject = NULL;
860
+
861
+
862
+ newObject = createNewElement(self->element_type, self->pairing);
863
+ element_neg(newObject, self);
864
+
865
+
866
+ return (PyObject *) newObject;
867
+ }
868
+
869
+ static PyObject *Element_pow(PyObject *o1, PyObject *o2, PyObject *o3)
870
+ {
871
+ Element *newObject = NULL, *lhs_o1 = NULL, *rhs_o2 = NULL;
872
+ int longFoundLHS = FALSE, longFoundRHS = FALSE;
873
+ mpz_t n;
874
+
875
+ Check_Types2(o1, o2, lhs_o1, rhs_o2, longFoundLHS, longFoundRHS);
876
+
877
+ if(longFoundLHS) {
878
+ // o1 is a long type and o2 is a element type
879
+ // o1 should be element and o2 should be mpz
880
+ printf("operation undefined: '%d' ^ <pairing element>\n", rhs_o2->element_type);
881
+ // if(rhs_o2->element_type == ZR) {
882
+ //
883
+ // mpz_init(n);
884
+ // element_to_mpz(n, rhs_o2);
885
+ //
886
+ // lhs_o1 = convertToZR(o1, o2);
887
+ // newObject = createNewElement(rhs_o2->element_type, rhs_o2->pairing);
888
+ // element_pow_zr(newObject, lhs_o1, n);
889
+ // mpz_clear(n);
890
+ // PyObject_Del(lhs_o1);
891
+ //
892
+ // }
893
+ }
894
+ else if(longFoundRHS) {
895
+ // o2 is a long type
896
+ // if(lhs_o1->element_type != pyZR_t) {
897
+
898
+ long rhs = PyLong_AsLong(o2);
899
+ if(PyErr_Occurred() || rhs >= 0) {
900
+ // clear error and continue
901
+ //PyErr_Print(); // for debug purposes
902
+ PyErr_Clear();
903
+ newObject = createNewElement(lhs_o1->element_type, lhs_o1->pairing);
904
+ rhs_o2 = createNewElement(pyZR_t, lhs_o1->pairing);
905
+ if(newObject->element_type != pyZR_t) {
906
+ mpz_init(n);
907
+ #if PY_MAJOR_VERSION < 3
908
+ PyObject *longObj2 = PyNumber_Long(o2);
909
+ longObjToMPZ(n, (PyLongObject *) longObj2);
910
+ Py_DECREF(longObj2);
911
+ #else
912
+ longObjToMPZ(n, (PyLongObject *) o2);
913
+ #endif
914
+ element_set_mpz(rhs_o2, n);
915
+ element_pow_zr(newObject, lhs_o1, rhs_o2);
916
+ mpz_clear(n);
917
+ }
918
+ else if(rhs >= 0 && rhs <= INT_MAX) {
919
+ // if less than int for given architecture
920
+ element_pow_int(newObject, lhs_o1, rhs);
921
+ }
922
+ else { // anything larger: convert to an MPZ type then raise to EXP value
923
+ mpz_init(n);
924
+ #if PY_MAJOR_VERSION < 3
925
+ PyObject *longObj2 = PyNumber_Long(o2);
926
+ longObjToMPZ(n, (PyLongObject *) longObj2);
927
+ Py_DECREF(longObj2);
928
+ #else
929
+ longObjToMPZ(n, (PyLongObject *) o2);
930
+ #endif
931
+ element_set_mpz(rhs_o2, n);
932
+ element_pow_zr(newObject, lhs_o1, rhs_o2);
933
+ mpz_clear(n);
934
+ }
935
+ Py_DECREF(rhs_o2);
936
+
937
+ }
938
+ else if(rhs == -1) {
939
+ newObject = createNewElement(lhs_o1->element_type, lhs_o1->pairing);
940
+ element_invert(newObject, lhs_o1);
941
+
942
+ }
943
+ else {
944
+ EXIT_IF(TRUE, "unexpected error.");
945
+ }
946
+ }
947
+ else if(Check_Elements(o1, o2)) {
948
+ debug("Starting '%s'\n", __func__);
949
+ EXIT_IF(exp_rule(lhs_o1->element_type, rhs_o2->element_type) == FALSE, "invalid exp operation.");
950
+
951
+ if(rhs_o2->element_type == pyZR_t) {
952
+
953
+ newObject = createNewElement(NONE_G, lhs_o1->pairing);
954
+ element_pow_zr(newObject, lhs_o1, rhs_o2);
955
+
956
+ }
957
+ }
958
+ else {
959
+ EXIT_IF(!PyElement_Check(o1), ERROR_TYPE(left, int, bytes, str));
960
+ EXIT_IF(!PyElement_Check(o2), ERROR_TYPE(right, int, bytes, str));
961
+ }
962
+
963
+ #ifdef BENCHMARK_ENABLED
964
+ UPDATE_BENCH(EXPONENTIATION, newObject->element_type, newObject->pairing);
965
+ #endif
966
+ return (PyObject *) newObject;
967
+ }
968
+
969
+ /* We assume the element has been initialized into a specific field (G1_t,G2,GT,or Zr), then
970
+ they have the opportunity to set the
971
+
972
+ */
973
+ static PyObject *Element_set(Element *self, PyObject *args)
974
+ {
975
+ Element *object = NULL;
976
+ int errcode = TRUE;
977
+ long int value = -1;
978
+
979
+ if(self->elem_initialized == FALSE) {
980
+ PyErr_SetString(ElementError, "must initialize element to a field (G1_t,G2,GT, or Zr)");
981
+ errcode = FALSE;
982
+ return Py_BuildValue("i", errcode);
983
+ }
984
+
985
+ debug("Creating a new element\n");
986
+ if(PyArg_ParseTuple(args, "|lO", &value, &object)) {
987
+ // convert into an int using PyArg_Parse(...)
988
+ // set the element
989
+ if(value == -1 && self->element_type == pyZR_t) {
990
+ debug("Setting element to '%li'\n", value);
991
+
992
+ debug("Value '%i'\n", (signed int) value);
993
+ element_set_si(self, (signed int) value);
994
+
995
+ }
996
+ else if(object != NULL) {
997
+
998
+ if(self->element_type == object->element_type) {
999
+
1000
+ element_set(self, object);
1001
+
1002
+ }
1003
+ else {
1004
+ PyErr_SetString(ElementError, "types are not the same!");
1005
+ errcode = FALSE;
1006
+ return Py_BuildValue("i", errcode);
1007
+ }
1008
+ }
1009
+ }
1010
+
1011
+ return Py_BuildValue("i", errcode);
1012
+ }
1013
+
1014
+ static PyObject *Element_setxy(Element *self, PyObject *args)
1015
+ {
1016
+ Element *object1 = NULL, *object2 = NULL;
1017
+ int errcode = TRUE;
1018
+
1019
+ if(self->elem_initialized == FALSE) {
1020
+ PyErr_SetString(ElementError, "must initialize element to a field (G1_t,G2,GT, or Zr)");
1021
+ return NULL;
1022
+ }
1023
+
1024
+ debug("Creating a new element\n");
1025
+ if(PyArg_ParseTuple(args, "|OO", &object1, &object2)) {
1026
+ // convert into an int using PyArg_Parse(...)
1027
+ // set the element
1028
+ if(self->element_type == pyG1_t) {
1029
+ if(object1->element_type == object2->element_type && object1->element_type == pyZR_t) {
1030
+ errcode = element_setG1(self, object1, object2);
1031
+ }
1032
+ else {
1033
+ PyErr_SetString(ElementError, "types are not the same!");
1034
+ return NULL;
1035
+ }
1036
+ }
1037
+ }
1038
+
1039
+ Py_RETURN_TRUE;
1040
+ }
1041
+
1042
+ static PyObject *Element_initPP(Element *self, PyObject *args)
1043
+ {
1044
+ EXITCODE_IF(self->elem_initPP == TRUE, "initialized the pre-processing function already", FALSE);
1045
+ EXITCODE_IF(self->elem_initialized == FALSE, "must initialize element to a field (G1,G2, or GT)", FALSE);
1046
+
1047
+ /* initialize and store preprocessing information in e_pp */
1048
+ if(self->element_type >= pyG1_t && self->element_type <= pyGT_t) {
1049
+ int result;
1050
+ element_pp_init(result, self);
1051
+ if(result == FALSE) { Py_RETURN_FALSE; }
1052
+ self->elem_initPP = TRUE;
1053
+ Py_RETURN_TRUE;
1054
+ }
1055
+
1056
+ Py_RETURN_FALSE;
1057
+ }
1058
+
1059
+
1060
+ /* Takes a list of two objects in G1 & G2 respectively and computes the multi-pairing */
1061
+ PyObject *multi_pairing_asymmetric(Pairing *groupObj, PyObject *listG1, PyObject *listG2)
1062
+ {
1063
+ int length = PySequence_Length(listG1);
1064
+
1065
+ if(length != PySequence_Length(listG2)) {
1066
+ PyErr_SetString(ElementError, "unequal number of pairing elements.");
1067
+ return NULL;
1068
+ }
1069
+
1070
+ if(length > 0) {
1071
+
1072
+ element_t *g1[length];
1073
+ element_t *g2[length];
1074
+ int i, l = 0, r = 0;
1075
+
1076
+ for(i = 0; i < length; i++) {
1077
+ PyObject *tmpObject1 = PySequence_GetItem(listG1, i);
1078
+ PyObject *tmpObject2 = PySequence_GetItem(listG2, i);
1079
+
1080
+ if(PyElement_Check(tmpObject1) && PyElement_Check(tmpObject2)) {
1081
+ Element *tmp1 = (Element *) tmpObject1;
1082
+ Element *tmp2 = (Element *) tmpObject2;
1083
+ if(tmp1->element_type == pyG1_t) {
1084
+ g1[l] = element_init_G1();
1085
+ element_set_raw(groupObj, pyG1_t, g1[l], tmp1->e);
1086
+ l++;
1087
+ }
1088
+ if(tmp2->element_type == pyG2_t) {
1089
+ g2[r] = element_init_G2();
1090
+ element_set_raw(groupObj, pyG2_t, g2[r], tmp2->e);
1091
+ r++;
1092
+ }
1093
+ }
1094
+ Py_DECREF(tmpObject1);
1095
+ Py_DECREF(tmpObject2);
1096
+ }
1097
+
1098
+ Element *newObject = NULL;
1099
+ if(l == r) {
1100
+ newObject = createNewElement(pyGT_t, groupObj);
1101
+ element_prod_pairing(newObject, &g1, &g2, l); // pairing product calculation
1102
+ }
1103
+ else {
1104
+ PyErr_SetString(ElementError, "invalid pairing element types in list.");
1105
+ }
1106
+
1107
+ /* clean up */
1108
+ for(i = 0; i < l; i++) { element_delete(pyG1_t, g1[i]); }
1109
+ for(i = 0; i < r; i++) { element_delete(pyG2_t, g2[i]); }
1110
+ return (PyObject *) newObject;
1111
+ }
1112
+
1113
+ PyErr_SetString(ElementError, "list is empty.");
1114
+ return NULL;
1115
+ }
1116
+
1117
+ /* this is a type method that is visible on the global or class level. Therefore,
1118
+ the function prototype needs the self (element class) and the args (tuple of Element objects).
1119
+ */
1120
+ PyObject *Apply_pairing(Element *self, PyObject *args)
1121
+ {
1122
+ // lhs => G1_t and rhs => G2
1123
+ Element *newObject = NULL, *lhs, *rhs;
1124
+ Pairing *group = NULL;
1125
+ PyObject *lhs2, *rhs2;
1126
+
1127
+ debug("Applying pairing...\n");
1128
+ if(!PyArg_ParseTuple(args, "OO|O", &lhs2, &rhs2, &group)) {
1129
+ PyErr_SetString(ElementError, "missing element objects");
1130
+ return NULL;
1131
+ }
1132
+
1133
+ if(PySequence_Check(lhs2) && PySequence_Check(rhs2)) {
1134
+ VERIFY_GROUP(group); /* defined iff using as multi-pairing */
1135
+ return multi_pairing_asymmetric(group, lhs2, rhs2);
1136
+ }
1137
+ else if(PyElement_Check(lhs2) && PyElement_Check(rhs2)) {
1138
+
1139
+ lhs = (Element *) lhs2;
1140
+ rhs = (Element *) rhs2;
1141
+
1142
+ if(Check_Elements(lhs, rhs) && pair_rule(lhs->element_type, rhs->element_type) == TRUE) {
1143
+ newObject = createNewElement(NONE_G, lhs->pairing);
1144
+ if(lhs->element_type == pyG1_t) {
1145
+ pairing_apply(newObject, lhs, rhs);
1146
+ }
1147
+ else if(lhs->element_type == pyG2_t) {
1148
+ pairing_apply(newObject, rhs, lhs);
1149
+ }
1150
+ #ifdef BENCHMARK_ENABLED
1151
+ UPDATE_BENCHMARK(PAIRINGS, newObject->pairing->dBench);
1152
+ #endif
1153
+ return (PyObject *) newObject;
1154
+ }
1155
+ }
1156
+
1157
+ PyErr_SetString(ElementError, "pairings only apply to elements of G1 x G2 --> GT");
1158
+ return NULL;
1159
+ }
1160
+
1161
+ PyObject *sha2_hash(Element *self, PyObject *args) {
1162
+ Element *object;
1163
+ PyObject *str;
1164
+ char *hash_hex = NULL;
1165
+ int label = 0;
1166
+
1167
+ debug("Hashing the element...\n");
1168
+ if(!PyArg_ParseTuple(args, "O|i", &object, &label)) {
1169
+ PyErr_SetString(ElementError, "missing element object");
1170
+ return NULL;
1171
+ }
1172
+
1173
+ if(!PyElement_Check(object)) {
1174
+ PyErr_SetString(ElementError, "not a valid element object.");
1175
+ return NULL;
1176
+ }
1177
+ if(!object->elem_initialized) {
1178
+ PyErr_SetString(ElementError, "null element object");
1179
+ return NULL;
1180
+ }
1181
+
1182
+ int hash_size = HASH_LEN;
1183
+ uint8_t hash_buf[hash_size + 1];
1184
+ memset(hash_buf, 0, hash_size);
1185
+ if(object->element_type == pyGT_t) {
1186
+ element_hash_to_key(object, hash_buf, hash_size);
1187
+
1188
+ hash_hex = convert_buffer_to_hex(hash_buf, hash_size);
1189
+ printf_buffer_as_hex(hash_buf, hash_size);
1190
+ }
1191
+
1192
+ str = PyBytes_FromStringAndSize((const char *) hash_hex, hash_size);
1193
+ free(hash_hex);
1194
+
1195
+ return str;
1196
+ }
1197
+
1198
+ // new version that uses same approach as Charm-C++
1199
+ static PyObject *Element_hash(Element *self, PyObject *args)
1200
+ {
1201
+ Element *newObject = NULL, *object = NULL;
1202
+ Pairing *group = NULL;
1203
+ PyObject *objList = NULL, *tmpObject = NULL;
1204
+ PyObject *tmp_obj = NULL;
1205
+ Group_t type = pyZR_t;
1206
+ int i;
1207
+
1208
+ char *tmp = NULL, *str;
1209
+ // make sure args have the right type -- check that args contain a "string" and "string"
1210
+ if(!PyArg_ParseTuple(args, "OO|i", &group, &objList, &type)) {
1211
+ tmp = "invalid object types";
1212
+ goto cleanup;
1213
+ }
1214
+
1215
+ VERIFY_GROUP(group);
1216
+ // first case: is a string and type may or may not be set
1217
+ if(PyBytes_CharmCheck(objList)) {
1218
+ str = NULL;
1219
+ if(type >= pyZR_t && type < pyGT_t) {
1220
+ PyBytes_ToString2(str, objList, tmp_obj);
1221
+ int len = strlen(str);
1222
+ debug("Hashing string '%s' to Zr...\n", str);
1223
+ // create an element of Zr
1224
+ // hash bytes using SHA1
1225
+ newObject = createNewElement(NONE_G, group);
1226
+ newObject->element_type = type;
1227
+
1228
+ element_init_hash(group);
1229
+ debug("Hashing string '%s' to Zr...: size=%d, newsize=%d\n", str, len, strlen(str));
1230
+ element_add_str_hash(group, str, len);
1231
+ element_finish_hash(newObject, type);
1232
+ if(tmp_obj != NULL) Py_DECREF(tmp_obj);
1233
+ }
1234
+ else {
1235
+ // not supported, right?
1236
+ tmp = "cannot hash a string to that field. Only Zr or G1_t.";
1237
+ goto cleanup;
1238
+ }
1239
+ }
1240
+ // second case: is a tuple of elements of which could be a string or group elements
1241
+ else if(PySequence_Check(objList)) {
1242
+ int size = PySequence_Length(objList);
1243
+ if(size > 0) {
1244
+ // its a tuple of Elements
1245
+ tmpObject = PySequence_GetItem(objList, 0);
1246
+ element_init_hash(group);
1247
+ if(PyElement_Check(tmpObject)) {
1248
+ object = (Element *) tmpObject;
1249
+
1250
+ element_add_to_hash(object);
1251
+
1252
+ }
1253
+ else if(PyBytes_CharmCheck(tmpObject)) {
1254
+ str = NULL;
1255
+ PyBytes_ToString2(str, tmpObject, tmp_obj);
1256
+
1257
+ element_add_str_hash(group, str, strlen(str));
1258
+
1259
+ }
1260
+ Py_DECREF(tmpObject);
1261
+ if(tmp_obj != NULL) Py_DECREF(tmp_obj);
1262
+
1263
+ // loop over the remaining elements in list
1264
+ for(i = 1; i < size; i++) {
1265
+ tmpObject = PySequence_GetItem(objList, i);
1266
+ if(PyElement_Check(tmpObject)) {
1267
+ object = (Element *) tmpObject;
1268
+
1269
+ element_add_to_hash(object);
1270
+ }
1271
+ else if(PyBytes_CharmCheck(tmpObject)) {
1272
+ str = NULL;
1273
+ PyBytes_ToString2(str, tmpObject, tmp_obj);
1274
+
1275
+ element_add_str_hash(group, str, strlen(str));
1276
+
1277
+ }
1278
+ Py_DECREF(tmpObject);
1279
+ if(tmp_obj != NULL) Py_DECREF(tmp_obj);
1280
+ }
1281
+
1282
+ if(type >= pyZR_t && type < pyGT_t) { newObject = createNewElement(NONE_G, group); }
1283
+ else {
1284
+ tmp = "invalid object type";
1285
+ goto cleanup;
1286
+ }
1287
+
1288
+ newObject->element_type = type;
1289
+ element_finish_hash(newObject, type);
1290
+
1291
+ }
1292
+ }
1293
+ // third case: a tuple with one element and
1294
+ else if(PyElement_Check(objList)) {
1295
+ // one element
1296
+ object = (Element *) objList;
1297
+ if(object->elem_initialized == FALSE) {
1298
+ tmp = "element not initialized.";
1299
+ goto cleanup;
1300
+ }
1301
+
1302
+ // Hash an element of Zr to an element of G1_t.
1303
+ if(type == pyG1_t) {
1304
+
1305
+ newObject = createNewElement(NONE_G, group);
1306
+ newObject->element_type = type;
1307
+ // hash the element to the G1_t field (uses sha1 as well)
1308
+ element_init_hash(group);
1309
+ element_add_to_hash(object);
1310
+ element_finish_hash(newObject, type);
1311
+
1312
+ }
1313
+ else {
1314
+ tmp = "can only hash an element of Zr to G1_t. Random Oracle.";
1315
+ goto cleanup;
1316
+ }
1317
+ }
1318
+ else {
1319
+ tmp = "invalid object types";
1320
+ goto cleanup;
1321
+ }
1322
+
1323
+
1324
+ return (PyObject *) newObject;
1325
+
1326
+ cleanup:
1327
+ PyErr_SetString(ElementError, tmp);
1328
+ if(newObject != NULL) Py_DECREF(newObject);
1329
+ return NULL;
1330
+ }
1331
+
1332
+ static PyObject *Element_equals(PyObject *lhs, PyObject *rhs, int opid) {
1333
+ Element *self = NULL, *other = NULL;
1334
+ signed long int z;
1335
+ int found_int = FALSE, result = -1; // , value;
1336
+
1337
+ if(opid != Py_EQ && opid != Py_NE) {
1338
+ PyErr_SetString(ElementError, "only comparison supported is '==' or '!='");
1339
+ goto cleanup;
1340
+ }
1341
+
1342
+ // check type of lhs
1343
+ if(PyElement_Check(lhs)) {
1344
+ self = (Element *) lhs;
1345
+ }
1346
+ else if(PyNumber_Check(lhs)) {
1347
+ if(PyArg_Parse(lhs, "l", &z)) {
1348
+ debug("Integer lhs: '%li'\n", z);
1349
+ }
1350
+ found_int = (z == 0 || z == 1) ? TRUE : FALSE;
1351
+ }
1352
+ else {
1353
+ PyErr_SetString(ElementError, "types supported: element or int (0 or 1)");
1354
+ goto cleanup;
1355
+ }
1356
+
1357
+ // check type of rhs
1358
+ if(PyElement_Check(rhs)) {
1359
+ other = (Element *) rhs;
1360
+ }
1361
+ else if(PyNumber_Check(rhs)) {
1362
+ if(PyArg_Parse(lhs, "l", &z)) {
1363
+ debug("Integer rhs: '%li'\n", z);
1364
+ }
1365
+ found_int = (z == 0 || z == 1) ? TRUE : FALSE;
1366
+ }
1367
+ else {
1368
+ PyErr_SetString(ElementError, "types supported: element or int (0 or 1)");
1369
+ goto cleanup;
1370
+ }
1371
+
1372
+ debug("Starting '%s'\n", __func__);
1373
+
1374
+ if(PyElement_Check(lhs) && found_int) {
1375
+ // lhs is the element type
1376
+ if(self->element_type == pyZR_t)
1377
+ result = element_is(self, z);
1378
+ }
1379
+ else if(PyElement_Check(rhs) && found_int) {
1380
+ if(other->element_type == pyZR_t)
1381
+ result = element_is(other, z);
1382
+ }
1383
+ else if(PyElement_Check(lhs) && PyElement_Check(rhs)) {
1384
+ // lhs and rhs are both elements
1385
+ if(self->elem_initialized && other->elem_initialized) {
1386
+ if(self->element_type == other->element_type)
1387
+ result = element_cmp(self, other);
1388
+ }
1389
+ else {
1390
+ debug("One of the elements is not initialized.\n");
1391
+ }
1392
+ }
1393
+
1394
+
1395
+ if(result == -1) {
1396
+ /* print error */
1397
+ PyErr_SetString(ElementError, "cannot compare different group types.\n");
1398
+ return NULL;
1399
+ }
1400
+ cleanup:
1401
+ // value = (result == 0) ? TRUE : FALSE;
1402
+
1403
+ if(opid == Py_EQ) {
1404
+ if(result == TRUE) {
1405
+ Py_RETURN_TRUE;
1406
+ }
1407
+ Py_RETURN_FALSE;
1408
+ }
1409
+ else { /* Py_NE */
1410
+ if(result == FALSE) {
1411
+ Py_RETURN_TRUE;
1412
+ }
1413
+ Py_RETURN_FALSE;
1414
+ }
1415
+ }
1416
+
1417
+ static PyObject *Element_long(PyObject *o1) {
1418
+ if(PyElement_Check(o1)) {
1419
+ Element *value = (Element *) o1;
1420
+ /* can only handle elements in ZR */
1421
+ if(value->element_type == pyZR_t) {
1422
+ mpz_t val;
1423
+ mpz_init(val);
1424
+ element_to_mpz(value, val);
1425
+ PyObject *obj = mpzToLongObj(val);
1426
+ mpz_clear(val);
1427
+ return obj;
1428
+ }
1429
+ }
1430
+ PyErr_SetString(ElementError, "cannot cast pairing object to an integer.");
1431
+ return NULL;
1432
+ }
1433
+
1434
+ static long Element_index(Element *o1) {
1435
+ long result = -1;
1436
+
1437
+ if(PyElement_Check(o1)) {
1438
+ if(o1->element_type == pyZR_t) {
1439
+ mpz_t o;
1440
+ mpz_init(o);
1441
+ element_to_mpz(o1, o);
1442
+ PyObject *temp = mpzToLongObj(o);
1443
+ result = PyObject_Hash(temp);
1444
+ mpz_clear(o);
1445
+ Py_XDECREF(temp); //PyObject_Del(temp);
1446
+ }
1447
+ }
1448
+ return result;
1449
+ }
1450
+
1451
+
1452
+ UNARY(instance_negate, 'i', Element_negate)
1453
+ UNARY(instance_invert, 'i', Element_invert)
1454
+ BINARY(instance_add, 'a', Element_add)
1455
+ BINARY(instance_sub, 's', Element_sub)
1456
+
1457
+ static PyObject *Serialize_cmp(Element *o1, PyObject *args) {
1458
+
1459
+ Element *self = NULL;
1460
+ if(!PyArg_ParseTuple(args, "O", &self)) {
1461
+ PyErr_SetString(ElementError, "invalid argument.");
1462
+ return NULL;
1463
+ }
1464
+
1465
+ if(!PyElement_Check(self)) {
1466
+ PyErr_SetString(ElementError, "not a valid element object.");
1467
+ return NULL;
1468
+ }
1469
+ if(self->elem_initialized == FALSE) {
1470
+ PyErr_SetString(ElementError, "element not initialized.");
1471
+ return NULL;
1472
+ }
1473
+
1474
+ int elem_len = 0;
1475
+ uint8_t *data_buf = NULL;
1476
+ size_t bytes_written;
1477
+
1478
+
1479
+ // printf("element type => '%d'\n", self->element_type);
1480
+ // print("test output => ", self->element_type, self->e);
1481
+ if(check_type(self->element_type) == TRUE) {
1482
+ // determine size of buffer we need to allocate
1483
+ elem_len = element_length_in_bytes(self);
1484
+ data_buf = (uint8_t *) malloc(elem_len + 1);
1485
+ memset(data_buf, 0, elem_len);
1486
+ if(data_buf == NULL) {
1487
+ PyErr_SetString(ElementError, "out of memory.");
1488
+ return NULL;
1489
+ }
1490
+
1491
+ // write to char buffer
1492
+ bytes_written = element_to_bytes(data_buf, self);
1493
+ if(elem_len != bytes_written) {
1494
+ PyErr_SetString(ElementError, "serialization failed. try again.");
1495
+ free(data_buf);
1496
+ return NULL;
1497
+ }
1498
+ debug("result => ");
1499
+ printf_buffer_as_hex(data_buf, bytes_written);
1500
+ }
1501
+ else {
1502
+ PyErr_SetString(ElementError, "invalid type.\n");
1503
+ return NULL;
1504
+ }
1505
+
1506
+ PyObject *result = PyBytes_FromFormat("%d:%s", self->element_type, (const char *) data_buf);
1507
+ debug("enc => '%s'\n", data_buf);
1508
+ free(data_buf);
1509
+
1510
+ return result;
1511
+ }
1512
+
1513
+ static PyObject *Deserialize_cmp(Element *self, PyObject *args) {
1514
+ Element *origObject = NULL;
1515
+ Pairing *group = NULL;
1516
+ PyObject *object;
1517
+
1518
+ if(PyArg_ParseTuple(args, "OO", &group, &object)) {
1519
+ VERIFY_GROUP(group);
1520
+ if(PyBytes_Check(object)) {
1521
+ uint8_t *serial_buf = (uint8_t *) PyBytes_AsString(object);
1522
+ int type = atoi((const char *) &(serial_buf[0]));
1523
+ uint8_t *base64_buf = (uint8_t *)(serial_buf + 2);
1524
+ // printf("type => %d\n", type);
1525
+ // printf("base64 dec => '%s'\n", base64_buf);
1526
+
1527
+ if(check_type(type) == TRUE && strlen((char *) base64_buf) > 0) {
1528
+ // debug("result => ");
1529
+ // printf_buffer_as_hex(binary_buf, deserialized_len);
1530
+ origObject = createNewElement(NONE_G, group);
1531
+ origObject->element_type = type;
1532
+ element_from_bytes(origObject, base64_buf);
1533
+
1534
+ return (PyObject *) origObject;
1535
+ }
1536
+ }
1537
+ PyErr_SetString(ElementError, "string object malformed.");
1538
+ return NULL;
1539
+ }
1540
+
1541
+ PyErr_SetString(ElementError, "nothing to deserialize in element.");
1542
+ return NULL;
1543
+ }
1544
+
1545
+ static PyObject *Group_Check(Element *self, PyObject *args) {
1546
+
1547
+ Pairing *group = NULL;
1548
+ Element *object = NULL;
1549
+ if(PyArg_ParseTuple(args, "OO", &group, &object)) {
1550
+ VERIFY_GROUP(group);
1551
+ if(PyElement_Check(object)) {
1552
+ if(check_membership(object) == TRUE) {
1553
+ Py_INCREF(Py_True);
1554
+ return Py_True;
1555
+ }
1556
+ else {
1557
+ Py_INCREF(Py_False);
1558
+ return Py_False;
1559
+ }
1560
+ }
1561
+ }
1562
+
1563
+ PyErr_SetString(ElementError, "invalid object type.");
1564
+ return NULL;
1565
+ }
1566
+
1567
+ static PyObject *Get_Order(Element *self, PyObject *args) {
1568
+
1569
+ Pairing *group = NULL;
1570
+ if(!PyArg_ParseTuple(args, "O", &group)) {
1571
+ PyErr_SetString(ElementError, "invalid group object.");
1572
+ return NULL;
1573
+ }
1574
+
1575
+ VERIFY_GROUP(group);
1576
+ mpz_t d;
1577
+ mpz_init(d);
1578
+ object_to_mpz(group->order, d);
1579
+ PyObject *object = (PyObject *) mpzToLongObj(d);
1580
+ mpz_clear(d);
1581
+ return object; /* returns a PyInt */
1582
+ }
1583
+
1584
+ /* TODO: move to cryptobase */
1585
+ PyObject *AES_Encrypt(Element *self, PyObject *args)
1586
+ {
1587
+ PyObject *keyObj = NULL, *tmp_obj = NULL; // string or bytes object
1588
+ char *messageStr;
1589
+ Py_ssize_t m_len = 0;
1590
+
1591
+ if(!PyArg_ParseTuple(args, "Os#", &keyObj, &messageStr, &m_len)) {
1592
+ PyErr_SetString(ElementError, "invalid arguments.");
1593
+ return NULL;
1594
+ }
1595
+
1596
+ if((m_len % aes_block_size) != 0) {
1597
+ PyErr_SetString(ElementError, "message not 16-byte block aligned. Add some padding.");
1598
+ return NULL;
1599
+ }
1600
+
1601
+ char *keyStr;
1602
+ if(PyBytes_CharmCheck(keyObj)) {
1603
+ PyBytes_ToString2(keyStr, keyObj, tmp_obj);
1604
+ //printf("key => '%s'\n", keyStr);
1605
+ //printf("message => '%s'\n", messageStr);
1606
+ // perform AES encryption using miracl
1607
+ char *cipher = NULL;
1608
+
1609
+ int c_len = aes_encrypt(keyStr, messageStr, (int) m_len, &cipher);
1610
+
1611
+ PyObject *str = PyBytes_FromStringAndSize((const char *) cipher, c_len);
1612
+ free(cipher);
1613
+ if(tmp_obj != NULL) Py_DECREF(tmp_obj);
1614
+ return str;
1615
+ }
1616
+
1617
+ PyErr_SetString(ElementError, "invalid objects.");
1618
+ return NULL;
1619
+ }
1620
+
1621
+ PyObject *AES_Decrypt(Element *self, PyObject *args)
1622
+ {
1623
+ PyObject *keyObj = NULL, *tmp_obj = NULL; // string or bytes object
1624
+ char *ciphertextStr;
1625
+ Py_ssize_t c_len = 0;
1626
+
1627
+ if(!PyArg_ParseTuple(args, "Os#", &keyObj, &ciphertextStr, &c_len)) {
1628
+ PyErr_SetString(ElementError, "invalid arguments.");
1629
+ return NULL;
1630
+ }
1631
+
1632
+ char *keyStr;
1633
+ if(PyBytes_CharmCheck(keyObj)) {
1634
+ PyBytes_ToString2(keyStr, keyObj, tmp_obj);
1635
+ // printf("key => '%s'\n", keyStr);
1636
+ // printf("message => '%s'\n", ciphertextStr);
1637
+ // perform AES encryption using miracl
1638
+ char *message = NULL;
1639
+
1640
+ int m_len = aes_decrypt(keyStr, ciphertextStr, (int) c_len, &message);
1641
+
1642
+ PyObject *str = PyBytes_FromStringAndSize((const char *) message, m_len);
1643
+ free(message);
1644
+ if(tmp_obj != NULL) Py_DECREF(tmp_obj);
1645
+ return str;
1646
+ }
1647
+
1648
+ PyErr_SetString(ElementError, "invalid objects.");
1649
+ return NULL;
1650
+
1651
+ }
1652
+
1653
+ #ifdef BENCHMARK_ENABLED
1654
+
1655
+ #define BenchmarkIdentifier 1
1656
+ #define GET_RESULTS_FUNC GetResultsWithPair
1657
+ #define GROUP_OBJECT Pairing
1658
+ #define BENCH_ERROR ElementError
1659
+ /* helper function for granularBenchmar */
1660
+ PyObject *PyCreateList(Operations *gBench, MeasureType type)
1661
+ {
1662
+ int countZR = -1, countG1 = -1, countG2 = -1, countGT = -1;
1663
+ GetField(countZR, type, pyZR_t, gBench);
1664
+ GetField(countG1, type, pyG1_t, gBench);
1665
+ GetField(countG2, type, pyG2_t, gBench);
1666
+ GetField(countGT, type, pyGT_t, gBench);
1667
+
1668
+ PyObject *objList = Py_BuildValue("[iiii]", countZR, countG1, countG2, countGT);
1669
+ return objList;
1670
+ }
1671
+
1672
+ #include "benchmark_util.c"
1673
+
1674
+ #endif
1675
+
1676
+
1677
+ #if PY_MAJOR_VERSION >= 3
1678
+
1679
+ PyTypeObject PairingType = {
1680
+ PyVarObject_HEAD_INIT(NULL, 0)
1681
+ "pairing.Pairing", /*tp_name*/
1682
+ sizeof(Pairing), /*tp_basicsize*/
1683
+ 0, /*tp_itemsize*/
1684
+ (destructor)Pairing_dealloc, /*tp_dealloc*/
1685
+ 0, /*tp_print*/
1686
+ 0, /*tp_getattr*/
1687
+ 0, /*tp_setattr*/
1688
+ 0, /*tp_reserved*/
1689
+ (reprfunc)Pairing_print, /*tp_repr*/
1690
+ 0, /*tp_as_number*/
1691
+ 0, /*tp_as_sequence*/
1692
+ 0, /*tp_as_mapping*/
1693
+ 0, /*tp_hash */
1694
+ 0, /*tp_call*/
1695
+ (reprfunc)Pairing_print, /*tp_str*/
1696
+ 0, /*tp_getattro*/
1697
+ 0, /*tp_setattro*/
1698
+ 0, /*tp_as_buffer*/
1699
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1700
+ "Pairing group parameters", /* tp_doc */
1701
+ 0, /* tp_traverse */
1702
+ 0, /* tp_clear */
1703
+ 0, /* tp_richcompare */
1704
+ 0, /* tp_weaklistoffset */
1705
+ 0, /* tp_iter */
1706
+ 0, /* tp_iternext */
1707
+ 0, /* tp_methods */
1708
+ 0, /* tp_members */
1709
+ 0, /* tp_getset */
1710
+ 0, /* tp_base */
1711
+ 0, /* tp_dict */
1712
+ 0, /* tp_descr_get */
1713
+ 0, /* tp_descr_set */
1714
+ 0, /* tp_dictoffset */
1715
+ (initproc)Pairing_init, /* tp_init */
1716
+ 0, /* tp_alloc */
1717
+ Pairing_new, /* tp_new */
1718
+ };
1719
+ #else
1720
+ /* python 2.x series */
1721
+ PyTypeObject PairingType = {
1722
+ PyObject_HEAD_INIT(NULL)
1723
+ 0, /*ob_size*/
1724
+ "pairing.Pairing", /*tp_name*/
1725
+ sizeof(Pairing), /*tp_basicsize*/
1726
+ 0, /*tp_itemsize*/
1727
+ (destructor)Pairing_dealloc, /*tp_dealloc*/
1728
+ 0, /*tp_print*/
1729
+ 0, /*tp_getattr*/
1730
+ 0, /*tp_setattr*/
1731
+ 0, /*tp_compare*/
1732
+ (reprfunc)Pairing_print, /*tp_repr*/
1733
+ 0, /*tp_as_number*/
1734
+ 0, /*tp_as_sequence*/
1735
+ 0, /*tp_as_mapping*/
1736
+ 0, /*tp_hash */
1737
+ 0, /*tp_call*/
1738
+ (reprfunc)Pairing_print, /*tp_str*/
1739
+ 0, /*tp_getattro*/
1740
+ 0, /*tp_setattro*/
1741
+ 0, /*tp_as_buffer*/
1742
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1743
+ "Pairing group parameters", /* tp_doc */
1744
+ 0, /* tp_traverse */
1745
+ 0, /* tp_clear */
1746
+ 0, /* tp_richcompare */
1747
+ 0, /* tp_weaklistoffset */
1748
+ 0, /* tp_iter */
1749
+ 0, /* tp_iternext */
1750
+ 0, /* tp_methods */
1751
+ 0, /* tp_members */
1752
+ 0, /* tp_getset */
1753
+ 0, /* tp_base */
1754
+ 0, /* tp_dict */
1755
+ 0, /* tp_descr_get */
1756
+ 0, /* tp_descr_set */
1757
+ 0, /* tp_dictoffset */
1758
+ (initproc) Pairing_init, /* tp_init */
1759
+ 0, /* tp_alloc */
1760
+ Pairing_new, /* tp_new */
1761
+ };
1762
+
1763
+ #endif
1764
+
1765
+ #if PY_MAJOR_VERSION >= 3
1766
+ PyNumberMethods element_number = {
1767
+ instance_add, /* nb_add */
1768
+ instance_sub, /* nb_subtract */
1769
+ Element_mul, /* nb_multiply */
1770
+ 0, /* nb_remainder */
1771
+ 0, /* nb_divmod */
1772
+ Element_pow, /* nb_power */
1773
+ instance_negate, /* nb_negative */
1774
+ 0, /* nb_positive */
1775
+ 0, /* nb_absolute */
1776
+ 0, /* nb_bool */
1777
+ (unaryfunc)instance_invert, /* nb_invert */
1778
+ 0, /* nb_lshift */
1779
+ 0, /* nb_rshift */
1780
+ 0, /* nb_and */
1781
+ 0, /* nb_xor */
1782
+ 0, /* nb_or */
1783
+ (unaryfunc)Element_long, /* nb_int */
1784
+ 0, /* nb_reserved */
1785
+ 0, /* nb_float */
1786
+ instance_add, /* nb_inplace_add */
1787
+ instance_sub, /* nb_inplace_subtract */
1788
+ Element_mul, /* nb_inplace_multiply */
1789
+ 0, /* nb_inplace_remainder */
1790
+ Element_pow, /* nb_inplace_power */
1791
+ 0, /* nb_inplace_lshift */
1792
+ 0, /* nb_inplace_rshift */
1793
+ 0, /* nb_inplace_and */
1794
+ 0, /* nb_inplace_xor */
1795
+ 0, /* nb_inplace_or */
1796
+ 0, /* nb_floor_divide */
1797
+ Element_div, /* nb_true_divide */
1798
+ 0, /* nb_inplace_floor_divide */
1799
+ Element_div, /* nb_inplace_true_divide */
1800
+ 0, /* nb_index */
1801
+ };
1802
+
1803
+ PyTypeObject ElementType = {
1804
+ PyVarObject_HEAD_INIT(NULL, 0)
1805
+ "pairing.Element", /*tp_name*/
1806
+ sizeof(Element), /*tp_basicsize*/
1807
+ 0, /*tp_itemsize*/
1808
+ (destructor)Element_dealloc, /*tp_dealloc*/
1809
+ 0, /*tp_print*/
1810
+ 0, /*tp_getattr*/
1811
+ 0, /*tp_setattr*/
1812
+ 0, /*tp_reserved*/
1813
+ (reprfunc)Element_print, /*tp_repr*/
1814
+ &element_number, /*tp_as_number*/
1815
+ 0, /*tp_as_sequence*/
1816
+ 0, /*tp_as_mapping*/
1817
+ (hashfunc)Element_index, /*tp_hash */
1818
+ 0, /*tp_call*/
1819
+ 0, /*tp_str*/
1820
+ 0, /*tp_getattro*/
1821
+ 0, /*tp_setattro*/
1822
+ 0, /*tp_as_buffer*/
1823
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1824
+ "Pairing objects", /* tp_doc */
1825
+ 0, /* tp_traverse */
1826
+ 0, /* tp_clear */
1827
+ Element_equals, /* tp_richcompare */
1828
+ 0, /* tp_weaklistoffset */
1829
+ 0, /* tp_iter */
1830
+ 0, /* tp_iternext */
1831
+ Element_methods, /* tp_methods */
1832
+ Element_members, /* tp_members */
1833
+ 0, /* tp_getset */
1834
+ 0, /* tp_base */
1835
+ 0, /* tp_dict */
1836
+ 0, /* tp_descr_get */
1837
+ 0, /* tp_descr_set */
1838
+ 0, /* tp_dictoffset */
1839
+ (initproc)Element_init, /* tp_init */
1840
+ 0, /* tp_alloc */
1841
+ Element_new, /* tp_new */
1842
+ };
1843
+ #else
1844
+ /* python 2.x series */
1845
+ PyNumberMethods element_number = {
1846
+ instance_add, /* nb_add */
1847
+ instance_sub, /* nb_subtract */
1848
+ Element_mul, /* nb_multiply */
1849
+ Element_div, /* nb_divide */
1850
+ 0, /* nb_remainder */
1851
+ 0, /* nb_divmod */
1852
+ Element_pow, /* nb_power */
1853
+ instance_negate, /* nb_negative */
1854
+ 0, /* nb_positive */
1855
+ 0, /* nb_absolute */
1856
+ 0, /* nb_nonzero */
1857
+ (unaryfunc)instance_invert, /* nb_invert */
1858
+ 0, /* nb_lshift */
1859
+ 0, /* nb_rshift */
1860
+ 0, /* nb_and */
1861
+ 0, /* nb_xor */
1862
+ 0, /* nb_or */
1863
+ 0, /* nb_coerce */
1864
+ 0, /* nb_int */
1865
+ (unaryfunc)Element_long, /* nb_long */
1866
+ 0, /* nb_float */
1867
+ 0, /* nb_oct */
1868
+ 0, /* nb_hex */
1869
+ instance_add, /* nb_inplace_add */
1870
+ instance_sub, /* nb_inplace_subtract */
1871
+ Element_mul, /* nb_inplace_multiply */
1872
+ Element_div, /* nb_inplace_divide */
1873
+ 0, /* nb_inplace_remainder */
1874
+ 0, /* nb_inplace_power */
1875
+ 0, /* nb_inplace_lshift */
1876
+ 0, /* nb_inplace_rshift */
1877
+ 0, /* nb_inplace_and */
1878
+ 0, /* nb_inplace_xor */
1879
+ 0, /* nb_inplace_or */
1880
+ 0, /* nb_floor_divide */
1881
+ 0, /* nb_true_divide */
1882
+ 0, /* nb_inplace_floor_divide */
1883
+ 0, /* nb_inplace_true_divide */
1884
+ 0, /* nb_index */
1885
+ };
1886
+
1887
+ PyTypeObject ElementType = {
1888
+ PyObject_HEAD_INIT(NULL)
1889
+ 0, /*ob_size*/
1890
+ "pairing.Element", /*tp_name*/
1891
+ sizeof(Element), /*tp_basicsize*/
1892
+ 0, /*tp_itemsize*/
1893
+ (destructor)Element_dealloc, /*tp_dealloc*/
1894
+ 0, /*tp_print*/
1895
+ 0, /*tp_getattr*/
1896
+ 0, /*tp_setattr*/
1897
+ 0, /*tp_compare*/
1898
+ 0, /*tp_repr*/
1899
+ &element_number, /*tp_as_number*/
1900
+ 0, /*tp_as_sequence*/
1901
+ 0, /*tp_as_mapping*/
1902
+ (hashfunc)Element_index, /*tp_hash */
1903
+ 0, /*tp_call*/
1904
+ (reprfunc)Element_print, /*tp_str*/
1905
+ 0, /*tp_getattro*/
1906
+ 0, /*tp_setattro*/
1907
+ 0, /*tp_as_buffer*/
1908
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
1909
+ "Pairing objects", /* tp_doc */
1910
+ 0, /* tp_traverse */
1911
+ 0, /* tp_clear */
1912
+ Element_equals, /* tp_richcompare */
1913
+ 0, /* tp_weaklistoffset */
1914
+ 0, /* tp_iter */
1915
+ 0, /* tp_iternext */
1916
+ Element_methods, /* tp_methods */
1917
+ Element_members, /* tp_members */
1918
+ 0, /* tp_getset */
1919
+ 0, /* tp_base */
1920
+ 0, /* tp_dict */
1921
+ 0, /* tp_descr_get */
1922
+ 0, /* tp_descr_set */
1923
+ 0, /* tp_dictoffset */
1924
+ (initproc) Element_init, /* tp_init */
1925
+ 0, /* tp_alloc */
1926
+ Element_new, /* tp_new */
1927
+ };
1928
+
1929
+ #endif
1930
+
1931
+
1932
+ struct module_state {
1933
+ PyObject *error;
1934
+ #ifdef BENCHMARK_ENABLED
1935
+ Benchmark *dBench;
1936
+ #endif
1937
+ };
1938
+
1939
+ #if PY_MAJOR_VERSION >= 3
1940
+ #define GETSTATE(m) ((struct module_state *) PyModule_GetState(m))
1941
+ #else
1942
+ #define GETSTATE(m) (&_state)
1943
+ static struct module_state _state;
1944
+ #endif
1945
+
1946
+ // end
1947
+ PyMemberDef Element_members[] = {
1948
+ {"type", T_INT, offsetof(Element, element_type), 0,
1949
+ "group type"},
1950
+ {"initialized", T_INT, offsetof(Element, elem_initialized), 0,
1951
+ "determine initialization status"},
1952
+ {NULL} /* Sentinel */
1953
+ };
1954
+
1955
+ PyMethodDef Element_methods[] = {
1956
+ {"initPP", (PyCFunction)Element_initPP, METH_NOARGS, "Initialize the pre-processing field of element."},
1957
+ {"set", (PyCFunction)Element_set, METH_VARARGS, "Set an element to a fixed value."},
1958
+ {"setPoint", (PyCFunction)Element_setxy, METH_VARARGS, "Set x and y coordinates of a G1 element object."},
1959
+ {NULL} /* Sentinel */
1960
+ };
1961
+
1962
+ PyMethodDef pairing_methods[] = {
1963
+ {"init", (PyCFunction)Element_elem, METH_VARARGS, "Create an element in a specific group: G1, G2, GT or Zr"},
1964
+ {"random", (PyCFunction)Element_random, METH_VARARGS, "Return a random element in a specific group: G1_t, G2, Zr"},
1965
+ {"H", (PyCFunction)Element_hash, METH_VARARGS, "Hash an element type to a specific field: Zr, G1_t, or G2"},
1966
+ {"serialize", (PyCFunction)Serialize_cmp, METH_VARARGS, "Serialize an element type into bytes."},
1967
+ {"deserialize", (PyCFunction)Deserialize_cmp, METH_VARARGS, "De-serialize an bytes object into an element object"},
1968
+ {"ismember", (PyCFunction) Group_Check, METH_VARARGS, "Group membership test for element objects."},
1969
+ {"order", (PyCFunction) Get_Order, METH_VARARGS, "Get the group order for a particular field."},
1970
+
1971
+ {"pair", (PyCFunction)Apply_pairing, METH_VARARGS, "Apply pairing between an element of G1_t and G2 and returns an element mapped to GT"},
1972
+ {"hashPair", (PyCFunction)sha2_hash, METH_VARARGS, "Compute a sha1 hash of an element type"},
1973
+ // {"SymEnc", (PyCFunction) AES_Encrypt, METH_VARARGS, "AES encryption args: key (bytes or str), message (str)"},
1974
+ // {"SymDec", (PyCFunction) AES_Decrypt, METH_VARARGS, "AES decryption args: key (bytes or str), ciphertext (str)"},
1975
+ #ifdef BENCHMARK_ENABLED
1976
+ {"InitBenchmark", (PyCFunction)InitBenchmark, METH_VARARGS, "Initialize a benchmark object"},
1977
+ {"StartBenchmark", (PyCFunction)StartBenchmark, METH_VARARGS, "Start a new benchmark with some options"},
1978
+ {"EndBenchmark", (PyCFunction)EndBenchmark, METH_VARARGS, "End a given benchmark"},
1979
+ {"GetBenchmark", (PyCFunction)GetBenchmark, METH_VARARGS, "Returns contents of a benchmark object"},
1980
+ {"GetGeneralBenchmarks", (PyCFunction)GetAllBenchmarks, METH_VARARGS, "Retrieve general benchmark info as a dictionary"},
1981
+ {"GetGranularBenchmarks", (PyCFunction) GranularBenchmark, METH_VARARGS, "Retrieve granular benchmarks as a dictionary"},
1982
+ #endif
1983
+ {NULL} /* Sentinel */
1984
+ };
1985
+
1986
+ #if PY_MAJOR_VERSION >= 3
1987
+ static int pairings_traverse(PyObject *m, visitproc visit, void *arg) {
1988
+ Py_VISIT(GETSTATE(m)->error);
1989
+ return 0;
1990
+ }
1991
+
1992
+ static int pairings_clear(PyObject *m) {
1993
+ Py_CLEAR(GETSTATE(m)->error);
1994
+ Py_XDECREF(ElementError);
1995
+ return 0;
1996
+ }
1997
+
1998
+ static int pairings_free(PyObject *m) {
1999
+ // Defensive check: Only call miracl_clean if module state is valid
2000
+ // This prevents hangs during Python 3.12+ shutdown when module state
2001
+ // may be corrupted or already cleaned up
2002
+ if(m != NULL && pairing_init_finished == FALSE) {
2003
+ // Additional safety: Check if we're in a valid state to clean up
2004
+ // Avoid calling miracl_clean() if Python is shutting down abnormally
2005
+ if(!CHARM_PY_IS_FINALIZING()) {
2006
+ miracl_clean(); // mirsys was called
2007
+ }
2008
+ }
2009
+ return 0;
2010
+ }
2011
+
2012
+ static struct PyModuleDef moduledef = {
2013
+ PyModuleDef_HEAD_INIT,
2014
+ "pairing",
2015
+ NULL,
2016
+ sizeof(struct module_state),
2017
+ pairing_methods,
2018
+ NULL,
2019
+ pairings_traverse,
2020
+ (inquiry) pairings_clear,
2021
+ (freefunc) pairings_free
2022
+ };
2023
+
2024
+ #define CLEAN_EXIT goto LEAVE;
2025
+ #define INITERROR return NULL
2026
+ PyMODINIT_FUNC
2027
+ PyInit_pairing(void) {
2028
+ #else
2029
+ #define CLEAN_EXIT goto LEAVE;
2030
+ #define INITERROR return
2031
+ void initpairing(void) {
2032
+ #endif
2033
+ PyObject* m;
2034
+
2035
+ #if PY_MAJOR_VERSION >= 3
2036
+ m = PyModule_Create(&moduledef);
2037
+ #else
2038
+ m = Py_InitModule("pairing", pairing_methods);
2039
+ #endif
2040
+
2041
+ if(PyType_Ready(&PairingType) < 0)
2042
+ CLEAN_EXIT;
2043
+ if(PyType_Ready(&ElementType) < 0)
2044
+ CLEAN_EXIT;
2045
+ #ifdef BENCHMARK_ENABLED
2046
+ if(import_benchmark() < 0)
2047
+ CLEAN_EXIT;
2048
+ if(PyType_Ready(&BenchmarkType) < 0)
2049
+ CLEAN_EXIT;
2050
+ if(PyType_Ready(&OperationsType) < 0)
2051
+ CLEAN_EXIT;
2052
+ #endif
2053
+
2054
+ struct module_state *st = GETSTATE(m);
2055
+ st->error = PyErr_NewException("pairing.Error", NULL, NULL);
2056
+ if(st->error == NULL)
2057
+ CLEAN_EXIT;
2058
+ ElementError = st->error;
2059
+ Py_INCREF(ElementError);
2060
+
2061
+ Py_INCREF(&ElementType);
2062
+ PyModule_AddObject(m, "pc_element", (PyObject *)&ElementType);
2063
+ Py_INCREF(&PairingType);
2064
+ PyModule_AddObject(m, "pairing", (PyObject *)&PairingType);
2065
+
2066
+ PyModule_AddIntConstant(m, "ZR", pyZR_t);
2067
+ PyModule_AddIntConstant(m, "G1", pyG1_t);
2068
+ PyModule_AddIntConstant(m, "G2", pyG2_t);
2069
+ PyModule_AddIntConstant(m, "GT", pyGT_t);
2070
+
2071
+ #ifdef BENCHMARK_ENABLED
2072
+ ADD_BENCHMARK_OPTIONS(m);
2073
+ PyModule_AddStringConstant(m, "Pair", _PAIR_OPT);
2074
+ PyModule_AddStringConstant(m, "Granular", _GRAN_OPT);
2075
+ #endif
2076
+
2077
+ // builtin curves
2078
+ PyModule_AddIntConstant(m, "MNT160", MNT160);
2079
+ PyModule_AddIntConstant(m, "BN256", BN256);
2080
+ PyModule_AddIntConstant(m, "SS512", SS512);
2081
+ PyModule_AddIntConstant(m, "SS1536", SS1536);
2082
+
2083
+ LEAVE:
2084
+ if (PyErr_Occurred()) {
2085
+ PyErr_Clear();
2086
+ Py_XDECREF(m);
2087
+ INITERROR;
2088
+ }
2089
+ pairing_init_finished = TRUE;
2090
+
2091
+ #if PY_MAJOR_VERSION >= 3
2092
+ return m;
2093
+ #endif
2094
+ }