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,220 @@
1
+ '''
2
+ Echo Broadcast Protocol Implementation
3
+
4
+ Implements Bracha's reliable broadcast protocol for Byzantine fault tolerance.
5
+ Ensures all honest parties receive the same message from each sender.
6
+
7
+ | Based on: Bracha's Reliable Broadcast (1987)
8
+ | Reference: "Asynchronous Byzantine Agreement Protocols" - Gabriel Bracha
9
+ |
10
+ | Used in: DKLS23 Threshold ECDSA DKG for broadcast consistency verification
11
+
12
+ :Authors: Elton de Souza
13
+ :Date: 01/2026
14
+ '''
15
+
16
+ import hashlib
17
+ import json
18
+ import logging
19
+ from typing import Any, Dict, List, Optional, Set, Tuple, Union
20
+
21
+ PartyId = int
22
+
23
+ # Module logger
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ class EchoBroadcast:
28
+ """
29
+ Echo broadcast protocol for Byzantine fault tolerant message delivery.
30
+
31
+ Ensures that if any honest party accepts a message from a sender,
32
+ all honest parties accept the same message (consistency).
33
+
34
+ This implements echo broadcast verification as used in distributed
35
+ key generation (DKG) protocols to prevent equivocation attacks where
36
+ a malicious sender sends different messages to different recipients.
37
+
38
+ Attributes:
39
+ n: Number of parties in the protocol
40
+ f: Byzantine fault threshold (default: (n-1)//3)
41
+
42
+ Example:
43
+ >>> broadcast = EchoBroadcast(num_parties=5)
44
+ >>> msg = broadcast.create_broadcast_message(1, {'value': 42})
45
+ >>> 'sender_id' in msg and 'hash' in msg
46
+ True
47
+ """
48
+
49
+ def __init__(self, num_parties: int, fault_threshold: Optional[int] = None):
50
+ """
51
+ Initialize echo broadcast with party count and fault threshold.
52
+
53
+ Parameters
54
+ ----------
55
+ num_parties : int
56
+ Total number of parties in the protocol
57
+ fault_threshold : int, optional
58
+ Maximum number of Byzantine (faulty) parties tolerated.
59
+ Defaults to (num_parties - 1) // 3 for optimal Byzantine tolerance.
60
+ """
61
+ if num_parties < 1:
62
+ raise ValueError("num_parties must be at least 1")
63
+
64
+ self.n = num_parties
65
+ self.f = fault_threshold if fault_threshold is not None else (num_parties - 1) // 3
66
+
67
+ if self.f < 0:
68
+ raise ValueError("fault_threshold must be non-negative")
69
+
70
+ def compute_message_hash(self, message: Any) -> bytes:
71
+ """
72
+ Compute hash of a message for echo comparison.
73
+
74
+ Parameters
75
+ ----------
76
+ message : Any
77
+ The message to hash. Can be bytes, dict, or any serializable type.
78
+
79
+ Returns
80
+ -------
81
+ bytes
82
+ SHA-256 hash of the message
83
+ """
84
+ if isinstance(message, bytes):
85
+ data = message
86
+ elif isinstance(message, dict):
87
+ # Serialize dict to bytes deterministically
88
+ data = json.dumps(message, sort_keys=True, default=str).encode()
89
+ else:
90
+ data = str(message).encode()
91
+
92
+ return hashlib.sha256(data).digest()
93
+
94
+ def create_broadcast_message(self, party_id: int, message: Any) -> Dict[str, Any]:
95
+ """
96
+ Create a broadcast message with its hash for echo verification.
97
+
98
+ Parameters
99
+ ----------
100
+ party_id : int
101
+ The sender's party identifier
102
+ message : Any
103
+ The message content to broadcast
104
+
105
+ Returns
106
+ -------
107
+ dict
108
+ Broadcast message containing:
109
+ - sender_id: The sender's party ID
110
+ - message: The original message content
111
+ - hash: SHA-256 hash of the message
112
+ """
113
+ msg_hash = self.compute_message_hash(message)
114
+ return {
115
+ 'sender_id': party_id,
116
+ 'message': message,
117
+ 'hash': msg_hash
118
+ }
119
+
120
+ def process_echo(
121
+ self,
122
+ verifier_id: int,
123
+ sender_id: int,
124
+ msg_hash: bytes,
125
+ echo_state: Optional[Dict[int, Dict[int, bytes]]] = None
126
+ ) -> Dict[int, Dict[int, bytes]]:
127
+ """
128
+ Process an echo from another party.
129
+
130
+ Records what message hash a verifier claims to have received from a sender.
131
+
132
+ Parameters
133
+ ----------
134
+ verifier_id : int
135
+ ID of the party reporting what they received
136
+ sender_id : int
137
+ ID of the original sender
138
+ msg_hash : bytes
139
+ Hash of the message the verifier claims to have received
140
+ echo_state : dict, optional
141
+ Current echo state to update. If None, creates new state.
142
+
143
+ Returns
144
+ -------
145
+ dict
146
+ Updated echo state: {verifier_id: {sender_id: msg_hash}}
147
+ """
148
+ if echo_state is None:
149
+ echo_state = {}
150
+ if verifier_id not in echo_state:
151
+ echo_state[verifier_id] = {}
152
+ echo_state[verifier_id][sender_id] = msg_hash
153
+ return echo_state
154
+
155
+ def verify_consistency(self, echo_msgs: Dict[int, Dict[int, bytes]]) -> bool:
156
+ """
157
+ Verify all parties received consistent messages from each sender.
158
+
159
+ Checks that for each sender, all verifiers report the same message hash.
160
+ If any sender sent different messages to different recipients (equivocation),
161
+ raises ValueError with details about the inconsistency.
162
+
163
+ Parameters
164
+ ----------
165
+ echo_msgs : dict
166
+ Echo state mapping {verifier_id: {sender_id: msg_hash}}
167
+
168
+ Returns
169
+ -------
170
+ bool
171
+ True if all messages are consistent
172
+
173
+ Raises
174
+ ------
175
+ ValueError
176
+ If broadcast inconsistency is detected, with details about which
177
+ sender sent different messages to different recipients
178
+
179
+ Example:
180
+ >>> broadcast = EchoBroadcast(num_parties=3)
181
+ >>> # All parties received same hash from sender 1
182
+ >>> echo_msgs = {1: {1: b'hash1'}, 2: {1: b'hash1'}, 3: {1: b'hash1'}}
183
+ >>> broadcast.verify_consistency(echo_msgs)
184
+ True
185
+ """
186
+ if not echo_msgs:
187
+ return True
188
+
189
+ # Build a map: sender_id -> {hash -> set of receivers who got that hash}
190
+ sender_to_hashes: Dict[int, Dict[bytes, Set[int]]] = {}
191
+
192
+ for verifier_id, received_hashes in echo_msgs.items():
193
+ for sender_id, msg_hash in received_hashes.items():
194
+ if sender_id not in sender_to_hashes:
195
+ sender_to_hashes[sender_id] = {}
196
+
197
+ # Convert hash to bytes if needed
198
+ hash_key = msg_hash if isinstance(msg_hash, bytes) else bytes(msg_hash)
199
+
200
+ if hash_key not in sender_to_hashes[sender_id]:
201
+ sender_to_hashes[sender_id][hash_key] = set()
202
+ sender_to_hashes[sender_id][hash_key].add(verifier_id)
203
+
204
+ # Check consistency: each sender should have only one unique hash
205
+ for sender_id, hash_to_receivers in sender_to_hashes.items():
206
+ if len(hash_to_receivers) > 1:
207
+ # Found inconsistency - sender sent different messages
208
+ receivers_by_hash = [
209
+ f"hash {i+1}: receivers {sorted(receivers)}"
210
+ for i, (_, receivers) in enumerate(hash_to_receivers.items())
211
+ ]
212
+ raise ValueError(
213
+ f"Broadcast inconsistency detected: Party {sender_id} sent "
214
+ f"different messages to different receivers. "
215
+ f"{'; '.join(receivers_by_hash)}"
216
+ )
217
+
218
+ logger.debug("Broadcast consistency verified for %d senders", len(sender_to_hashes))
219
+ return True
220
+
@@ -0,0 +1,100 @@
1
+ '''
2
+ :Date: Jul 5, 2011
3
+ :Authors: Gary Belvin
4
+
5
+ This class facilitates conversion between domain spaces
6
+ '''
7
+ from charm.core.math.integer import integer
8
+ from charm.toolbox.bitstring import Bytes,py3
9
+ import math
10
+
11
+ class Conversion(object):
12
+ '''
13
+ The goal is to convert arbitrarily between any of the following types
14
+
15
+ Input types:
16
+
17
+ * bytes
18
+ * Bytes
19
+ * int
20
+ * Integer Element
21
+ * Modular Integer Element
22
+
23
+ Output types:
24
+
25
+ * int
26
+ * Group element
27
+ * Integer element
28
+ * Integer element mod N
29
+ '''
30
+
31
+ @classmethod
32
+ def bytes2element(self, bytestr):
33
+ '''Converts a byte string to a group element'''
34
+ pass
35
+ @classmethod
36
+ def bytes2integer(self, bytestr):
37
+ '''Converts a bytes string to an integer object'''
38
+ return integer(bytestr)
39
+ @classmethod
40
+ def str2bytes(self, strobj):
41
+ return Bytes(strobj, 'utf-8')
42
+ @classmethod
43
+ def bytes2str(self, byteobj):
44
+ return Bytes.decode(byteobj, 'utf-8')
45
+
46
+ @classmethod
47
+ def int2bin(self, intobj):
48
+ _str = bin(int(intobj))
49
+ _array = []
50
+ for i in range(2, len(_str)):
51
+ _array.append(int(_str[i]))
52
+ return _array
53
+
54
+ @classmethod
55
+ def OS2IP(self, bytestr, element = False):
56
+ '''
57
+ :Return: A python ``int`` if element is False. An ``integer.Element`` if element is True
58
+
59
+ Converts a byte string to an integer
60
+ '''
61
+ val = 0
62
+ for i in range(len(bytestr)):
63
+ byt = bytestr[len(bytestr)-1-i]
64
+ if not py3: byt = ord(byt)
65
+ val += byt << (8 *i)
66
+
67
+ #These lines convert val into a binary string of 1's and 0's
68
+ #bstr = bin(val)[2:] #cut out the 0b header
69
+ #val = int(bstr, 2)
70
+ #return val
71
+ if element:
72
+ return integer(val)
73
+ else:
74
+ return val
75
+ @classmethod
76
+ def IP2OS(self, number, xLen=None):
77
+ '''
78
+ :Parameters:
79
+ - ``number``: is a normal integer, not modular
80
+ - ``xLen``: is the intended length of the resulting octet string
81
+
82
+ Converts an integer into a byte string'''
83
+
84
+ ba = bytearray()
85
+ x = 0
86
+ if type(number) == integer:
87
+ x = int(number)
88
+ elif type(number) == int:
89
+ x = number
90
+ elif not py3 and type(number) == long:
91
+ x = number
92
+
93
+ if xLen == None:
94
+ xLen = int(math.ceil(math.log(x, 2) / 8.0))
95
+
96
+ for i in range(xLen):
97
+ ba.append(x % 256)
98
+ x = x >> 8
99
+ ba.reverse()
100
+ return Bytes(ba)
@@ -0,0 +1,149 @@
1
+
2
+ """ Openssl Elliptic Curve Parameters
3
+ Run ``openssl ecparam -list_curves`` to show all of the curve identifiers supported in OpenSSL.
4
+
5
+ import the ``charm.toolbox.eccurve`` module for the full listing from Charm.
6
+ """
7
+
8
+ prime192v1 = 409
9
+ prime192v2 = 410
10
+ prime192v3 = 411
11
+ prime239v1 = 412
12
+ prime239v2 = 413
13
+ prime239v3 = 414
14
+ prime256v1 = 415
15
+
16
+ c2pnb163v1 = 684
17
+ c2pnb163v2 = 685
18
+ c2pnb163v3 = 686
19
+ c2pnb176v1 = 687
20
+ c2tnb191v1 = 688
21
+ c2tnb191v2 = 689
22
+ c2tnb191v3 = 690
23
+ c2onb191v4 = 691
24
+ c2onb191v5 = 692
25
+ c2pnb208w1 = 693
26
+
27
+ c2tnb239v1 = 694
28
+ c2tnb239v2 = 695
29
+ c2tnb239v3 = 696
30
+ c2onb239v4 = 697
31
+ c2onb239v5 = 698
32
+
33
+ c2pnb272w1 = 699
34
+ c2pnb304w1 = 700
35
+ c2tnb359v1 = 701
36
+ c2pnb368w1 = 702
37
+ c2tnb431r1 = 703
38
+
39
+ secp112r1 = 704
40
+ secp112r2 = 705
41
+ secp128r1 = 706
42
+ secp128r2 = 707
43
+ secp160k1 = 708
44
+ secp160r1 = 709
45
+ secp160r2 = 710
46
+ secp192k1 = 711
47
+ secp224k1 = 712
48
+ secp224r1 = 713
49
+ secp256k1 = 714
50
+ secp384r1 = 715
51
+ secp521r1 = 716
52
+ sect113r1 = 717
53
+ sect113r2 = 718
54
+ sect131r1 = 719
55
+ sect131r2 = 720
56
+ sect163k1 = 721
57
+ sect163r1 = 722
58
+ sect163r2 = 723
59
+ sect193r1 = 724
60
+ sect193r2 = 725
61
+ sect233k1 = 726
62
+ sect233r1 = 727
63
+ sect239k1 = 728
64
+ sect283k1 = 729
65
+ sect283r1 = 730
66
+ sect409k1 = 731
67
+ sect409r1 = 732
68
+ sect571k1 = 733
69
+ sect571r1 = 734
70
+
71
+ ecid_wtls1 = 735
72
+ ecid_wtls3 = 736
73
+ ecid_wtls4 = 737
74
+ ecid_wtls5 = 738
75
+ ecid_wtls6 = 739
76
+ ecid_wtls7 = 740
77
+ ecid_wtls8 = 741
78
+ ecid_wtls9 = 742
79
+ ecid_wtls10 = 743
80
+ ecid_wtls11 = 744
81
+ ecid_wtls12 = 745
82
+
83
+ curve_description = {
84
+ secp112r1 : 'SECG/WTLS curve over a 112 bit prime field',
85
+ secp112r2 : 'SECG curve over a 112 bit prime field',
86
+ secp128r1 : 'SECG curve over a 128 bit prime field',
87
+ secp128r2 : 'SECG curve over a 128 bit prime field',
88
+ secp160k1 : 'SECG curve over a 160 bit prime field',
89
+ secp160r1 : 'SECG curve over a 160 bit prime field',
90
+ secp160r2 : 'SECG/WTLS curve over a 160 bit prime field',
91
+ secp192k1 : 'SECG curve over a 192 bit prime field',
92
+ secp224k1 : 'SECG curve over a 224 bit prime field',
93
+ secp224r1 : 'NIST/SECG curve over a 224 bit prime field',
94
+ secp256k1 : 'SECG curve over a 256 bit prime field',
95
+ secp384r1 : 'NIST/SECG curve over a 384 bit prime field',
96
+ secp521r1 : 'NIST/SECG curve over a 521 bit prime field',
97
+ prime192v1: 'NIST/X9.62/SECG curve over a 192 bit prime field',
98
+ prime192v2: 'X9.62 curve over a 192 bit prime field',
99
+ prime192v3: 'X9.62 curve over a 192 bit prime field',
100
+ prime239v1: 'X9.62 curve over a 239 bit prime field',
101
+ prime239v2: 'X9.62 curve over a 239 bit prime field',
102
+ prime239v3: 'X9.62 curve over a 239 bit prime field',
103
+ prime256v1: 'X9.62/SECG curve over a 256 bit prime field',
104
+ sect113r1 : 'SECG curve over a 113 bit binary field',
105
+ sect113r2 : 'SECG curve over a 113 bit binary field',
106
+ sect131r1 : 'SECG/WTLS curve over a 131 bit binary field',
107
+ sect131r2 : 'SECG curve over a 131 bit binary field',
108
+ sect163k1 : 'NIST/SECG/WTLS curve over a 163 bit binary field',
109
+ sect163r1 : 'SECG curve over a 163 bit binary field',
110
+ sect163r2 : 'NIST/SECG curve over a 163 bit binary field',
111
+ sect193r1 : 'SECG curve over a 193 bit binary field',
112
+ sect193r2 : 'SECG curve over a 193 bit binary field',
113
+ sect233k1 : 'NIST/SECG/WTLS curve over a 233 bit binary field',
114
+ sect233r1 : 'NIST/SECG/WTLS curve over a 233 bit binary field',
115
+ sect239k1 : 'SECG curve over a 239 bit binary field',
116
+ sect283k1 : 'NIST/SECG curve over a 283 bit binary field',
117
+ sect283r1 : 'NIST/SECG curve over a 283 bit binary field',
118
+ sect409k1 : 'NIST/SECG curve over a 409 bit binary field',
119
+ sect409r1 : 'NIST/SECG curve over a 409 bit binary field',
120
+ sect571k1 : 'NIST/SECG curve over a 571 bit binary field',
121
+ sect571r1 : 'NIST/SECG curve over a 571 bit binary field',
122
+ c2pnb163v1: 'X9.62 curve over a 163 bit binary field',
123
+ c2pnb163v2: 'X9.62 curve over a 163 bit binary field',
124
+ c2pnb163v3: 'X9.62 curve over a 163 bit binary field',
125
+ c2pnb176v1: 'X9.62 curve over a 176 bit binary field',
126
+ c2tnb191v1: 'X9.62 curve over a 191 bit binary field',
127
+ c2tnb191v2: 'X9.62 curve over a 191 bit binary field',
128
+ c2tnb191v3: 'X9.62 curve over a 191 bit binary field',
129
+ c2pnb208w1: 'X9.62 curve over a 208 bit binary field',
130
+ c2tnb239v1: 'X9.62 curve over a 239 bit binary field',
131
+ c2tnb239v2: 'X9.62 curve over a 239 bit binary field',
132
+ c2tnb239v3: 'X9.62 curve over a 239 bit binary field',
133
+ c2pnb272w1: 'X9.62 curve over a 272 bit binary field',
134
+ c2pnb304w1: 'X9.62 curve over a 304 bit binary field',
135
+ c2tnb359v1: 'X9.62 curve over a 359 bit binary field',
136
+ c2pnb368w1: 'X9.62 curve over a 368 bit binary field',
137
+ c2tnb431r1: 'X9.62 curve over a 431 bit binary field',
138
+ ecid_wtls1: 'WTLS curve over a 113 bit binary field',
139
+ ecid_wtls3: 'NIST/SECG/WTLS curve over a 163 bit binary field',
140
+ ecid_wtls4: 'SECG curve over a 113 bit binary field',
141
+ ecid_wtls5: 'X9.62 curve over a 163 bit binary field',
142
+ ecid_wtls6: 'SECG/WTLS curve over a 112 bit prime field',
143
+ ecid_wtls7: 'SECG/WTLS curve over a 160 bit prime field',
144
+ ecid_wtls8: 'WTLS curve over a 112 bit prime field',
145
+ ecid_wtls9: 'WTLS curve over a 160 bit prime field',
146
+ ecid_wtls10:'NIST/SECG/WTLS curve over a 233 bit binary field',
147
+ ecid_wtls11:'NIST/SECG/WTLS curve over a 233 bit binary field',
148
+ ecid_wtls12:'WTLS curvs over a 224 bit prime field',
149
+ }
@@ -0,0 +1,143 @@
1
+ try:
2
+ from charm.core.math.elliptic_curve import elliptic_curve,ec_element,ZR,G,init,random,order,getGenerator,bitsize,serialize,deserialize,hashEC,encode,decode,getXY
3
+ import charm.core.math.elliptic_curve as ecc
4
+ except Exception as err:
5
+ raise ImportError("Cannot import elliptic_curve module. Ensure Charm crypto C extensions are compiled: %s" % err)
6
+
7
+ class ECGroup():
8
+ def __init__(self, builtin_cv):
9
+ self.ec_group = elliptic_curve(nid=builtin_cv)
10
+ self.param = builtin_cv
11
+ self._verbose = True
12
+
13
+ def __str__(self):
14
+ return str(self.ec_group)
15
+
16
+ def order(self):
17
+ """returns the order of the group"""
18
+ return order(self.ec_group)
19
+
20
+ def bitsize(self):
21
+ """returns the bitsize for encoding messages in the group"""
22
+ return bitsize(self.ec_group)
23
+
24
+ def paramgen(self, secparam):
25
+ return None
26
+
27
+ def groupSetting(self):
28
+ return 'elliptic_curve'
29
+
30
+ def groupType(self):
31
+ return self.param
32
+
33
+ def init(self, _type=ZR, value=None):
34
+ """initializes an object with a specified type and value"""
35
+ if value is not None:
36
+ return init(self.ec_group, _type, value)
37
+ return init(self.ec_group, _type)
38
+
39
+ def random(self, _type=ZR):
40
+ """selects a random element in ZR or G"""
41
+ if _type == ZR or _type == G:
42
+ return random(self.ec_group, _type)
43
+ return None
44
+
45
+ def encode(self, message, include_ctr=False):
46
+ """encode arbitrary string as a group element. Max size is dependent on the EC group order"""
47
+ return encode(self.ec_group, message, include_ctr)
48
+
49
+ def decode(self, msg_bytes, include_ctr=False):
50
+ """decode a group element into a string"""
51
+ return decode(self.ec_group, msg_bytes, include_ctr)
52
+
53
+ def serialize(self, object):
54
+ """serializes a pairing object into bytes"""
55
+ return serialize(object)
56
+
57
+ def deserialize(self, bytes_object):
58
+ """deserializes into a pairing object"""
59
+ return deserialize(self.ec_group, bytes_object)
60
+
61
+ def hash(self, args, target_type=ZR):
62
+ """hashes objects into ZR or G
63
+
64
+ Different object types may hash to the same element, e.g., the ASCII
65
+ string 'str' and the byte string b'str' map to the same element."""
66
+ def hash_encode(arg):
67
+ """encode a data type to bytes"""
68
+ if type(arg) is bytes:
69
+ s = arg
70
+ elif type(arg) is ec_element:
71
+ s = serialize(arg)
72
+ elif type(arg) is str:
73
+ s = arg.encode('utf-8')
74
+ elif type(arg) is int:
75
+ s = arg.to_bytes((arg.bit_length() + 7) // 8, 'little')
76
+ elif isinstance(args, tuple):
77
+ # based on TupleHash (see NIST SP 800-185)
78
+ def left_encode(x):
79
+ # This implictly checks for validity conditions:
80
+ # An exception is raised if n > 255, i.e., if len(x) > 2**2040
81
+ n = (x.bit_length() + 7 ) // 8
82
+ return n.to_bytes(1, 'little') + x.to_bytes(n, 'little')
83
+
84
+ s = b''
85
+ for arg in args:
86
+ z = hash_encode(arg)
87
+ # concat with encode_string(z)
88
+ s += left_encode(len(z)) + z
89
+ else:
90
+ raise ValueError("unexpected type to hash: {}".format(type(arg)))
91
+
92
+ return s
93
+
94
+ return hashEC(self.ec_group, hash_encode(args), target_type)
95
+
96
+ def zr(self, point):
97
+ """get the X coordinate only"""
98
+ if type(point) == ec_element:
99
+ return getXY(self.ec_group, point, False)
100
+ return None
101
+
102
+ def coordinates(self, point):
103
+ """get the X and Y coordinates of an EC point"""
104
+ if type(point) == ec_element:
105
+ return getXY(self.ec_group, point, True)
106
+
107
+ def debug(self, data, prefix=None):
108
+ if type(data) == dict and self._verbose:
109
+ for k,v in data.items():
110
+ print(k,v)
111
+ elif type(data) == list and self._verbose:
112
+ for i in range(0, len(data)):
113
+ print(prefix, (i+1),':',data[i])
114
+ print('')
115
+ elif type(data) == str and self._verbose:
116
+ print(data)
117
+ return None
118
+
119
+ def InitBenchmark(self):
120
+ """initiates the benchmark state"""
121
+ return ecc.InitBenchmark(self.ec_group)
122
+
123
+ def StartBenchmark(self, options):
124
+ """starts the benchmark with any of these options:
125
+ RealTime, CpuTime, Mul, Div, Add, Sub, Exp, Granular"""
126
+ return ecc.StartBenchmark(self.ec_group, options)
127
+
128
+ def EndBenchmark(self):
129
+ """ends an ongoing benchmark"""
130
+ return ecc.EndBenchmark(self.ec_group)
131
+
132
+ def GetGeneralBenchmarks(self):
133
+ """retrieves benchmark count for all group operations"""
134
+ return ecc.GetGeneralBenchmarks(self.ec_group)
135
+
136
+ def GetGranularBenchmarks(self):
137
+ """retrieves group operation count per type: ZR and G"""
138
+ return ecc.GetGranularBenchmarks(self.ec_group)
139
+
140
+ def GetBenchmark(self, option):
141
+ """retrieves benchmark results for any of these options:
142
+ RealTime, CpuTime, Mul, Div, Add, Sub, Exp, Granular"""
143
+ return ecc.GetBenchmark(self.ec_group, option)
charm/toolbox/enum.py ADDED
@@ -0,0 +1,60 @@
1
+ # code adapted from active state code recipes for enumeration
2
+ def Enum(*names):
3
+ class EnumClass(object):
4
+ __slots__ = names
5
+ def __iter__(self): return iter(constants)
6
+ def __len__(self): return len(constants)
7
+ def __getitem__(self, i):
8
+ if type(i) == int: return constants[i]
9
+ elif type(i) == str:
10
+ index = lookup.get(i)
11
+ if index != None: return constants[index]
12
+ else: return None
13
+ else: assert False, "Invalid input type."
14
+ def __repr__(self): return 'Enum' + str(names)
15
+ def __str__(self): return 'enum ' + str(constants)
16
+ def getList(self): return list(names)
17
+
18
+ class EnumValue(object):
19
+ #__slots__ = ('__value')
20
+ def __init__(self, value): self.__value = value
21
+ Value = property(lambda self: self.__value)
22
+ EnumType = property(lambda self: EnumType)
23
+ def __hash__(self): return hash(self.__value)
24
+ def __lt__(self, other):
25
+ return (self.__value < other.__value)
26
+ def __gt__(self, other):
27
+ return (self.__value > other.__value)
28
+ def __le__(self, other):
29
+ return (self.__value <= other.__value)
30
+ def __ge__(self, other):
31
+ return (self.__value >= other.__value)
32
+ def __eq__(self, other):
33
+ if type(self) == int: lhs = self
34
+ else: lhs = self.__value
35
+ if type(other) == int: rhs = other
36
+ else: rhs = other.__value
37
+ return (lhs == rhs)
38
+ def __ne__(self, other):
39
+ if type(self) == int: lhs = self
40
+ else: lhs = self.__value
41
+ if type(other) == int: rhs = other
42
+ else: rhs = other.__value
43
+ return (lhs != rhs)
44
+ def __invert__(self): return constants[maximum - self.__value]
45
+ def __nonzero__(self): return bool(self.__value)
46
+ def __repr__(self): return str(names[self.__value])
47
+
48
+ maximum = len(names) - 1
49
+ constants = [None] * len(names)
50
+ lookup = {}
51
+ for i, each in enumerate(names):
52
+ val = EnumValue(i)
53
+ setattr(EnumClass, each, val)
54
+ # create list of int => 'str'
55
+ constants[i] = val
56
+ # create reverse lookup
57
+ lookup[str(val)] = i
58
+ constants = tuple(constants)
59
+ EnumType = EnumClass()
60
+ return EnumType