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.
- charm/__init__.py +5 -0
- charm/adapters/__init__.py +0 -0
- charm/adapters/abenc_adapt_hybrid.py +90 -0
- charm/adapters/dabenc_adapt_hybrid.py +145 -0
- charm/adapters/ibenc_adapt_hybrid.py +72 -0
- charm/adapters/ibenc_adapt_identityhash.py +80 -0
- charm/adapters/kpabenc_adapt_hybrid.py +91 -0
- charm/adapters/pkenc_adapt_bchk05.py +121 -0
- charm/adapters/pkenc_adapt_chk04.py +91 -0
- charm/adapters/pkenc_adapt_hybrid.py +98 -0
- charm/adapters/pksig_adapt_naor01.py +89 -0
- charm/config.py +7 -0
- charm/core/__init__.py +0 -0
- charm/core/benchmark/benchmark_util.c +353 -0
- charm/core/benchmark/benchmark_util.h +61 -0
- charm/core/benchmark/benchmarkmodule.c +476 -0
- charm/core/benchmark/benchmarkmodule.h +162 -0
- charm/core/benchmark.cpython-313-darwin.so +0 -0
- charm/core/crypto/AES/AES.c +1464 -0
- charm/core/crypto/AES.cpython-313-darwin.so +0 -0
- charm/core/crypto/DES/DES.c +113 -0
- charm/core/crypto/DES.cpython-313-darwin.so +0 -0
- charm/core/crypto/DES3/DES3.c +26 -0
- charm/core/crypto/DES3.cpython-313-darwin.so +0 -0
- charm/core/crypto/__init__.py +0 -0
- charm/core/crypto/cryptobase/XOR.c +80 -0
- charm/core/crypto/cryptobase/_counter.c +496 -0
- charm/core/crypto/cryptobase/_counter.h +54 -0
- charm/core/crypto/cryptobase/block_template.c +900 -0
- charm/core/crypto/cryptobase/block_template.h +69 -0
- charm/core/crypto/cryptobase/cryptobasemodule.c +220 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt.h +90 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_argchk.h +44 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_cfg.h +186 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_cipher.h +941 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_custom.h +556 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_des.c +1912 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_hash.h +407 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_mac.h +496 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_macros.h +435 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_math.h +534 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_misc.h +103 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_pk.h +653 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_pkcs.h +90 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_prng.h +199 -0
- charm/core/crypto/cryptobase/stream_template.c +271 -0
- charm/core/crypto/cryptobase/strxor.c +229 -0
- charm/core/crypto/cryptobase.cpython-313-darwin.so +0 -0
- charm/core/engine/__init__.py +5 -0
- charm/core/engine/protocol.py +293 -0
- charm/core/engine/util.py +174 -0
- charm/core/math/__init__.py +0 -0
- charm/core/math/elliptic_curve/ecmodule.c +1986 -0
- charm/core/math/elliptic_curve/ecmodule.h +230 -0
- charm/core/math/elliptic_curve.cpython-313-darwin.so +0 -0
- charm/core/math/elliptic_curve.pyi +63 -0
- charm/core/math/integer/integermodule.c +2539 -0
- charm/core/math/integer/integermodule.h +145 -0
- charm/core/math/integer.cpython-313-darwin.so +0 -0
- charm/core/math/integer.pyi +76 -0
- charm/core/math/pairing/miracl/miracl_config.h +37 -0
- charm/core/math/pairing/miracl/miracl_interface.h +118 -0
- charm/core/math/pairing/miracl/miracl_interface2.h +126 -0
- charm/core/math/pairing/miracl/pairingmodule2.c +2094 -0
- charm/core/math/pairing/miracl/pairingmodule2.h +307 -0
- charm/core/math/pairing/pairingmodule.c +2230 -0
- charm/core/math/pairing/pairingmodule.h +241 -0
- charm/core/math/pairing/relic/pairingmodule3.c +1853 -0
- charm/core/math/pairing/relic/pairingmodule3.h +233 -0
- charm/core/math/pairing/relic/relic_interface.c +1337 -0
- charm/core/math/pairing/relic/relic_interface.h +217 -0
- charm/core/math/pairing/relic/test_relic.c +171 -0
- charm/core/math/pairing.cpython-313-darwin.so +0 -0
- charm/core/math/pairing.pyi +69 -0
- charm/core/utilities/base64.c +248 -0
- charm/core/utilities/base64.h +15 -0
- charm/schemes/__init__.py +0 -0
- charm/schemes/abenc/__init__.py +0 -0
- charm/schemes/abenc/abenc_accountability_jyjxgd20.py +647 -0
- charm/schemes/abenc/abenc_bsw07.py +146 -0
- charm/schemes/abenc/abenc_ca_cpabe_ar17.py +684 -0
- charm/schemes/abenc/abenc_dacmacs_yj14.py +298 -0
- charm/schemes/abenc/abenc_lsw08.py +159 -0
- charm/schemes/abenc/abenc_maabe_rw15.py +236 -0
- charm/schemes/abenc/abenc_maabe_yj14.py +297 -0
- charm/schemes/abenc/abenc_tbpre_lww14.py +309 -0
- charm/schemes/abenc/abenc_unmcpabe_yahk14.py +223 -0
- charm/schemes/abenc/abenc_waters09.py +144 -0
- charm/schemes/abenc/abenc_yct14.py +208 -0
- charm/schemes/abenc/abenc_yllc15.py +178 -0
- charm/schemes/abenc/ac17.py +248 -0
- charm/schemes/abenc/bsw07.py +141 -0
- charm/schemes/abenc/cgw15.py +277 -0
- charm/schemes/abenc/dabe_aw11.py +204 -0
- charm/schemes/abenc/dfa_fe12.py +144 -0
- charm/schemes/abenc/pk_hve08.py +179 -0
- charm/schemes/abenc/waters11.py +143 -0
- charm/schemes/aggrsign_MuSig.py +150 -0
- charm/schemes/aggrsign_bls.py +267 -0
- charm/schemes/blindsig_ps16.py +654 -0
- charm/schemes/chamhash_adm05.py +113 -0
- charm/schemes/chamhash_rsa_hw09.py +100 -0
- charm/schemes/commit/__init__.py +0 -0
- charm/schemes/commit/commit_gs08.py +77 -0
- charm/schemes/commit/commit_pedersen92.py +53 -0
- charm/schemes/encap_bchk05.py +62 -0
- charm/schemes/grpsig/__init__.py +0 -0
- charm/schemes/grpsig/groupsig_bgls04.py +114 -0
- charm/schemes/grpsig/groupsig_bgls04_var.py +115 -0
- charm/schemes/hibenc/__init__.py +0 -0
- charm/schemes/hibenc/hibenc_bb04.py +105 -0
- charm/schemes/hibenc/hibenc_lew11.py +193 -0
- charm/schemes/ibenc/__init__.py +0 -0
- charm/schemes/ibenc/clpkc_rp03.py +119 -0
- charm/schemes/ibenc/ibenc_CW13_z.py +168 -0
- charm/schemes/ibenc/ibenc_bb03.py +94 -0
- charm/schemes/ibenc/ibenc_bf01.py +121 -0
- charm/schemes/ibenc/ibenc_ckrs09.py +120 -0
- charm/schemes/ibenc/ibenc_cllww12_z.py +172 -0
- charm/schemes/ibenc/ibenc_lsw08.py +120 -0
- charm/schemes/ibenc/ibenc_sw05.py +238 -0
- charm/schemes/ibenc/ibenc_waters05.py +144 -0
- charm/schemes/ibenc/ibenc_waters05_z.py +164 -0
- charm/schemes/ibenc/ibenc_waters09.py +107 -0
- charm/schemes/ibenc/ibenc_waters09_z.py +147 -0
- charm/schemes/joye_scheme.py +106 -0
- charm/schemes/lem_scheme.py +207 -0
- charm/schemes/pk_fre_ccv11.py +107 -0
- charm/schemes/pk_vrf.py +127 -0
- charm/schemes/pkenc/__init__.py +0 -0
- charm/schemes/pkenc/pkenc_cs98.py +108 -0
- charm/schemes/pkenc/pkenc_elgamal85.py +122 -0
- charm/schemes/pkenc/pkenc_gm82.py +98 -0
- charm/schemes/pkenc/pkenc_paillier99.py +118 -0
- charm/schemes/pkenc/pkenc_rabin.py +254 -0
- charm/schemes/pkenc/pkenc_rsa.py +186 -0
- charm/schemes/pksig/__init__.py +0 -0
- charm/schemes/pksig/pksig_CW13_z.py +135 -0
- charm/schemes/pksig/pksig_bls04.py +87 -0
- charm/schemes/pksig/pksig_boyen.py +156 -0
- charm/schemes/pksig/pksig_chch.py +97 -0
- charm/schemes/pksig/pksig_chp.py +70 -0
- charm/schemes/pksig/pksig_cl03.py +150 -0
- charm/schemes/pksig/pksig_cl04.py +87 -0
- charm/schemes/pksig/pksig_cllww12_z.py +142 -0
- charm/schemes/pksig/pksig_cyh.py +132 -0
- charm/schemes/pksig/pksig_dsa.py +76 -0
- charm/schemes/pksig/pksig_ecdsa.py +71 -0
- charm/schemes/pksig/pksig_hess.py +104 -0
- charm/schemes/pksig/pksig_hw.py +110 -0
- charm/schemes/pksig/pksig_lamport.py +63 -0
- charm/schemes/pksig/pksig_ps01.py +135 -0
- charm/schemes/pksig/pksig_ps02.py +124 -0
- charm/schemes/pksig/pksig_ps03.py +119 -0
- charm/schemes/pksig/pksig_rsa_hw09.py +206 -0
- charm/schemes/pksig/pksig_schnorr91.py +77 -0
- charm/schemes/pksig/pksig_waters.py +115 -0
- charm/schemes/pksig/pksig_waters05.py +121 -0
- charm/schemes/pksig/pksig_waters09.py +121 -0
- charm/schemes/pre_mg07.py +150 -0
- charm/schemes/prenc/pre_afgh06.py +126 -0
- charm/schemes/prenc/pre_bbs98.py +123 -0
- charm/schemes/prenc/pre_nal16.py +216 -0
- charm/schemes/protocol_a01.py +272 -0
- charm/schemes/protocol_ao00.py +215 -0
- charm/schemes/protocol_cns07.py +274 -0
- charm/schemes/protocol_schnorr91.py +125 -0
- charm/schemes/sigma1.py +64 -0
- charm/schemes/sigma2.py +129 -0
- charm/schemes/sigma3.py +126 -0
- charm/schemes/threshold/__init__.py +59 -0
- charm/schemes/threshold/dkls23_dkg.py +556 -0
- charm/schemes/threshold/dkls23_presign.py +1089 -0
- charm/schemes/threshold/dkls23_sign.py +761 -0
- charm/schemes/threshold/xrpl_wallet.py +967 -0
- charm/test/__init__.py +0 -0
- charm/test/adapters/__init__.py +0 -0
- charm/test/adapters/abenc_adapt_hybrid_test.py +29 -0
- charm/test/adapters/dabenc_adapt_hybrid_test.py +56 -0
- charm/test/adapters/ibenc_adapt_hybrid_test.py +36 -0
- charm/test/adapters/ibenc_adapt_identityhash_test.py +32 -0
- charm/test/adapters/kpabenc_adapt_hybrid_test.py +30 -0
- charm/test/benchmark/abenc_yllc15_bench.py +92 -0
- charm/test/benchmark/benchmark_test.py +148 -0
- charm/test/benchmark_threshold.py +260 -0
- charm/test/conftest.py +38 -0
- charm/test/fuzz/__init__.py +1 -0
- charm/test/fuzz/conftest.py +5 -0
- charm/test/fuzz/fuzz_policy_parser.py +76 -0
- charm/test/fuzz/fuzz_serialization.py +83 -0
- charm/test/schemes/__init__.py +0 -0
- charm/test/schemes/abenc/__init__.py +0 -0
- charm/test/schemes/abenc/abenc_bsw07_test.py +39 -0
- charm/test/schemes/abenc/abenc_dacmacs_yj14_test.py +16 -0
- charm/test/schemes/abenc/abenc_lsw08_test.py +33 -0
- charm/test/schemes/abenc/abenc_maabe_yj14_test.py +16 -0
- charm/test/schemes/abenc/abenc_tbpre_lww14_test.py +16 -0
- charm/test/schemes/abenc/abenc_waters09_test.py +38 -0
- charm/test/schemes/abenc/abenc_yllc15_test.py +74 -0
- charm/test/schemes/chamhash_adm05_test.py +31 -0
- charm/test/schemes/chamhash_rsa_hw09_test.py +29 -0
- charm/test/schemes/commit/__init__.py +0 -0
- charm/test/schemes/commit/commit_gs08_test.py +24 -0
- charm/test/schemes/commit/commit_pedersen92_test.py +26 -0
- charm/test/schemes/dabe_aw11_test.py +45 -0
- charm/test/schemes/encap_bchk05_test.py +21 -0
- charm/test/schemes/grpsig/__init__.py +0 -0
- charm/test/schemes/grpsig/groupsig_bgls04_test.py +35 -0
- charm/test/schemes/grpsig/groupsig_bgls04_var_test.py +39 -0
- charm/test/schemes/hibenc/__init__.py +0 -0
- charm/test/schemes/hibenc/hibenc_bb04_test.py +28 -0
- charm/test/schemes/ibenc/__init__.py +0 -0
- charm/test/schemes/ibenc/ibenc_bb03_test.py +26 -0
- charm/test/schemes/ibenc/ibenc_bf01_test.py +24 -0
- charm/test/schemes/ibenc/ibenc_ckrs09_test.py +25 -0
- charm/test/schemes/ibenc/ibenc_lsw08_test.py +31 -0
- charm/test/schemes/ibenc/ibenc_sw05_test.py +32 -0
- charm/test/schemes/ibenc/ibenc_waters05_test.py +31 -0
- charm/test/schemes/ibenc/ibenc_waters09_test.py +27 -0
- charm/test/schemes/pk_vrf_test.py +29 -0
- charm/test/schemes/pkenc/__init__.py +0 -0
- charm/test/schemes/pkenc_test.py +255 -0
- charm/test/schemes/pksig/__init__.py +0 -0
- charm/test/schemes/pksig_test.py +376 -0
- charm/test/schemes/rsa_alg_test.py +340 -0
- charm/test/schemes/threshold_test.py +1792 -0
- charm/test/serialize/__init__.py +0 -0
- charm/test/serialize/serialize_test.py +40 -0
- charm/test/toolbox/__init__.py +0 -0
- charm/test/toolbox/conversion_test.py +30 -0
- charm/test/toolbox/ecgroup_test.py +53 -0
- charm/test/toolbox/integer_arithmetic_test.py +441 -0
- charm/test/toolbox/paddingschemes_test.py +238 -0
- charm/test/toolbox/policy_parser_stress_test.py +969 -0
- charm/test/toolbox/secretshare_test.py +28 -0
- charm/test/toolbox/symcrypto_test.py +108 -0
- charm/test/toolbox/test_policy_expression.py +16 -0
- charm/test/vectors/__init__.py +1 -0
- charm/test/vectors/test_bls_vectors.py +289 -0
- charm/test/vectors/test_pedersen_vectors.py +315 -0
- charm/test/vectors/test_schnorr_vectors.py +368 -0
- charm/test/zkp_compiler/__init__.py +9 -0
- charm/test/zkp_compiler/benchmark_zkp.py +258 -0
- charm/test/zkp_compiler/test_and_proof.py +240 -0
- charm/test/zkp_compiler/test_batch_verify.py +248 -0
- charm/test/zkp_compiler/test_dleq_proof.py +264 -0
- charm/test/zkp_compiler/test_or_proof.py +231 -0
- charm/test/zkp_compiler/test_proof_serialization.py +121 -0
- charm/test/zkp_compiler/test_range_proof.py +241 -0
- charm/test/zkp_compiler/test_representation_proof.py +325 -0
- charm/test/zkp_compiler/test_schnorr_proof.py +221 -0
- charm/test/zkp_compiler/test_thread_safety.py +169 -0
- charm/test/zkp_compiler/test_zkp_parser.py +139 -0
- charm/toolbox/ABEnc.py +26 -0
- charm/toolbox/ABEncMultiAuth.py +66 -0
- charm/toolbox/ABEnumeric.py +800 -0
- charm/toolbox/Commit.py +24 -0
- charm/toolbox/DFA.py +89 -0
- charm/toolbox/FSA.py +1254 -0
- charm/toolbox/Hash.py +39 -0
- charm/toolbox/IBEnc.py +62 -0
- charm/toolbox/IBSig.py +64 -0
- charm/toolbox/PKEnc.py +66 -0
- charm/toolbox/PKSig.py +56 -0
- charm/toolbox/PREnc.py +32 -0
- charm/toolbox/ZKProof.py +289 -0
- charm/toolbox/__init__.py +0 -0
- charm/toolbox/bitstring.py +49 -0
- charm/toolbox/broadcast.py +220 -0
- charm/toolbox/conversion.py +100 -0
- charm/toolbox/eccurve.py +149 -0
- charm/toolbox/ecgroup.py +143 -0
- charm/toolbox/enum.py +60 -0
- charm/toolbox/hash_module.py +91 -0
- charm/toolbox/integergroup.py +323 -0
- charm/toolbox/iterate.py +22 -0
- charm/toolbox/matrixops.py +76 -0
- charm/toolbox/mpc_utils.py +296 -0
- charm/toolbox/msp.py +175 -0
- charm/toolbox/mta.py +985 -0
- charm/toolbox/node.py +120 -0
- charm/toolbox/ot/__init__.py +22 -0
- charm/toolbox/ot/base_ot.py +374 -0
- charm/toolbox/ot/dpf.py +642 -0
- charm/toolbox/ot/mpfss.py +228 -0
- charm/toolbox/ot/ot_extension.py +589 -0
- charm/toolbox/ot/silent_ot.py +378 -0
- charm/toolbox/paddingschemes.py +423 -0
- charm/toolbox/paddingschemes_test.py +238 -0
- charm/toolbox/pairingcurves.py +85 -0
- charm/toolbox/pairinggroup.py +186 -0
- charm/toolbox/policy_expression_spec.py +70 -0
- charm/toolbox/policytree.py +189 -0
- charm/toolbox/reCompiler.py +346 -0
- charm/toolbox/redundancyschemes.py +65 -0
- charm/toolbox/schemebase.py +188 -0
- charm/toolbox/secretshare.py +104 -0
- charm/toolbox/secretutil.py +174 -0
- charm/toolbox/securerandom.py +73 -0
- charm/toolbox/sigmaprotocol.py +46 -0
- charm/toolbox/specialprimes.py +45 -0
- charm/toolbox/symcrypto.py +279 -0
- charm/toolbox/threshold_sharing.py +553 -0
- charm/toolbox/xmlserialize.py +94 -0
- charm/toolbox/zknode.py +105 -0
- charm/zkp_compiler/__init__.py +89 -0
- charm/zkp_compiler/and_proof.py +460 -0
- charm/zkp_compiler/batch_verify.py +324 -0
- charm/zkp_compiler/dleq_proof.py +423 -0
- charm/zkp_compiler/or_proof.py +305 -0
- charm/zkp_compiler/range_proof.py +417 -0
- charm/zkp_compiler/representation_proof.py +466 -0
- charm/zkp_compiler/schnorr_proof.py +273 -0
- charm/zkp_compiler/thread_safe.py +150 -0
- charm/zkp_compiler/zk_demo.py +489 -0
- charm/zkp_compiler/zkp_factory.py +330 -0
- charm/zkp_compiler/zkp_generator.py +370 -0
- charm/zkp_compiler/zkparser.py +269 -0
- charm_crypto_framework-0.61.1.dist-info/METADATA +337 -0
- charm_crypto_framework-0.61.1.dist-info/RECORD +323 -0
- charm_crypto_framework-0.61.1.dist-info/WHEEL +5 -0
- charm_crypto_framework-0.61.1.dist-info/licenses/LICENSE.txt +165 -0
- 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)
|
charm/toolbox/eccurve.py
ADDED
|
@@ -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
|
+
}
|
charm/toolbox/ecgroup.py
ADDED
|
@@ -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
|