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
charm/toolbox/node.py
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import string
|
|
2
|
+
from charm.toolbox.enum import *
|
|
3
|
+
|
|
4
|
+
OpType = Enum('OR', 'AND', 'ATTR', 'THRESHOLD', 'CONDITIONAL', 'NONE')
|
|
5
|
+
|
|
6
|
+
class BinNode:
|
|
7
|
+
def __init__(self, value, left=None, right=None):
|
|
8
|
+
#types of node
|
|
9
|
+
# self.OR = 1
|
|
10
|
+
# self.AND = 2
|
|
11
|
+
# self.ATTR = 0
|
|
12
|
+
self.negated = False
|
|
13
|
+
self.index = None
|
|
14
|
+
#OF = '' # anything above 1 and 2
|
|
15
|
+
if(isinstance(value, str)):
|
|
16
|
+
if value[0] == '!':
|
|
17
|
+
value = value[1:] # remove but set flag
|
|
18
|
+
self.negated = True
|
|
19
|
+
if value.find('_') != -1:
|
|
20
|
+
val = value.split('_')
|
|
21
|
+
self.index = int(val[1]) # index
|
|
22
|
+
value = val[0]
|
|
23
|
+
self.type = OpType.ATTR
|
|
24
|
+
self.attribute = value.upper()
|
|
25
|
+
|
|
26
|
+
elif(value >= OpType.OR and value < OpType.NONE):
|
|
27
|
+
self.type = value
|
|
28
|
+
if self.type == OpType.OR:
|
|
29
|
+
self.threshold = 1
|
|
30
|
+
elif self.type == OpType.AND:
|
|
31
|
+
self.threshold = 2
|
|
32
|
+
# elif self.type == OpType.THRESHOLD:
|
|
33
|
+
self.attribute = ''
|
|
34
|
+
else:
|
|
35
|
+
self.type = None
|
|
36
|
+
self.attribute = ''
|
|
37
|
+
|
|
38
|
+
self.left = left
|
|
39
|
+
self.right = right
|
|
40
|
+
|
|
41
|
+
def __repr__(self):
|
|
42
|
+
return str(self)
|
|
43
|
+
|
|
44
|
+
def __str__(self):
|
|
45
|
+
if(self.type == OpType.ATTR):
|
|
46
|
+
if self.negated: prefix = '!'
|
|
47
|
+
else: prefix = ''
|
|
48
|
+
if self.index != None: postfix = '_' + str(self.index)
|
|
49
|
+
else: postfix = ''
|
|
50
|
+
return prefix + self.attribute + postfix
|
|
51
|
+
else:
|
|
52
|
+
left = str(self.left)
|
|
53
|
+
right = str(self.right)
|
|
54
|
+
|
|
55
|
+
if(self.type == OpType.OR):
|
|
56
|
+
return ('('+ left + ' or ' + right + ')')
|
|
57
|
+
elif(self.type == OpType.AND):
|
|
58
|
+
return ('(' + left + ' and ' + right + ')')
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
def getAttribute(self):
|
|
62
|
+
if (self.type == OpType.ATTR):
|
|
63
|
+
if self.negated: prefix = '!'
|
|
64
|
+
else: prefix = ''
|
|
65
|
+
return prefix + self.attribute
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
def getAttributeAndIndex(self):
|
|
69
|
+
if (self.type == OpType.ATTR):
|
|
70
|
+
if self.negated: prefix = '!'
|
|
71
|
+
else: prefix = ''
|
|
72
|
+
if self.index != None: postfix = '_' + str(self.index)
|
|
73
|
+
else: postfix = ''
|
|
74
|
+
|
|
75
|
+
return prefix + self.attribute + postfix
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
def __iter__(self):
|
|
79
|
+
return self
|
|
80
|
+
|
|
81
|
+
def __eq__(self, other):
|
|
82
|
+
#print("checking...:", self, str(other))
|
|
83
|
+
if other == None:
|
|
84
|
+
return False
|
|
85
|
+
if type(self) == type(other):
|
|
86
|
+
return self.getAttribute() == other.getAttribute()
|
|
87
|
+
elif type(other) in [str, bytes]:
|
|
88
|
+
return other in self.getAttributeAndIndex()
|
|
89
|
+
elif type(self) in [str, bytes]:
|
|
90
|
+
return self in other.getAttributeAndIndex()
|
|
91
|
+
else:
|
|
92
|
+
raise ValueError('BinNode - invalid comparison.')
|
|
93
|
+
|
|
94
|
+
def getLeft(self):
|
|
95
|
+
return self.left
|
|
96
|
+
|
|
97
|
+
def getRight(self):
|
|
98
|
+
return self.right
|
|
99
|
+
|
|
100
|
+
def getNodeType(self):
|
|
101
|
+
return self.type
|
|
102
|
+
|
|
103
|
+
def addSubNode(self, left, right):
|
|
104
|
+
# set subNodes appropriately
|
|
105
|
+
self.left = left if left != None else None
|
|
106
|
+
self.right = right if left != None else None
|
|
107
|
+
|
|
108
|
+
# only applies function on leaf nodes
|
|
109
|
+
def traverse(self, function):
|
|
110
|
+
# visit node then traverse left and right
|
|
111
|
+
function(self.type, self)
|
|
112
|
+
if(self.left == None):
|
|
113
|
+
return None
|
|
114
|
+
self.left.traverse(function)
|
|
115
|
+
if(self.right == None):
|
|
116
|
+
return None
|
|
117
|
+
self.right.traverse(function)
|
|
118
|
+
return None
|
|
119
|
+
|
|
120
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Oblivious Transfer (OT) Protocols for Charm
|
|
3
|
+
|
|
4
|
+
This module provides implementations of Oblivious Transfer protocols
|
|
5
|
+
for use with elliptic curve groups.
|
|
6
|
+
|
|
7
|
+
Available classes:
|
|
8
|
+
- SimpleOT: Simplest OT (Chou-Orlandi style) for 1-out-of-2 OT
|
|
9
|
+
- OTExtension: IKNP-style OT Extension for efficient many-OT execution
|
|
10
|
+
- DPF: Distributed Point Function based on GGM construction
|
|
11
|
+
- MPFSS: Multi-Point Function Secret Sharing using DPF
|
|
12
|
+
- SilentOT: Silent OT Extension using PCG (Boyle et al. Crypto 2019)
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from charm.toolbox.ot.base_ot import SimpleOT
|
|
16
|
+
from charm.toolbox.ot.ot_extension import OTExtension
|
|
17
|
+
from charm.toolbox.ot.dpf import DPF
|
|
18
|
+
from charm.toolbox.ot.mpfss import MPFSS
|
|
19
|
+
from charm.toolbox.ot.silent_ot import SilentOT
|
|
20
|
+
|
|
21
|
+
__all__ = ['SimpleOT', 'OTExtension', 'DPF', 'MPFSS', 'SilentOT']
|
|
22
|
+
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Simplest Oblivious Transfer (Chou-Orlandi style) for Elliptic Curve Groups
|
|
3
|
+
|
|
4
|
+
| From: "The Simplest Protocol for Oblivious Transfer"
|
|
5
|
+
| By: Tung Chou and Claudio Orlandi
|
|
6
|
+
| Published: LATINCRYPT 2015
|
|
7
|
+
| URL: https://eprint.iacr.org/2015/267
|
|
8
|
+
|
|
9
|
+
* type: oblivious transfer (1-out-of-2)
|
|
10
|
+
* setting: Elliptic Curve DDH-hard group
|
|
11
|
+
* assumption: DDH
|
|
12
|
+
|
|
13
|
+
:Authors: Elton de Souza
|
|
14
|
+
:Date: 01/2026
|
|
15
|
+
'''
|
|
16
|
+
|
|
17
|
+
from charm.toolbox.ecgroup import ECGroup, ZR, G
|
|
18
|
+
from charm.toolbox.symcrypto import AuthenticatedCryptoAbstraction
|
|
19
|
+
from hashlib import sha256
|
|
20
|
+
import logging
|
|
21
|
+
|
|
22
|
+
# Module logger
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class SimpleOT:
|
|
27
|
+
"""
|
|
28
|
+
Simplest Oblivious Transfer based on Chou-Orlandi for EC groups.
|
|
29
|
+
|
|
30
|
+
This implementation is thread-safe - each instance maintains its own
|
|
31
|
+
group reference and state.
|
|
32
|
+
|
|
33
|
+
Implements 1-out-of-2 OT where:
|
|
34
|
+
- Sender has two messages (m0, m1)
|
|
35
|
+
- Receiver has a choice bit b
|
|
36
|
+
- Receiver learns m_b without learning m_{1-b}
|
|
37
|
+
- Sender learns nothing about b
|
|
38
|
+
|
|
39
|
+
>>> from charm.toolbox.eccurve import secp256k1
|
|
40
|
+
>>> from charm.toolbox.ecgroup import ECGroup
|
|
41
|
+
>>> group = ECGroup(secp256k1)
|
|
42
|
+
>>> sender = SimpleOT(group)
|
|
43
|
+
>>> receiver = SimpleOT(group)
|
|
44
|
+
>>> # Sender setup: generates public parameters
|
|
45
|
+
>>> sender_params = sender.sender_setup()
|
|
46
|
+
>>> # Receiver chooses bit 0
|
|
47
|
+
>>> receiver_response, receiver_state = receiver.receiver_choose(sender_params, 0)
|
|
48
|
+
>>> # Sender transfers encrypted messages
|
|
49
|
+
>>> m0, m1 = b'message zero!!!!', b'message one!!!!!'
|
|
50
|
+
>>> ciphertexts = sender.sender_transfer(receiver_response, m0, m1)
|
|
51
|
+
>>> # Receiver retrieves chosen message
|
|
52
|
+
>>> result = receiver.receiver_retrieve(ciphertexts, receiver_state)
|
|
53
|
+
>>> result == m0
|
|
54
|
+
True
|
|
55
|
+
>>> # Test with choice bit 1
|
|
56
|
+
>>> sender2 = SimpleOT(group)
|
|
57
|
+
>>> receiver2 = SimpleOT(group)
|
|
58
|
+
>>> sender_params2 = sender2.sender_setup()
|
|
59
|
+
>>> receiver_response2, receiver_state2 = receiver2.receiver_choose(sender_params2, 1)
|
|
60
|
+
>>> ciphertexts2 = sender2.sender_transfer(receiver_response2, m0, m1)
|
|
61
|
+
>>> result2 = receiver2.receiver_retrieve(ciphertexts2, receiver_state2)
|
|
62
|
+
>>> result2 == m1
|
|
63
|
+
True
|
|
64
|
+
|
|
65
|
+
Security Note
|
|
66
|
+
-------------
|
|
67
|
+
- Each SimpleOT instance should be used for a SINGLE OT operation.
|
|
68
|
+
- Reusing instances with the same keys is NOT recommended for security.
|
|
69
|
+
- The instance generates fresh randomness per transfer but shares the
|
|
70
|
+
sender's key across transfers if sender_setup is not called again.
|
|
71
|
+
- For multiple OT operations, create new SimpleOT instances or use
|
|
72
|
+
OT extension (see OTExtension class).
|
|
73
|
+
- To regenerate keys on an existing instance, call reset_sender() before
|
|
74
|
+
sender_setup(), or simply call sender_setup() again which generates
|
|
75
|
+
fresh keys.
|
|
76
|
+
|
|
77
|
+
Security Limitations
|
|
78
|
+
--------------------
|
|
79
|
+
WARNING: This implementation is NOT constant-time and is vulnerable to
|
|
80
|
+
timing attacks. The following operations leak timing information:
|
|
81
|
+
|
|
82
|
+
- Modular inversion: Variable-time modular inverse operations
|
|
83
|
+
- Bit extraction: Conditional logic based on secret choice bit values
|
|
84
|
+
- Conditional branching: Control flow depends on secret data
|
|
85
|
+
|
|
86
|
+
This implementation is suitable for research and educational purposes only.
|
|
87
|
+
Do NOT use in production environments where side-channel attacks are a concern.
|
|
88
|
+
Production deployments should use constant-time cryptographic implementations
|
|
89
|
+
with proper side-channel mitigations.
|
|
90
|
+
|
|
91
|
+
Encryption Note
|
|
92
|
+
---------------
|
|
93
|
+
This implementation uses AuthenticatedCryptoAbstraction for symmetric
|
|
94
|
+
encryption of OT messages. The current implementation provides AEAD
|
|
95
|
+
(Authenticated Encryption with Associated Data) using AES-CBC with
|
|
96
|
+
HMAC-SHA256 in an Encrypt-then-MAC construction. While this provides
|
|
97
|
+
authentication, it is not as robust as AES-GCM. For production use,
|
|
98
|
+
consider verifying the underlying implementation uses authenticated
|
|
99
|
+
encryption (e.g., AES-GCM) to prevent ciphertext malleability attacks.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
def __init__(self, groupObj):
|
|
103
|
+
"""
|
|
104
|
+
Initialize SimpleOT with an elliptic curve group.
|
|
105
|
+
|
|
106
|
+
Parameters
|
|
107
|
+
----------
|
|
108
|
+
groupObj : ECGroup
|
|
109
|
+
An elliptic curve group object from charm.toolbox.ecgroup
|
|
110
|
+
"""
|
|
111
|
+
if groupObj is None:
|
|
112
|
+
raise ValueError("groupObj cannot be None")
|
|
113
|
+
self.group = groupObj
|
|
114
|
+
self._a = None # Sender's private key
|
|
115
|
+
self._A = None # Sender's public key
|
|
116
|
+
self._g = None # Generator point
|
|
117
|
+
|
|
118
|
+
def _derive_key(self, point):
|
|
119
|
+
"""
|
|
120
|
+
Derive a symmetric key from an EC point using SHA-256.
|
|
121
|
+
|
|
122
|
+
Parameters
|
|
123
|
+
----------
|
|
124
|
+
point : ec_element
|
|
125
|
+
An elliptic curve point
|
|
126
|
+
|
|
127
|
+
Returns
|
|
128
|
+
-------
|
|
129
|
+
bytes
|
|
130
|
+
32-byte key suitable for symmetric encryption
|
|
131
|
+
"""
|
|
132
|
+
point_bytes = self.group.serialize(point)
|
|
133
|
+
return sha256(point_bytes).digest()
|
|
134
|
+
|
|
135
|
+
def _validate_point(self, point, name="point"):
|
|
136
|
+
"""
|
|
137
|
+
Validate that a point is a valid non-identity element on the curve.
|
|
138
|
+
|
|
139
|
+
Parameters
|
|
140
|
+
----------
|
|
141
|
+
point : ec_element
|
|
142
|
+
An elliptic curve point to validate
|
|
143
|
+
name : str
|
|
144
|
+
Name of the point for error messages
|
|
145
|
+
|
|
146
|
+
Raises
|
|
147
|
+
------
|
|
148
|
+
ValueError
|
|
149
|
+
If the point is invalid, at infinity (identity), or not on the curve
|
|
150
|
+
|
|
151
|
+
Note on Subgroup Validation
|
|
152
|
+
---------------------------
|
|
153
|
+
For curves with cofactor > 1 (e.g., Curve25519 with cofactor 8), an
|
|
154
|
+
additional subgroup membership test is required to prevent small subgroup
|
|
155
|
+
attacks. This check verifies that ``point ** order == identity``.
|
|
156
|
+
|
|
157
|
+
However, secp256k1 (the default curve) has **cofactor 1** (prime order
|
|
158
|
+
group), meaning all non-identity points on the curve are already in the
|
|
159
|
+
prime-order subgroup. Therefore, subgroup validation is unnecessary for
|
|
160
|
+
secp256k1 and is not performed here.
|
|
161
|
+
|
|
162
|
+
If this implementation is extended to support curves with cofactor > 1,
|
|
163
|
+
add the following check after the on-curve validation::
|
|
164
|
+
|
|
165
|
+
# Subgroup membership test (required for curves with cofactor > 1):
|
|
166
|
+
# order = self.group.order()
|
|
167
|
+
# if not (point ** order).isInf():
|
|
168
|
+
# raise ValueError(f"Invalid {name}: point not in prime-order subgroup")
|
|
169
|
+
"""
|
|
170
|
+
# Check for identity element (point at infinity)
|
|
171
|
+
if point.isInf():
|
|
172
|
+
raise ValueError(f"Invalid {name}: point is at infinity (identity element)")
|
|
173
|
+
|
|
174
|
+
# Validate point is on curve by serialize/deserialize round-trip
|
|
175
|
+
# The deserialize function validates the point is on the curve
|
|
176
|
+
try:
|
|
177
|
+
serialized = self.group.serialize(point)
|
|
178
|
+
deserialized = self.group.deserialize(serialized)
|
|
179
|
+
if deserialized is None or deserialized is False:
|
|
180
|
+
raise ValueError(f"Invalid {name}: point is not on the curve")
|
|
181
|
+
except Exception as e:
|
|
182
|
+
raise ValueError(f"Invalid {name}: failed to validate point - {e}")
|
|
183
|
+
|
|
184
|
+
# Note: Subgroup membership test is NOT performed here because secp256k1
|
|
185
|
+
# has cofactor 1. For curves with cofactor > 1, uncomment the check above.
|
|
186
|
+
|
|
187
|
+
def reset_sender(self):
|
|
188
|
+
"""
|
|
189
|
+
Reset the sender's state, clearing all keys.
|
|
190
|
+
|
|
191
|
+
Call this method before sender_setup() to ensure fresh keys are
|
|
192
|
+
generated. This is useful when reusing a SimpleOT instance for
|
|
193
|
+
multiple OT operations (though creating new instances is preferred).
|
|
194
|
+
|
|
195
|
+
Note: sender_setup() also generates fresh keys, so calling
|
|
196
|
+
reset_sender() is optional but makes the intent explicit.
|
|
197
|
+
"""
|
|
198
|
+
self._a = None
|
|
199
|
+
self._A = None
|
|
200
|
+
self._g = None
|
|
201
|
+
logger.debug("Sender state reset - keys cleared")
|
|
202
|
+
|
|
203
|
+
def sender_setup(self):
|
|
204
|
+
"""
|
|
205
|
+
Sender generates public parameters for the OT protocol.
|
|
206
|
+
|
|
207
|
+
Returns
|
|
208
|
+
-------
|
|
209
|
+
dict
|
|
210
|
+
Dictionary containing:
|
|
211
|
+
- 'A': sender's public key (g^a)
|
|
212
|
+
- 'g': generator point
|
|
213
|
+
"""
|
|
214
|
+
self._a = self.group.random(ZR)
|
|
215
|
+
g = self.group.random(G)
|
|
216
|
+
self._A = g ** self._a
|
|
217
|
+
self._g = g
|
|
218
|
+
|
|
219
|
+
logger.debug("Sender setup: a=%s, A=%s, g=%s", self._a, self._A, g)
|
|
220
|
+
|
|
221
|
+
return {'A': self._A, 'g': g}
|
|
222
|
+
|
|
223
|
+
def receiver_choose(self, sender_params, choice_bit):
|
|
224
|
+
"""
|
|
225
|
+
Receiver generates response based on choice bit.
|
|
226
|
+
|
|
227
|
+
Parameters
|
|
228
|
+
----------
|
|
229
|
+
sender_params : dict
|
|
230
|
+
Public parameters from sender_setup containing 'A' and 'g'
|
|
231
|
+
choice_bit : int
|
|
232
|
+
The receiver's choice (0 or 1)
|
|
233
|
+
|
|
234
|
+
Returns
|
|
235
|
+
-------
|
|
236
|
+
tuple
|
|
237
|
+
(receiver_response, receiver_state) where:
|
|
238
|
+
- receiver_response: dict with 'B' to send to sender
|
|
239
|
+
- receiver_state: dict with private state for receiver_retrieve
|
|
240
|
+
|
|
241
|
+
Raises
|
|
242
|
+
------
|
|
243
|
+
ValueError
|
|
244
|
+
If choice_bit is not 0 or 1, or if sender's points are invalid
|
|
245
|
+
"""
|
|
246
|
+
if choice_bit not in (0, 1):
|
|
247
|
+
raise ValueError("choice_bit must be 0 or 1")
|
|
248
|
+
|
|
249
|
+
A = sender_params['A']
|
|
250
|
+
g = sender_params['g']
|
|
251
|
+
|
|
252
|
+
# Validate sender's points are valid curve points (not identity or off-curve)
|
|
253
|
+
# This prevents attacks using invalid or small-subgroup points
|
|
254
|
+
self._validate_point(g, "generator g")
|
|
255
|
+
self._validate_point(A, "sender public key A")
|
|
256
|
+
|
|
257
|
+
# Receiver picks random b
|
|
258
|
+
b = self.group.random(ZR)
|
|
259
|
+
|
|
260
|
+
# Compute B based on choice:
|
|
261
|
+
# If choice=0: B = g^b (so B^a = g^(ab) = k0)
|
|
262
|
+
# If choice=1: B = A * g^b (so (B/A)^a = g^(ab) = k1)
|
|
263
|
+
if choice_bit == 0:
|
|
264
|
+
B = g ** b
|
|
265
|
+
else:
|
|
266
|
+
B = A * (g ** b)
|
|
267
|
+
|
|
268
|
+
logger.debug("Receiver choose (bit=%d): b=%s, B=%s", choice_bit, b, B)
|
|
269
|
+
|
|
270
|
+
# The key the receiver will compute: k_choice = A^b
|
|
271
|
+
receiver_state = {
|
|
272
|
+
'b': b,
|
|
273
|
+
'A': A,
|
|
274
|
+
'choice_bit': choice_bit
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return {'B': B}, receiver_state
|
|
278
|
+
|
|
279
|
+
def sender_transfer(self, receiver_response, m0, m1):
|
|
280
|
+
"""
|
|
281
|
+
Sender encrypts both messages using derived keys.
|
|
282
|
+
|
|
283
|
+
Parameters
|
|
284
|
+
----------
|
|
285
|
+
receiver_response : dict
|
|
286
|
+
Response from receiver_choose containing 'B'
|
|
287
|
+
m0 : bytes
|
|
288
|
+
First message (sent if receiver chose 0)
|
|
289
|
+
m1 : bytes
|
|
290
|
+
Second message (sent if receiver chose 1)
|
|
291
|
+
|
|
292
|
+
Returns
|
|
293
|
+
-------
|
|
294
|
+
dict
|
|
295
|
+
Dictionary containing:
|
|
296
|
+
- 'e0': encrypted m0
|
|
297
|
+
- 'e1': encrypted m1
|
|
298
|
+
|
|
299
|
+
Raises
|
|
300
|
+
------
|
|
301
|
+
RuntimeError
|
|
302
|
+
If sender_setup was not called first
|
|
303
|
+
"""
|
|
304
|
+
if self._a is None or self._A is None:
|
|
305
|
+
raise RuntimeError("sender_setup must be called before sender_transfer")
|
|
306
|
+
|
|
307
|
+
B = receiver_response['B']
|
|
308
|
+
|
|
309
|
+
# Validate receiver's point B is a valid curve point (not identity or off-curve)
|
|
310
|
+
# This prevents attacks using invalid or small-subgroup points
|
|
311
|
+
self._validate_point(B, "receiver public key B")
|
|
312
|
+
|
|
313
|
+
# Compute keys:
|
|
314
|
+
# k0 = H(B^a) - receiver gets this if they chose 0
|
|
315
|
+
# k1 = H((B/A)^a) = H(B^a / A^a) - receiver gets this if they chose 1
|
|
316
|
+
k0_point = B ** self._a
|
|
317
|
+
k1_point = (B * (self._A ** -1)) ** self._a
|
|
318
|
+
|
|
319
|
+
k0 = self._derive_key(k0_point)
|
|
320
|
+
k1 = self._derive_key(k1_point)
|
|
321
|
+
|
|
322
|
+
logger.debug("Sender transfer: k0_point=%s, k1_point=%s", k0_point, k1_point)
|
|
323
|
+
|
|
324
|
+
# Encrypt messages
|
|
325
|
+
cipher0 = AuthenticatedCryptoAbstraction(k0)
|
|
326
|
+
cipher1 = AuthenticatedCryptoAbstraction(k1)
|
|
327
|
+
|
|
328
|
+
e0 = cipher0.encrypt(m0)
|
|
329
|
+
e1 = cipher1.encrypt(m1)
|
|
330
|
+
|
|
331
|
+
return {'e0': e0, 'e1': e1}
|
|
332
|
+
|
|
333
|
+
def receiver_retrieve(self, sender_ciphertexts, receiver_state):
|
|
334
|
+
"""
|
|
335
|
+
Receiver decrypts the chosen message.
|
|
336
|
+
|
|
337
|
+
Parameters
|
|
338
|
+
----------
|
|
339
|
+
sender_ciphertexts : dict
|
|
340
|
+
Ciphertexts from sender_transfer containing 'e0' and 'e1'
|
|
341
|
+
receiver_state : dict
|
|
342
|
+
Private state from receiver_choose
|
|
343
|
+
|
|
344
|
+
Returns
|
|
345
|
+
-------
|
|
346
|
+
bytes
|
|
347
|
+
The decrypted chosen message
|
|
348
|
+
|
|
349
|
+
Raises
|
|
350
|
+
------
|
|
351
|
+
ValueError
|
|
352
|
+
If decryption fails (should not happen in honest execution)
|
|
353
|
+
"""
|
|
354
|
+
b = receiver_state['b']
|
|
355
|
+
A = receiver_state['A']
|
|
356
|
+
choice_bit = receiver_state['choice_bit']
|
|
357
|
+
|
|
358
|
+
# Compute the key: k_choice = A^b
|
|
359
|
+
# This equals:
|
|
360
|
+
# - k0 = (g^a)^b = g^(ab) if choice=0 (since B = g^b, B^a = g^(ab))
|
|
361
|
+
# - k1 = (g^a)^b = g^(ab) if choice=1 (since B = A*g^b, (B/A)^a = g^(ab))
|
|
362
|
+
k_point = A ** b
|
|
363
|
+
k = self._derive_key(k_point)
|
|
364
|
+
|
|
365
|
+
logger.debug("Receiver retrieve (choice=%d): k_point=%s", choice_bit, k_point)
|
|
366
|
+
|
|
367
|
+
# Decrypt the chosen ciphertext
|
|
368
|
+
cipher = AuthenticatedCryptoAbstraction(k)
|
|
369
|
+
|
|
370
|
+
if choice_bit == 0:
|
|
371
|
+
return cipher.decrypt(sender_ciphertexts['e0'])
|
|
372
|
+
else:
|
|
373
|
+
return cipher.decrypt(sender_ciphertexts['e1'])
|
|
374
|
+
|