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,174 @@
1
+ '''
2
+ Contains all the auxillary functions to do linear secret sharing (LSS) over an access structure. Mainly, we represent the
3
+ access structure as a binary tree. This could also support matrices for representing access structures.
4
+ '''
5
+ from charm.core.math.pairing import ZR
6
+ from charm.toolbox.policytree import *
7
+
8
+ class SecretUtil:
9
+ def __init__(self, groupObj, verbose=True):
10
+ self.group = groupObj
11
+ # self.parser = PolicyParser()
12
+
13
+ def P(self, coeff, x):
14
+ share = 0
15
+ # evaluate polynomial
16
+ for i in range(0, len(coeff)):
17
+ share += (coeff[i] * (x ** i))
18
+ return share
19
+
20
+ def genShares(self, secret, k, n):
21
+ if(k <= n):
22
+ rand = self.group.random
23
+ a = [] # will hold polynomial coefficients
24
+ for i in range(0, k):
25
+ if (i == 0): a.append(secret) # a[0]
26
+ else: a.append(rand(ZR))
27
+ Pfunc = self.P
28
+ shares = [Pfunc(a, i) for i in range(0, n+1)]
29
+ return shares
30
+
31
+ # shares is a dictionary
32
+ def recoverCoefficients(self, list):
33
+ """recovers the coefficients over a binary tree."""
34
+ coeff = {}
35
+ list2 = [self.group.init(ZR, i) for i in list]
36
+ for idx, i in enumerate(list):
37
+ i_zr = list2[idx] # self.group.init(ZR, i)
38
+ result = 1
39
+ for j_zr in list2:
40
+ if not (i_zr == j_zr):
41
+ # lagrange basis poly
42
+ result *= (0 - j_zr) / (i_zr - j_zr)
43
+ # print("coeff '%d' => '%s'" % (i, result))
44
+ coeff[int(i)] = result
45
+ return coeff
46
+
47
+ def recoverSecret(self, shares):
48
+ """take shares and attempt to recover secret by taking sum of coeff * share for all shares.
49
+ if user indeed has at least k of n shares, then secret will be recovered."""
50
+ list = shares.keys()
51
+ if self.verbose: print(list)
52
+ coeff = self.recoverCoefficients(list)
53
+ secret = 0
54
+ for i in list:
55
+ secret += (coeff[i] * shares[i])
56
+
57
+ return secret
58
+
59
+ def getCoefficients(self, tree):
60
+ coeffs = {}
61
+ self._getCoefficientsDict(tree, coeffs)
62
+ return coeffs
63
+
64
+ def _getCoefficientsDict(self, tree, coeff_list, coeff=1):
65
+ """recover coefficient over a binary tree where possible node types are OR = (1 of 2)
66
+ and AND = (2 of 2) secret sharing. The leaf nodes are attributes and the coefficients are
67
+ recorded in a coeff-list dictionary."""
68
+ if tree:
69
+ node = tree.getNodeType()
70
+ if(node == OpType.AND):
71
+ this_coeff = self.recoverCoefficients([1,2])
72
+ # left child => coeff[1], right child => coeff[2]
73
+ self._getCoefficientsDict(tree.getLeft(), coeff_list, coeff * this_coeff[1])
74
+ self._getCoefficientsDict(tree.getRight(), coeff_list, coeff * this_coeff[2])
75
+ elif(node == OpType.OR):
76
+ this_coeff = self.recoverCoefficients([1])
77
+ self._getCoefficientsDict(tree.getLeft(), coeff_list, coeff * this_coeff[1])
78
+ self._getCoefficientsDict(tree.getRight(), coeff_list, coeff * this_coeff[1])
79
+ elif(node == OpType.ATTR):
80
+ attr = tree.getAttributeAndIndex()
81
+ coeff_list[ attr ] = coeff
82
+ else:
83
+ return None
84
+
85
+ def _calculateShares(self, secret, tree, _type=dict):
86
+ """performs secret sharing over a policy tree. could be adapted for LSSS matrices."""
87
+ attr_list = []
88
+ self._compute_shares(secret, tree, attr_list)
89
+ if _type == list:
90
+ return attr_list
91
+ else: # assume dict
92
+ share = {}
93
+ for i in range(0, len(attr_list)):
94
+ key = attr_list[i][0].getAttributeAndIndex()
95
+ if not key in share.keys():
96
+ share[ key ] = attr_list[i][1]
97
+ return share
98
+
99
+ def calculateSharesList(self, secret, tree):
100
+ """calculate shares from given secret and returns a list of shares."""
101
+ return self._calculateShares(secret, tree, list)
102
+
103
+ def calculateSharesDict(self, secret, tree):
104
+ """calculate shares from given secret and returns a dict as {attribute:shares} pairs"""
105
+ return self._calculateShares(secret, tree, dict)
106
+
107
+ def _compute_shares(self, secret, subtree, List):
108
+ """computes recursive secret sharing over the binary tree. Start by splitting 1-of-2 (OR) or 2-of-2 (AND nodes).
109
+ Continues recursively down the tree doing a round of secret sharing at each boolean node type."""
110
+ k = 0
111
+ if(subtree == None):
112
+ return None
113
+
114
+ type = subtree.getNodeType()
115
+ if(type == OpType.ATTR):
116
+ # visiting a leaf node
117
+ # t = (subtree.getAttribute(), secret)
118
+ t = (subtree, secret)
119
+ List.append(t)
120
+ return None
121
+ elif(type == OpType.OR or type == OpType.AND):
122
+ k = subtree.threshold # 1-of-2 or 2-of-2
123
+ # elif(type == OpType.AND):
124
+ # k = 2 # 2-of-2
125
+ else:
126
+ return None
127
+ # generate shares for k and n
128
+ shares = self.genShares(secret, k, n=2)
129
+ # recursively generate shares for children nodes
130
+ self._compute_shares(shares[1], subtree.getLeft(), List)
131
+ self._compute_shares(shares[2], subtree.getRight(), List)
132
+
133
+ def strip_index(self, node_str):
134
+ if node_str.find('_') != -1: return node_str.split('_')[0]
135
+ return node_str
136
+
137
+
138
+ def createPolicy(self, policy_string):
139
+ assert type(policy_string) == str, "invalid type for policy_string"
140
+ parser = PolicyParser()
141
+ policy_obj = parser.parse(policy_string)
142
+ _dictCount, _dictLabel = {}, {}
143
+ parser.findDuplicates(policy_obj, _dictCount)
144
+ for i in _dictCount.keys():
145
+ if _dictCount[ i ] > 1: _dictLabel[ i ] = 0
146
+ parser.labelDuplicates(policy_obj, _dictLabel)
147
+ return policy_obj
148
+
149
+ def prune(self, policy, attributes):
150
+ """determine whether a given set of attributes satisfies the policy"""
151
+ parser = PolicyParser()
152
+ return parser.prune(policy, attributes)
153
+
154
+ def getAttributeList(self, Node):
155
+ aList = []
156
+ self._getAttributeList(Node, aList)
157
+ return aList
158
+
159
+ def _getAttributeList(self, Node, List):
160
+ """retrieve the attributes that occur in a policy tree in order (left to right)"""
161
+ if(Node == None):
162
+ return None
163
+ # V, L, R
164
+ if(Node.getNodeType() == OpType.ATTR):
165
+ List.append(Node.getAttributeAndIndex()) # .getAttribute()
166
+ else:
167
+ self._getAttributeList(Node.getLeft(), List)
168
+ self._getAttributeList(Node.getRight(), List)
169
+ return None
170
+
171
+ # TODO: add test cases here for SecretUtil
172
+ if __name__ == "__main__":
173
+ pass
174
+
@@ -0,0 +1,73 @@
1
+ '''
2
+ Base class for cryptographic secure random number generation
3
+ :authors: Gary Belvin
4
+ '''
5
+ from charm.toolbox.bitstring import Bytes
6
+ from charm.toolbox.conversion import Conversion
7
+ from charm.core.math.integer import randomBits
8
+ import datetime
9
+ import math
10
+ import random
11
+
12
+ class SecureRandom():
13
+ def __init__(self):
14
+ pass
15
+ def getRandomBytes(self, length):
16
+ '''Returns a random bit string of length bytes'''
17
+ raise NotImplementedError
18
+ def addSeed(self, seed):
19
+ '''
20
+ Add randomness to the generator.
21
+ Always increases entropy
22
+ '''
23
+ raise NotImplementedError
24
+
25
+ class SecureRandomFactory():
26
+ '''
27
+ This class provides a central place to swap out the randomness engine
28
+ used by the charm framework.
29
+ Classes should call ``rand = SecureRandomFactory.getInstance()``
30
+ to acquire a randomnesss generator
31
+ '''
32
+ @classmethod
33
+ def getInstance(self):
34
+ return OpenSSLRand()
35
+
36
+
37
+ class OpenSSLRand(SecureRandom):
38
+ '''Uses the OpenSSL PRNG for random bits'''
39
+ def __init__(self):
40
+ SecureRandom.__init__(self)
41
+ #seed with a little bit of random data. This is not the only source
42
+ #of randomness. Internally, OpenSSL samples additional physical randomness.
43
+
44
+ def getRandomBytes(self, length):
45
+ bits = length * 8;
46
+ val = randomBits(bits)
47
+ return Conversion.IP2OS(val, length)
48
+
49
+ def getRandomBits(self, length):
50
+ i = randomBits(length)
51
+ len = math.ceil(length / 8)
52
+ return Conversion.IP2OS(i, len)
53
+
54
+
55
+ class WeakRandom(SecureRandom):
56
+ def __init__(self):
57
+ SecureRandom.__init__(self)
58
+ def getRandomBytes(self, length):
59
+ return self.myrandom(length, False)
60
+ def addSeed(self, seed):
61
+ raise NotImplementedError()
62
+ @classmethod
63
+ def myrandom(self, length, printable=False):
64
+ '''
65
+ This method does **NOT** provide cryptographically secure random numbers.
66
+ This should **NOT** be used for production code
67
+ '''
68
+ if(printable):
69
+ #Nice printable characters for testing purposes
70
+ return Bytes(random.randrange(0x20, 0x7E) for i in range(length))
71
+ else:
72
+ return Bytes(random.randrange(0, 256) for i in range(length))
73
+
@@ -0,0 +1,46 @@
1
+
2
+ from charm.core.engine.protocol import Protocol
3
+ from charm.core.engine.util import *
4
+ from charm. toolbox.enum import Enum
5
+
6
+ #party = Enum('Prover', 'Verifier')
7
+
8
+ class Sigma(Protocol):
9
+ def __init__(self, groupObj, common_input=None):
10
+ Protocol.__init__(self, None) # think of something for handling errors
11
+ self.verifier_states = { 2:self.verifier_state2, 4:self.verifier_state4, 6:self.verifier_state6 }
12
+ self.prover_states = { 1:self.prover_state1, 3:self.prover_state3, 5:self.prover_state5 }
13
+ self.PROVER, self.VERIFIER = 1, 2 # PROVER = 1, VERIFIER = 2
14
+
15
+ self.verifier_trans = { 2:4, 4:6 }
16
+ self.prover_trans = { 1:3, 3:5 }
17
+ # describe the parties involved and the valid transitions
18
+ Protocol.addPartyType(self, self.VERIFIER, self.verifier_states, self.verifier_trans)
19
+ Protocol.addPartyType(self, self.PROVER, self.prover_states, self.prover_trans, True)
20
+
21
+ self.group = groupObj
22
+ # proof parameter generation
23
+ if common_input == None: # generate common parameters to P and V
24
+ db = {}
25
+ else: # can be used as a sub-protocol if common_input is specified by caller
26
+ db = common_input
27
+ Protocol.setSubclassVars(self, self.group, db)
28
+
29
+ # must be implemented by sub class...
30
+ def prover_state1(self):
31
+ pass
32
+
33
+ def prover_state3(self, input):
34
+ pass
35
+
36
+ def prover_state5(self, input):
37
+ pass
38
+
39
+ def verifier_state2(self, input):
40
+ pass
41
+
42
+ def verifier_state4(self, input):
43
+ pass
44
+
45
+ def verifier_state6(self, input):
46
+ pass
@@ -0,0 +1,45 @@
1
+ '''
2
+ Generates a Blum-Williams integer, which is the product of two distinct primes
3
+ each congruent to 3 mod 4
4
+ '''
5
+
6
+ from charm.core.math.integer import integer,isPrime,randomPrime
7
+
8
+ class BlumWilliamsInteger:
9
+ def __init__(self):
10
+ pass
11
+
12
+ def generatePrimes(self, n):
13
+ # Add safety limit to prevent infinite loops on Python 3.12+
14
+ # Blum-Williams primes (p ≡ 3 mod 4) are approximately 50% of all primes
15
+ # so we should find one within a reasonable number of attempts
16
+ max_attempts = 10000
17
+
18
+ for attempt in range(max_attempts):
19
+ p = randomPrime(n)
20
+ if(isPrime(p) and (((p-3)%4) == 0)):
21
+ break
22
+ else:
23
+ raise RuntimeError(
24
+ f"Could not generate Blum-Williams prime p after {max_attempts} attempts"
25
+ )
26
+
27
+ for attempt in range(max_attempts):
28
+ q = randomPrime(n)
29
+ if(isPrime(q) and (((q-3)%4) == 0) and not(q == p)):
30
+ break
31
+ else:
32
+ raise RuntimeError(
33
+ f"Could not generate Blum-Williams prime q after {max_attempts} attempts"
34
+ )
35
+
36
+ return (p, q)
37
+
38
+ def generateBlumWilliamsInteger(self, n, p=0, q=0):
39
+ if((p == 0) or (q == 0)):
40
+ (p,q) = self.generatePrimes(n)
41
+ N = p * q
42
+ return (p, q, N)
43
+ else:
44
+ N = p * q
45
+ return N
@@ -0,0 +1,279 @@
1
+ from charm.toolbox.paddingschemes import PKCS7Padding
2
+ from charm.toolbox.securerandom import OpenSSLRand
3
+ from charm.core.crypto.cryptobase import MODE_CBC,AES,selectPRP
4
+ from hashlib import sha256 as sha2
5
+ import json
6
+ import hmac
7
+ from base64 import b64encode, b64decode
8
+
9
+ class MessageAuthenticator(object):
10
+ """ Abstraction for constructing and verifying authenticated messages
11
+
12
+ A large number of the schemes can only encrypt group elements
13
+ and do not provide an efficient mechanism for encoding byte in
14
+ those elements. As such we don't pick a symmetric key and encrypt
15
+ it asymmetrically. Rather, we hash a random group element to get the
16
+ symmetric key.
17
+
18
+ >>> from charm.toolbox.pairinggroup import PairingGroup,GT,extract_key
19
+ >>> groupObj = PairingGroup('SS512')
20
+ >>> key = groupObj.random(GT)
21
+ >>> m = MessageAuthenticator(extract_key(key))
22
+ >>> AuthenticatedMessage = m.mac('Hello World')
23
+ >>> m.verify(AuthenticatedMessage)
24
+ True
25
+ """
26
+ def __init__(self, key, alg="HMAC_SHA2"):
27
+ """
28
+ Creates a message authenticator and verifier under the specified key
29
+ """
30
+ if alg != "HMAC_SHA2":
31
+ raise ValueError("Currently only HMAC_SHA2 is supported as an algorithm")
32
+ self._algorithm = alg
33
+ self._key = key
34
+
35
+ def mac(self, msg, associatedData=b''):
36
+ """
37
+ Authenticates (MAC) a message. The MAC is computed as:
38
+ MAC = HMAC(key, algorithm + associatedData + message).
39
+
40
+ Parameters
41
+ ----------
42
+ msg : str or byte str
43
+ The message serving as input to the HMAC algorithm, in addition to the HMAC algorithm and associated data.
44
+ associatedData : str or byte str, optional
45
+ Associated data that will be MACed together with the ciphertext and algorithm; the associated data will not be encrypted.
46
+
47
+ Returns
48
+ -------
49
+ dict
50
+ Dictionary composed of the MAC algorithm, the MACed message (or ciphertext), and the digest computed by MACing HMAC_algorithm + associatedData + msg.
51
+ """
52
+ # Ensure the associated data is in byte format, convert if necessary.
53
+ if type(associatedData) != bytes :
54
+ associatedData = bytes(associatedData, "utf-8")
55
+ return {
56
+ "alg": self._algorithm,
57
+ "msg": msg,
58
+ "digest": hmac.new(self._key, bytes(self._algorithm, "utf-8") + associatedData + bytes(msg, "utf-8"), digestmod=sha2).hexdigest()
59
+ }
60
+
61
+ def verify(self, msgAndDigest, associatedData=b''):
62
+ """
63
+ Verifies whether the MAC digest from input ciphertext and digest matches the computed one over ciphertext and associated data.
64
+
65
+ Parameters
66
+ ----------
67
+ msgAndDigest : dict
68
+ Dictionary composed of the MAC algorithm, the MACed message (or ciphertext), and the digest computed by MACing HMAC_algorithm + associatedData + msg.
69
+ It is the format generated by the mac() function within this class.
70
+ associatedData : str or byte str, optional
71
+ Associated data that will be MACed together with the ciphertext and algorithm; the associated data will not be encrypted.
72
+
73
+ Returns
74
+ -------
75
+ bool
76
+ True if the digests match, False otherwise.
77
+
78
+ Raises
79
+ ------
80
+ ValueError
81
+ If the HMAC algorithm is not supported.
82
+ """
83
+ if msgAndDigest['alg'] != self._algorithm:
84
+ raise ValueError("Currently only HMAC_SHA2 is supported as an algorithm")
85
+ expected = bytes(self.mac(msgAndDigest['msg'], associatedData=associatedData)['digest'], 'utf-8')
86
+ received = bytes(msgAndDigest['digest'], 'utf-8')
87
+ # we compare the hash instead of the direct value to avoid a timing attack
88
+ return sha2(expected).digest() == sha2(received).digest()
89
+
90
+ class SymmetricCryptoAbstraction(object):
91
+ """
92
+ Abstraction for symmetric encryption and decryption of data.
93
+ Ideally provide an INDCCA2 secure symmetric container for arbitrary data.
94
+ Currently only supports primitives that JSON can encode and decode.
95
+
96
+ A large number of the schemes can only encrypt group elements
97
+ and do not provide an efficient mechanism for encoding byte in
98
+ those elements. As such we don't pick a symmetric key and encrypt
99
+ it asymmetrically. Rather, we hash a random group element to get the
100
+ symmetric key.
101
+
102
+ >>> from charm.toolbox.pairinggroup import PairingGroup,GT,extract_key
103
+ >>> groupObj = PairingGroup('SS512')
104
+ >>> a = SymmetricCryptoAbstraction(extract_key(groupObj.random(GT)))
105
+ >>> ct = a.encrypt(b"Friendly Fire Isn't")
106
+ >>> a.decrypt(ct)
107
+ b"Friendly Fire Isn't"
108
+ """
109
+
110
+ def __init__(self, key, alg = AES, mode = MODE_CBC):
111
+ self._alg = alg
112
+ self.key_len = 16
113
+ self._block_size = 16
114
+ self._mode = mode
115
+ self._key = key[0:self.key_len] # expected to be bytes
116
+ assert len(self._key) == self.key_len, "SymmetricCryptoAbstraction key too short"
117
+ self._padding = PKCS7Padding()
118
+
119
+ def _initCipher(self,IV = None):
120
+ if IV == None :
121
+ IV = OpenSSLRand().getRandomBytes(self._block_size)
122
+ self._IV = IV
123
+ return selectPRP(self._alg,(self._key,self._mode,self._IV))
124
+
125
+ def __encode_decode(self,data,func):
126
+ data['IV'] = func(data['IV'])
127
+ data['CipherText'] = func(data['CipherText'])
128
+ return data
129
+
130
+ #This code should be factored out into another class
131
+ #Because json is only defined over strings, we need to base64 encode the encrypted data
132
+ # and convert the base 64 byte array into a utf8 string
133
+ def _encode(self, data):
134
+ return self.__encode_decode(data, lambda x: b64encode(x).decode('utf-8'))
135
+
136
+ def _decode(self, data):
137
+ return self.__encode_decode(data, lambda x: b64decode(bytes(x, 'utf-8')))
138
+
139
+ def encrypt(self, message):
140
+ #This should be removed when all crypto functions deal with bytes"
141
+ if type(message) != bytes :
142
+ message = bytes(message, "utf-8")
143
+ ct = self._encrypt(message)
144
+ #JSON strings cannot have binary data in them, so we must base64 encode cipher
145
+ cte = json.dumps(self._encode(ct))
146
+ return cte
147
+
148
+ def _encrypt(self, message):
149
+ #Because the IV cannot be set after instantiation, decrypt and encrypt
150
+ # must operate on their own instances of the cipher
151
+ cipher = self._initCipher()
152
+ ct= {'ALG': self._alg,
153
+ 'MODE': self._mode,
154
+ 'IV': self._IV,
155
+ 'CipherText': cipher.encrypt(self._padding.encode(message))
156
+ }
157
+ return ct
158
+
159
+ def decrypt(self, cipherText):
160
+ f = json.loads(cipherText)
161
+ return self._decrypt(self._decode(f))
162
+
163
+ def _decrypt(self, cipherText):
164
+ cipher = self._initCipher(cipherText['IV'])
165
+ msg = cipher.decrypt(cipherText['CipherText'])
166
+ return self._padding.decode(msg)
167
+
168
+ class AuthenticatedCryptoAbstraction(SymmetricCryptoAbstraction):
169
+ """
170
+ Implements Authenticated Encryption with Associated Data (AEAD) abstraction. The associated data is optional, and this version is backwards compatible
171
+ with the same class without the associated data option.
172
+
173
+ Examples
174
+ --------
175
+ >>> from hashlib import sha256
176
+ >>> import charm.toolbox.symcrypto
177
+ >>> key = sha256(b'shameful secret key').digest()
178
+ >>> cipher = charm.toolbox.symcrypto.AuthenticatedCryptoAbstraction(key)
179
+ >>> ciphertext = cipher.encrypt('My age is 42.')
180
+ >>> cipher.decrypt(ciphertext)
181
+ b'My age is 42.'
182
+ >>> ciphertext2 = cipher.encrypt(b'My age is 42.')
183
+ >>> cipher.decrypt(ciphertext2)
184
+ b'My age is 42.'
185
+ >>> ad = b'\x10\x11\x11\x11'
186
+ >>> ciphertextAssociatedData = cipher.encrypt('Some network PDU.', associatedData=ad)
187
+ >>> cipher.decrypt(ciphertextAssociatedData)
188
+ Traceback (most recent call last):
189
+ File "<stdin>", line 1, in <module>
190
+ File "./charm/toolbox/symcrypto.py", line 233, in decrypt
191
+ raise ValueError("Invalid mac. Your data was tampered with or your key is wrong")
192
+ ValueError: Invalid mac. Your data was tampered with or your key is wrong
193
+ >>> cipher.decrypt(ciphertextAssociatedData, associatedData='wrong data')
194
+ Traceback (most recent call last):
195
+ File "<stdin>", line 1, in <module>
196
+ File "./charm/toolbox/symcrypto.py", line 233, in decrypt
197
+ raise ValueError("Invalid mac. Your data was tampered with or your key is wrong")
198
+ ValueError: Invalid mac. Your data was tampered with or your key is wrong
199
+ >>> cipher.decrypt(ciphertextAssociatedData, associatedData=b'\x10\x11\x11\x11')
200
+ b'Some network PDU.'
201
+ >>>
202
+ """
203
+ def encrypt(self, msg, associatedData=''):
204
+ """
205
+ Encrypts a message in AEAD mode (Authenticated Encryption with Associated Data) using the superclass symmetric encryption parameters.
206
+ The MAC is computed with both the ciphertext and associated data (and other cryptosystem parameters), but the associated data is not encrypted, nor
207
+ saved within the ciphertext structure.
208
+
209
+ Parameters
210
+ ----------
211
+ msg : str or byte str
212
+ The message to be encrypted.
213
+ associatedData : str or byte str, optional
214
+ Associated data that will be MACed together with the ciphertext and algorithm; the associated data will not be encrypted.
215
+
216
+ Returns
217
+ -------
218
+ dict
219
+ Dictionary structure containing:
220
+ msg: {'ALG': symmetric cryptosystem.
221
+ 'MODE': symmetric encryption mode.
222
+ 'IV': the IV for the encryption algorithm.
223
+ 'CipherText': the padded ciphertext (padding according to PKCS 7).
224
+ }
225
+ "alg": The HMAC algorithm.
226
+ "digest": The MAC computed as MAC = HMAC(key, alg + associatedData + msg)
227
+
228
+ Notes
229
+ -----
230
+ The IV is included in the computation of the MAC. In fact, all cipher parameters are included: the encryption function returns a JSON object from
231
+ a dictionary composed of the cipher parameters (e.g., algorithm, mode, IV), and the ciphertext. The MAC function uses the whole JSON object/string
232
+ to compute the MAC, prepended with the HMAC algorithm + associatedData.
233
+
234
+ The MAC key is computed as sha2(b'Poor Mans Key Extractor" + key).
235
+ """
236
+ # warning only valid in the random oracle
237
+ mac_key = sha2(b'Poor Mans Key Extractor'+self._key).digest()
238
+ mac = MessageAuthenticator(mac_key)
239
+ enc = super(AuthenticatedCryptoAbstraction, self).encrypt(msg)
240
+ return mac.mac(enc, associatedData=associatedData)
241
+
242
+ def decrypt(self, cipherText, associatedData=''):
243
+ """
244
+ Decrypts a ciphertext in AEAD mode (Authenticated Encryption with Associated Data) using the superclass symmetric encryption parameters.
245
+ The MAC is computed with both the ciphertext and associated data (and other cryptosystem parameters), but the associated data is not encrypted, nor
246
+ available within the ciphertext structure.
247
+
248
+ Parameters
249
+ ----------
250
+ ciphertext : str or byte str
251
+ The message to be decrypted.
252
+ associatedData : str or byte str, optional
253
+ Associated data that will be MACed together with the ciphertext and algorithm. This associated text must be in plaintext.
254
+
255
+ Returns
256
+ -------
257
+ byte str
258
+ The decrypted plaintext, if the ciphertext was successfuly authenticated. Raise exception otherwise.
259
+
260
+ Raises
261
+ ------
262
+ ValueError
263
+ If the MAC is invalid.
264
+
265
+ Notes
266
+ -----
267
+ The IV is included in the computation of the MAC. In fact, all cipher parameters are included: the encryption function returns a JSON object from
268
+ a dictionary composed of the cipher parameters (e.g., algorithm, mode, IV), and the ciphertext. The MAC function uses the whole JSON object/string
269
+ to compute the MAC, prepended with the HMAC algorithm + associatedData.
270
+
271
+ The MAC key is computed as sha2(b'Poor Mans Key Extractor" + key).
272
+ """
273
+ # warning only valid in the random oracle
274
+ mac_key = sha2(b'Poor Mans Key Extractor'+self._key).digest()
275
+ mac = MessageAuthenticator(mac_key)
276
+ if not mac.verify(cipherText, associatedData=associatedData):
277
+ raise ValueError("Invalid mac. Your data was tampered with or your key is wrong")
278
+ else:
279
+ return super(AuthenticatedCryptoAbstraction, self).decrypt(cipherText['msg'])