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,553 @@
1
+ '''
2
+ Threshold Secret Sharing for DKLS23 and Threshold ECDSA
3
+
4
+ | From: "How to Share a Secret" (Shamir Secret Sharing)
5
+ | By: Adi Shamir
6
+ | Published: Communications of the ACM, 1979
7
+ | URL: https://dl.acm.org/doi/10.1145/359168.359176
8
+ |
9
+ | Feldman VSS from:
10
+ | "A Practical Scheme for Non-interactive Verifiable Secret Sharing"
11
+ | By: Paul Feldman
12
+ | Published: FOCS 1987
13
+ | URL: https://ieeexplore.ieee.org/document/4568297
14
+ |
15
+ | Pedersen Commitments from:
16
+ | "Non-Interactive and Information-Theoretic Secure Verifiable Secret Sharing"
17
+ | By: Torben Pryds Pedersen
18
+ | Published: CRYPTO 1991
19
+ | URL: https://link.springer.com/chapter/10.1007/3-540-46766-1_9
20
+
21
+ * type: secret sharing
22
+ * setting: Elliptic Curve group
23
+ * assumption: DLP (for Feldman VSS)
24
+
25
+ This module extends Shamir secret sharing for threshold ECDSA requirements,
26
+ providing Feldman VSS, Pedersen commitments, and EC group element support.
27
+ '''
28
+
29
+ from typing import Dict, List, Tuple, Any, Optional
30
+
31
+ from charm.toolbox.ecgroup import ECGroup, ZR, G
32
+ from charm.toolbox.eccurve import secp256k1
33
+ from charm.toolbox.secretshare import SecretShare
34
+
35
+ # Type alias for ZR elements (scalar field elements)
36
+ ZRElement = Any
37
+ # Type alias for G elements (group/curve points)
38
+ GElement = Any
39
+ # Type alias for ECGroup objects
40
+ ECGroupType = Any
41
+ # Type alias for party identifiers
42
+ PartyId = int
43
+
44
+
45
+ class ThresholdSharing:
46
+ """
47
+ Enhanced secret sharing for threshold ECDSA
48
+
49
+ Supports Feldman VSS and operations on EC groups.
50
+
51
+ Curve Agnostic
52
+ --------------
53
+ This implementation supports any elliptic curve group that is DDH-hard.
54
+ The curve is specified via the groupObj parameter.
55
+
56
+ >>> from charm.toolbox.eccurve import secp256k1
57
+ >>> group = ECGroup(secp256k1)
58
+ >>> ts = ThresholdSharing(group)
59
+ >>> g = group.random(G)
60
+ >>> secret = group.random(ZR)
61
+ >>> shares, commitments = ts.share_with_verification(secret, g, threshold=2, num_parties=3)
62
+ >>> ts.verify_share(1, shares[1], commitments, g)
63
+ True
64
+ >>> ts.verify_share(2, shares[2], commitments, g)
65
+ True
66
+ >>> ts.verify_share(3, shares[3], commitments, g)
67
+ True
68
+ >>> recovered = ts.reconstruct({1: shares[1], 2: shares[2]}, threshold=2)
69
+ >>> secret == recovered
70
+ True
71
+ """
72
+
73
+ def __init__(self, groupObj: ECGroupType) -> None:
74
+ """
75
+ Initialize threshold sharing with an EC group
76
+
77
+ Args:
78
+ groupObj: An ECGroup instance (e.g., ECGroup(secp256k1))
79
+
80
+ Raises:
81
+ ValueError: If groupObj is None
82
+ """
83
+ if groupObj is None:
84
+ raise ValueError("groupObj cannot be None")
85
+ self.group = groupObj
86
+ self.order = groupObj.order()
87
+
88
+ def _eval_polynomial(self, coeffs: List[ZRElement], x: Any) -> ZRElement:
89
+ """
90
+ Evaluate polynomial at point x using Horner's method
91
+
92
+ This method computes f(x) = a_0 + a_1*x + a_2*x^2 + ... + a_{t-1}*x^{t-1}
93
+ using Horner's method for optimal efficiency.
94
+
95
+ Horner's method rewrites the polynomial as:
96
+ f(x) = a_0 + x*(a_1 + x*(a_2 + ... + x*a_{t-1}))
97
+
98
+ This reduces the number of multiplications from 2n to n-1.
99
+
100
+ Args:
101
+ coeffs: List of coefficients [a_0, a_1, ..., a_{t-1}]
102
+ x: Point to evaluate at (ZR element or int)
103
+
104
+ Returns:
105
+ Polynomial value at x
106
+ """
107
+ if not coeffs:
108
+ return self.group.init(ZR, 0)
109
+
110
+ if isinstance(x, int):
111
+ x = self.group.init(ZR, x)
112
+
113
+ # Start with the highest degree coefficient
114
+ result = coeffs[-1]
115
+
116
+ # Work backwards through coefficients: result = result * x + a_i
117
+ for i in range(len(coeffs) - 2, -1, -1):
118
+ result = result * x + coeffs[i]
119
+
120
+ return result
121
+
122
+ def share(self, secret: ZRElement, threshold: int, num_parties: int) -> Dict[int, ZRElement]:
123
+ """
124
+ Basic Shamir secret sharing
125
+
126
+ Args:
127
+ secret: The secret to share (ZR element)
128
+ threshold: Minimum number of shares needed to reconstruct (t)
129
+ num_parties: Total number of parties (n)
130
+
131
+ Returns:
132
+ Dictionary mapping party_id (1 to n) to share values
133
+
134
+ >>> from charm.toolbox.eccurve import secp256k1
135
+ >>> group = ECGroup(secp256k1)
136
+ >>> ts = ThresholdSharing(group)
137
+ >>> secret = group.random(ZR)
138
+ >>> shares = ts.share(secret, threshold=2, num_parties=4)
139
+ >>> len(shares) == 4
140
+ True
141
+ >>> recovered = ts.reconstruct({1: shares[1], 3: shares[3]}, threshold=2)
142
+ >>> secret == recovered
143
+ True
144
+ """
145
+ if threshold > num_parties:
146
+ raise ValueError("threshold cannot exceed num_parties")
147
+ if threshold < 1:
148
+ raise ValueError("threshold must be at least 1")
149
+ if threshold > 256:
150
+ raise ValueError(f"Threshold {threshold} exceeds safe limit of 256 for polynomial evaluation")
151
+
152
+ # Generate random polynomial coefficients: a_0 = secret, a_1...a_{t-1} random
153
+ coeffs = [secret]
154
+ for _ in range(threshold - 1):
155
+ coeffs.append(self.group.random(ZR))
156
+
157
+ # Evaluate polynomial at points 1, 2, ..., n
158
+ shares = {}
159
+ for i in range(1, num_parties + 1):
160
+ shares[i] = self._eval_polynomial(coeffs, i)
161
+
162
+ return shares
163
+
164
+ def share_with_verification(self, secret: ZRElement, generator: GElement, threshold: int, num_parties: int) -> Tuple[Dict[int, ZRElement], List[GElement]]:
165
+ """
166
+ Feldman VSS - shares with public commitments for verification
167
+
168
+ Creates shares using Shamir's scheme and publishes commitments
169
+ C_j = g^{a_j} for each coefficient a_j, allowing verification
170
+ without revealing the secret.
171
+
172
+ Args:
173
+ secret: The secret to share (ZR element)
174
+ generator: Generator point g in the EC group (G element)
175
+ threshold: Minimum shares needed to reconstruct
176
+ num_parties: Total number of parties
177
+
178
+ Returns:
179
+ Tuple of (shares_dict, commitments_list)
180
+ - shares_dict: {party_id: share_value}
181
+ - commitments_list: [C_0, C_1, ..., C_{t-1}] where C_j = g^{a_j}
182
+
183
+ >>> from charm.toolbox.eccurve import secp256k1
184
+ >>> group = ECGroup(secp256k1)
185
+ >>> ts = ThresholdSharing(group)
186
+ >>> g = group.random(G)
187
+ >>> secret = group.random(ZR)
188
+ >>> shares, comms = ts.share_with_verification(secret, g, 2, 3)
189
+ >>> all(ts.verify_share(i, shares[i], comms, g) for i in range(1, 4))
190
+ True
191
+ """
192
+ if threshold > num_parties:
193
+ raise ValueError("threshold cannot exceed num_parties")
194
+ if threshold < 1:
195
+ raise ValueError("threshold must be at least 1")
196
+
197
+ # Generate polynomial coefficients
198
+ coeffs = [secret]
199
+ for _ in range(threshold - 1):
200
+ coeffs.append(self.group.random(ZR))
201
+
202
+ # Compute Feldman commitments: C_j = g^{a_j}
203
+ commitments = [generator ** coeff for coeff in coeffs]
204
+
205
+ # Generate shares
206
+ shares = {}
207
+ for i in range(1, num_parties + 1):
208
+ shares[i] = self._eval_polynomial(coeffs, i)
209
+
210
+ return shares, commitments
211
+
212
+ def verify_share(self, party_id: int, share: ZRElement, commitments: List[GElement], generator: GElement) -> bool:
213
+ """
214
+ Verify a share against Feldman commitments
215
+
216
+ Checks that g^{share} == prod_{j=0}^{t-1} C_j^{i^j}
217
+
218
+ Args:
219
+ party_id: The party's identifier (1 to n)
220
+ share: The share value to verify (ZR element)
221
+ commitments: List of Feldman commitments [C_0, ..., C_{t-1}]
222
+ generator: Generator point g used in commitments
223
+
224
+ Returns:
225
+ True if share is valid, False otherwise
226
+ """
227
+ # Compute g^{share}
228
+ lhs = generator ** share
229
+
230
+ # Compute prod_{j=0}^{t-1} C_j^{i^j}
231
+ rhs = commitments[0] # C_0^{i^0} = C_0
232
+ i_power = self.group.init(ZR, party_id)
233
+
234
+ for j in range(1, len(commitments)):
235
+ rhs = rhs * (commitments[j] ** i_power)
236
+ i_power = i_power * self.group.init(ZR, party_id)
237
+
238
+ return lhs == rhs
239
+
240
+ def reconstruct(self, shares: Dict[int, ZRElement], threshold: int) -> ZRElement:
241
+ """
242
+ Reconstruct secret from threshold shares using Lagrange interpolation
243
+
244
+ Args:
245
+ shares: Dictionary {party_id: share_value} with at least threshold entries
246
+ threshold: The threshold used when sharing
247
+
248
+ Returns:
249
+ The reconstructed secret
250
+
251
+ Raises:
252
+ ValueError: If fewer than threshold shares provided
253
+
254
+ >>> from charm.toolbox.eccurve import secp256k1
255
+ >>> group = ECGroup(secp256k1)
256
+ >>> ts = ThresholdSharing(group)
257
+ >>> secret = group.random(ZR)
258
+ >>> shares = ts.share(secret, threshold=3, num_parties=5)
259
+ >>> recovered = ts.reconstruct({1: shares[1], 2: shares[2], 4: shares[4]}, 3)
260
+ >>> secret == recovered
261
+ True
262
+ """
263
+ if len(shares) < threshold:
264
+ raise ValueError(f"Need at least {threshold} shares, got {len(shares)}")
265
+
266
+ party_ids = list(shares.keys())
267
+
268
+ # Compute secret = sum of (share_i * lagrange_coeff_i) at x=0
269
+ secret = self.group.init(ZR, 0)
270
+ for i in party_ids:
271
+ coeff = self.lagrange_coefficient(party_ids, i, x=0)
272
+ secret = secret + (shares[i] * coeff)
273
+
274
+ return secret
275
+
276
+ def lagrange_coefficient(self, party_ids: List[int], i: int, x: int = 0) -> ZRElement:
277
+ """
278
+ Compute Lagrange coefficient for party i at point x
279
+
280
+ L_i(x) = prod_{j != i} (x - j) / (i - j)
281
+
282
+ Args:
283
+ party_ids: List of party identifiers in the reconstruction set
284
+ i: The party for which to compute the coefficient
285
+ x: The evaluation point (default 0 for secret recovery)
286
+
287
+ Returns:
288
+ The Lagrange coefficient as a ZR element
289
+
290
+ >>> from charm.toolbox.eccurve import secp256k1
291
+ >>> group = ECGroup(secp256k1)
292
+ >>> ts = ThresholdSharing(group)
293
+ >>> coeff = ts.lagrange_coefficient([1, 2, 3], 1, x=0)
294
+ >>> # L_1(0) = (0-2)(0-3) / (1-2)(1-3) = 6/2 = 3
295
+ """
296
+ if isinstance(x, int):
297
+ x = self.group.init(ZR, x)
298
+ i_zr = self.group.init(ZR, i)
299
+
300
+ result = self.group.init(ZR, 1)
301
+ for j in party_ids:
302
+ if j != i:
303
+ j_zr = self.group.init(ZR, j)
304
+ numerator = x - j_zr
305
+ denominator = i_zr - j_zr
306
+ result = result * numerator * (denominator ** -1)
307
+
308
+ return result
309
+
310
+ def add_shares(self, shares1: Dict[int, ZRElement], shares2: Dict[int, ZRElement]) -> Dict[int, ZRElement]:
311
+ """
312
+ Add two sets of shares (for additive share combination)
313
+
314
+ Useful for distributed key generation and refreshing.
315
+
316
+ Args:
317
+ shares1: First dictionary of shares {party_id: share}
318
+ shares2: Second dictionary of shares {party_id: share}
319
+
320
+ Returns:
321
+ Dictionary of combined shares
322
+
323
+ >>> from charm.toolbox.eccurve import secp256k1
324
+ >>> group = ECGroup(secp256k1)
325
+ >>> ts = ThresholdSharing(group)
326
+ >>> s1, s2 = group.random(ZR), group.random(ZR)
327
+ >>> shares1 = ts.share(s1, 2, 3)
328
+ >>> shares2 = ts.share(s2, 2, 3)
329
+ >>> combined = ts.add_shares(shares1, shares2)
330
+ >>> recovered = ts.reconstruct({1: combined[1], 2: combined[2]}, 2)
331
+ >>> recovered == s1 + s2
332
+ True
333
+ """
334
+ if set(shares1.keys()) != set(shares2.keys()):
335
+ raise ValueError("Share sets must have same party IDs")
336
+
337
+ combined = {}
338
+ for party_id in shares1.keys():
339
+ combined[party_id] = shares1[party_id] + shares2[party_id]
340
+
341
+ return combined
342
+
343
+ def refresh_shares(self, shares: Dict[int, ZRElement], threshold: int) -> Dict[int, ZRElement]:
344
+ """
345
+ Refresh shares for proactive security
346
+
347
+ Generates new shares of zero and adds them to existing shares.
348
+ The new shares reconstruct to the same secret but are unlinkable
349
+ to the old shares.
350
+
351
+ Args:
352
+ shares: Dictionary of current shares {party_id: share}
353
+ threshold: The threshold of the sharing
354
+
355
+ Returns:
356
+ Dictionary of refreshed shares
357
+
358
+ >>> from charm.toolbox.eccurve import secp256k1
359
+ >>> group = ECGroup(secp256k1)
360
+ >>> ts = ThresholdSharing(group)
361
+ >>> secret = group.random(ZR)
362
+ >>> shares = ts.share(secret, 2, 3)
363
+ >>> refreshed = ts.refresh_shares(shares, 2)
364
+ >>> recovered = ts.reconstruct({1: refreshed[1], 3: refreshed[3]}, 2)
365
+ >>> secret == recovered
366
+ True
367
+ """
368
+ num_parties = len(shares)
369
+
370
+ # Create shares of zero
371
+ zero = self.group.init(ZR, 0)
372
+ zero_shares = self.share(zero, threshold, num_parties)
373
+
374
+ # Remap zero_shares to match party IDs in original shares
375
+ party_ids = sorted(shares.keys())
376
+ remapped_zero_shares = {}
377
+ for idx, party_id in enumerate(party_ids):
378
+ remapped_zero_shares[party_id] = zero_shares[idx + 1]
379
+
380
+ return self.add_shares(shares, remapped_zero_shares)
381
+
382
+
383
+ class PedersenVSS(ThresholdSharing):
384
+ """
385
+ Pedersen VSS with information-theoretic hiding
386
+
387
+ Uses two generators g, h for commitments where the discrete log
388
+ relationship between g and h is unknown. This provides unconditional
389
+ hiding of the secret, unlike Feldman VSS.
390
+
391
+ >>> from charm.toolbox.eccurve import secp256k1
392
+ >>> group = ECGroup(secp256k1)
393
+ >>> pvss = PedersenVSS(group)
394
+ >>> g = group.random(G)
395
+ >>> h = group.random(G)
396
+ >>> secret = group.random(ZR)
397
+ >>> shares, blindings, comms = pvss.share_with_blinding(secret, g, h, 2, 3)
398
+ >>> pvss.verify_pedersen_share(1, shares[1], blindings[1], comms, g, h)
399
+ True
400
+ >>> pvss.verify_pedersen_share(2, shares[2], blindings[2], comms, g, h)
401
+ True
402
+ >>> pvss.verify_pedersen_share(3, shares[3], blindings[3], comms, g, h)
403
+ True
404
+ >>> recovered = pvss.reconstruct({1: shares[1], 2: shares[2]}, 2)
405
+ >>> secret == recovered
406
+ True
407
+ """
408
+
409
+ def share_with_blinding(self, secret: ZRElement, g: GElement, h: GElement, threshold: int, num_parties: int) -> Tuple[Dict[int, ZRElement], Dict[int, ZRElement], List[GElement]]:
410
+ """
411
+ Share with Pedersen commitments (information-theoretically hiding)
412
+
413
+ Creates two polynomials:
414
+ - f(x) with f(0) = secret for the actual shares
415
+ - r(x) with r(0) = random blinding for hiding
416
+
417
+ Commitments are C_j = g^{a_j} * h^{b_j} where a_j, b_j are
418
+ coefficients of f and r respectively.
419
+
420
+ Args:
421
+ secret: The secret to share (ZR element)
422
+ g: First generator point
423
+ h: Second generator point (discrete log to g unknown)
424
+ threshold: Minimum shares needed to reconstruct
425
+ num_parties: Total number of parties
426
+
427
+ Returns:
428
+ Tuple of (shares_dict, blindings_dict, commitments_list)
429
+ - shares_dict: {party_id: share_value}
430
+ - blindings_dict: {party_id: blinding_value}
431
+ - commitments_list: [C_0, C_1, ..., C_{t-1}]
432
+
433
+ >>> from charm.toolbox.eccurve import secp256k1
434
+ >>> group = ECGroup(secp256k1)
435
+ >>> pvss = PedersenVSS(group)
436
+ >>> g, h = group.random(G), group.random(G)
437
+ >>> secret = group.random(ZR)
438
+ >>> shares, blindings, comms = pvss.share_with_blinding(secret, g, h, 2, 4)
439
+ >>> all(pvss.verify_pedersen_share(i, shares[i], blindings[i], comms, g, h)
440
+ ... for i in range(1, 5))
441
+ True
442
+ """
443
+ if threshold > num_parties:
444
+ raise ValueError("threshold cannot exceed num_parties")
445
+ if threshold < 1:
446
+ raise ValueError("threshold must be at least 1")
447
+
448
+ # Generate polynomial for secret: f(x) = a_0 + a_1*x + ... + a_{t-1}*x^{t-1}
449
+ secret_coeffs = [secret]
450
+ for _ in range(threshold - 1):
451
+ secret_coeffs.append(self.group.random(ZR))
452
+
453
+ # Generate polynomial for blinding: r(x) = b_0 + b_1*x + ... + b_{t-1}*x^{t-1}
454
+ blinding_coeffs = []
455
+ for _ in range(threshold):
456
+ blinding_coeffs.append(self.group.random(ZR))
457
+
458
+ # Compute Pedersen commitments: C_j = g^{a_j} * h^{b_j}
459
+ commitments = []
460
+ for j in range(threshold):
461
+ C_j = (g ** secret_coeffs[j]) * (h ** blinding_coeffs[j])
462
+ commitments.append(C_j)
463
+
464
+ # Generate shares and blindings
465
+ shares = {}
466
+ blindings = {}
467
+ for i in range(1, num_parties + 1):
468
+ shares[i] = self._eval_polynomial(secret_coeffs, i)
469
+ blindings[i] = self._eval_polynomial(blinding_coeffs, i)
470
+
471
+ return shares, blindings, commitments
472
+
473
+ def verify_pedersen_share(self, party_id: int, share: ZRElement, blinding: ZRElement, commitments: List[GElement], g: GElement, h: GElement) -> bool:
474
+ """
475
+ Verify a share against Pedersen commitments
476
+
477
+ Checks that g^{share} * h^{blinding} == prod_{j=0}^{t-1} C_j^{i^j}
478
+
479
+ Args:
480
+ party_id: The party's identifier (1 to n)
481
+ share: The share value (ZR element)
482
+ blinding: The blinding value (ZR element)
483
+ commitments: List of Pedersen commitments [C_0, ..., C_{t-1}]
484
+ g: First generator point
485
+ h: Second generator point
486
+
487
+ Returns:
488
+ True if share is valid, False otherwise
489
+
490
+ >>> from charm.toolbox.eccurve import secp256k1
491
+ >>> group = ECGroup(secp256k1)
492
+ >>> pvss = PedersenVSS(group)
493
+ >>> g, h = group.random(G), group.random(G)
494
+ >>> secret = group.random(ZR)
495
+ >>> shares, blindings, comms = pvss.share_with_blinding(secret, g, h, 3, 5)
496
+ >>> pvss.verify_pedersen_share(3, shares[3], blindings[3], comms, g, h)
497
+ True
498
+ """
499
+ # Compute g^{share} * h^{blinding}
500
+ lhs = (g ** share) * (h ** blinding)
501
+
502
+ # Compute prod_{j=0}^{t-1} C_j^{i^j}
503
+ rhs = commitments[0] # C_0^{i^0} = C_0
504
+ i_power = self.group.init(ZR, party_id)
505
+
506
+ for j in range(1, len(commitments)):
507
+ rhs = rhs * (commitments[j] ** i_power)
508
+ i_power = i_power * self.group.init(ZR, party_id)
509
+
510
+ return lhs == rhs
511
+
512
+ def combine_pedersen_commitments(self, commitments_list: List[List[GElement]]) -> List[GElement]:
513
+ """
514
+ Combine multiple Pedersen commitments (for DKG)
515
+
516
+ When multiple dealers contribute shares, their commitments
517
+ can be combined element-wise.
518
+
519
+ Args:
520
+ commitments_list: List of commitment lists from different dealers
521
+
522
+ Returns:
523
+ Combined commitments list
524
+
525
+ >>> from charm.toolbox.eccurve import secp256k1
526
+ >>> group = ECGroup(secp256k1)
527
+ >>> pvss = PedersenVSS(group)
528
+ >>> g, h = group.random(G), group.random(G)
529
+ >>> s1, s2 = group.random(ZR), group.random(ZR)
530
+ >>> _, _, comms1 = pvss.share_with_blinding(s1, g, h, 2, 3)
531
+ >>> _, _, comms2 = pvss.share_with_blinding(s2, g, h, 2, 3)
532
+ >>> combined = pvss.combine_pedersen_commitments([comms1, comms2])
533
+ >>> len(combined) == len(comms1)
534
+ True
535
+ """
536
+ if not commitments_list:
537
+ raise ValueError("Need at least one commitment list")
538
+
539
+ num_coeffs = len(commitments_list[0])
540
+ combined = list(commitments_list[0])
541
+
542
+ for comms in commitments_list[1:]:
543
+ if len(comms) != num_coeffs:
544
+ raise ValueError("All commitment lists must have same length")
545
+ for j in range(num_coeffs):
546
+ combined[j] = combined[j] * comms[j]
547
+
548
+ return combined
549
+
550
+
551
+ if __name__ == "__main__":
552
+ import doctest
553
+ doctest.testmod()
@@ -0,0 +1,94 @@
1
+ from charm.toolbox.pairinggroup import PairingGroup
2
+ from charm.toolbox.ecgroup import ECGroup
3
+ from charm.toolbox.integergroup import IntegerGroup
4
+ from charm.core.engine.util import bytesToObject,objectToBytes
5
+ from xml.dom.minidom import *
6
+
7
+ def writeToXML(object, groupObj, name=None):
8
+ """ Output
9
+ <?xml version="1.0" ?>
10
+ <charm>
11
+ <group param="SS512" setting="pairing">
12
+ <object>
13
+ This is a test!
14
+ </object>
15
+ </group>
16
+ </charm>
17
+ """
18
+ # Create the minidom document
19
+ doc = Document()
20
+
21
+ # Create the <wml> base element
22
+ charm = doc.createElement("charm")
23
+ doc.appendChild(charm)
24
+
25
+ # Create the main <card> element
26
+ maingroup = doc.createElement("group")
27
+ # make this programmatic
28
+ setting = groupObj.groupSetting()
29
+ param = groupObj.groupType()
30
+
31
+ maingroup.setAttribute("setting", setting)
32
+ maingroup.setAttribute("param", param)
33
+ charm.appendChild(maingroup)
34
+
35
+ # Create a <p> element
36
+ if name:
37
+ paragraph0 = doc.createElement("name")
38
+ paragraph0.setAttribute("id", name)
39
+ maingroup.appendChild(paragraph0)
40
+
41
+ paragraph1 = doc.createElement("object")
42
+ maingroup.appendChild(paragraph1)
43
+
44
+ # Give the <p> elemenet some text
45
+ # ptext = doc.createTextNode("This is a test!")
46
+ serializedObject = objectToBytes(object, groupObj)
47
+ ptext = doc.createTextNode(bytes.decode(serializedObject, 'utf8'))
48
+ paragraph1.appendChild(ptext)
49
+
50
+ # Print our newly created XML
51
+ print(doc.toprettyxml(indent=" "))
52
+ return doc.toprettyxml(indent=" ")
53
+
54
+ def getText(nodelist):
55
+ rc = []
56
+ for node in nodelist:
57
+ if node.nodeType == node.TEXT_NODE:
58
+ rc.append(node.data)
59
+ result = ''.join(rc)
60
+ return bytes(result, 'utf8')
61
+
62
+ def parseFromXML(xmlObjectString, group=None):
63
+ assert type(xmlObjectString) == str, "Invalid type for XML object"
64
+ dom = parseString(xmlObjectString)
65
+ assert dom.documentElement.tagName == "charm", "Not a Charm element"
66
+ # print(dom.toprettyxml(indent=" "))
67
+
68
+ groupObj = dom.getElementsByTagName("group")
69
+ assert groupObj != None, "Error: could not find group tag."
70
+ groupObj = groupObj[0]
71
+ charmObj1 = dom.getElementsByTagName("object")
72
+ assert charmObj1 != None, "Error: could not find object tag."
73
+ charmObj1 = charmObj1[0]
74
+
75
+ structure = {}
76
+ setting = groupObj.getAttribute("setting")
77
+ param = groupObj.getAttribute("param")
78
+
79
+ charmObj2 = dom.getElementsByTagName("name")
80
+ structure['name'] = None
81
+ if charmObj2 != None:
82
+ charmObj2 = charmObj2[0] # what is this useful for?
83
+ structure['name'] = charmObj2.getAttribute("id")
84
+
85
+ bytesObj = getText(charmObj1.childNodes).strip()
86
+
87
+ if setting == 'pairing' and group == None:
88
+ group = PairingGroup(param)
89
+ elif structure['setting'] == 'elliptic_curve' and group == None:
90
+ group = ECGroup(param)
91
+ elif structure['setting'] == 'integer':
92
+ # TODO: this is a special case
93
+ pass
94
+ return bytesToObject(bytesObj, group)