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,296 @@
|
|
|
1
|
+
'''
|
|
2
|
+
MPC Utility Functions for Charm
|
|
3
|
+
|
|
4
|
+
Common utilities for multi-party computation protocols including:
|
|
5
|
+
- Byte/integer conversion with consistent big-endian ordering
|
|
6
|
+
- Bit decomposition and reconstruction for OT-based protocols
|
|
7
|
+
- Pedersen commitment scheme for hiding commitments
|
|
8
|
+
|
|
9
|
+
:Authors: Elton de Souza
|
|
10
|
+
:Date: 01/2026
|
|
11
|
+
'''
|
|
12
|
+
|
|
13
|
+
from charm.toolbox.ecgroup import ECGroup, ZR, G
|
|
14
|
+
from typing import List, Tuple, Any, Optional
|
|
15
|
+
|
|
16
|
+
# Type aliases
|
|
17
|
+
ZRElement = Any
|
|
18
|
+
GElement = Any
|
|
19
|
+
ECGroupType = Any
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def int_to_bytes(n: int, length: int) -> bytes:
|
|
23
|
+
"""
|
|
24
|
+
Convert a non-negative integer to a fixed-length byte string.
|
|
25
|
+
|
|
26
|
+
Uses big-endian byte ordering (most significant byte first),
|
|
27
|
+
which is standard for cryptographic protocols.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
n : int
|
|
32
|
+
Non-negative integer to convert. Must fit within `length` bytes.
|
|
33
|
+
length : int
|
|
34
|
+
Exact number of bytes in the output. Value is zero-padded if needed.
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
bytes
|
|
39
|
+
Big-endian representation of `n` with exactly `length` bytes.
|
|
40
|
+
|
|
41
|
+
Raises
|
|
42
|
+
------
|
|
43
|
+
OverflowError
|
|
44
|
+
If `n` is too large to fit in `length` bytes.
|
|
45
|
+
ValueError
|
|
46
|
+
If `n` is negative.
|
|
47
|
+
|
|
48
|
+
Examples
|
|
49
|
+
--------
|
|
50
|
+
>>> int_to_bytes(256, 2)
|
|
51
|
+
b'\\x01\\x00'
|
|
52
|
+
>>> int_to_bytes(0, 4)
|
|
53
|
+
b'\\x00\\x00\\x00\\x00'
|
|
54
|
+
"""
|
|
55
|
+
if n < 0:
|
|
56
|
+
raise ValueError("n must be non-negative")
|
|
57
|
+
return n.to_bytes(length, byteorder='big')
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def bytes_to_int(b: bytes) -> int:
|
|
61
|
+
"""
|
|
62
|
+
Convert a byte string to a non-negative integer.
|
|
63
|
+
|
|
64
|
+
Uses big-endian byte ordering (most significant byte first),
|
|
65
|
+
which is standard for cryptographic protocols.
|
|
66
|
+
|
|
67
|
+
Parameters
|
|
68
|
+
----------
|
|
69
|
+
b : bytes
|
|
70
|
+
Byte string to convert.
|
|
71
|
+
|
|
72
|
+
Returns
|
|
73
|
+
-------
|
|
74
|
+
int
|
|
75
|
+
The integer value represented by the bytes.
|
|
76
|
+
|
|
77
|
+
Examples
|
|
78
|
+
--------
|
|
79
|
+
>>> bytes_to_int(b'\\x01\\x00')
|
|
80
|
+
256
|
|
81
|
+
>>> bytes_to_int(b'\\x00\\x00\\x00\\x00')
|
|
82
|
+
0
|
|
83
|
+
"""
|
|
84
|
+
return int.from_bytes(b, byteorder='big')
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def bit_decompose(value: Any, order: int, num_bits: int) -> List[int]:
|
|
88
|
+
"""
|
|
89
|
+
Decompose a field element into its bit representation.
|
|
90
|
+
|
|
91
|
+
The input value is first reduced modulo order to ensure consistent
|
|
92
|
+
behavior for values at or near the group order boundary.
|
|
93
|
+
|
|
94
|
+
Parameters
|
|
95
|
+
----------
|
|
96
|
+
value : ZR element or int
|
|
97
|
+
The value to decompose (will be reduced mod order)
|
|
98
|
+
order : int
|
|
99
|
+
The group order
|
|
100
|
+
num_bits : int
|
|
101
|
+
Number of bits to extract
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
list of int
|
|
106
|
+
List of bits (0 or 1), LSB first
|
|
107
|
+
|
|
108
|
+
Examples
|
|
109
|
+
--------
|
|
110
|
+
>>> bit_decompose(5, 2**256, 4)
|
|
111
|
+
[1, 0, 1, 0]
|
|
112
|
+
>>> bit_decompose(0, 2**256, 4)
|
|
113
|
+
[0, 0, 0, 0]
|
|
114
|
+
"""
|
|
115
|
+
if hasattr(value, '__int__'):
|
|
116
|
+
v = int(value) % order
|
|
117
|
+
else:
|
|
118
|
+
v = int(str(value)) % order
|
|
119
|
+
|
|
120
|
+
bits = []
|
|
121
|
+
for i in range(num_bits):
|
|
122
|
+
bits.append((v >> i) & 1)
|
|
123
|
+
return bits
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def bits_to_int(bits: List[int], order: int) -> int:
|
|
127
|
+
"""
|
|
128
|
+
Reconstruct an integer from its bit representation, reduced mod order.
|
|
129
|
+
|
|
130
|
+
This is the inverse of bit_decompose. The result is always reduced
|
|
131
|
+
modulo the group order to ensure values stay in the valid field range.
|
|
132
|
+
|
|
133
|
+
Parameters
|
|
134
|
+
----------
|
|
135
|
+
bits : list of int
|
|
136
|
+
List of bits (0 or 1), LSB first
|
|
137
|
+
order : int
|
|
138
|
+
The group order
|
|
139
|
+
|
|
140
|
+
Returns
|
|
141
|
+
-------
|
|
142
|
+
int
|
|
143
|
+
The reconstructed integer, reduced mod order
|
|
144
|
+
|
|
145
|
+
Examples
|
|
146
|
+
--------
|
|
147
|
+
>>> bits_to_int([1, 0, 1, 0], 2**256)
|
|
148
|
+
5
|
|
149
|
+
>>> bits_to_int([0, 0, 0, 0], 2**256)
|
|
150
|
+
0
|
|
151
|
+
"""
|
|
152
|
+
result = 0
|
|
153
|
+
for i, bit in enumerate(bits):
|
|
154
|
+
if bit:
|
|
155
|
+
result += (1 << i)
|
|
156
|
+
return result % order
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class PedersenCommitment:
|
|
160
|
+
"""
|
|
161
|
+
Pedersen Commitment Scheme for Elliptic Curve Groups.
|
|
162
|
+
|
|
163
|
+
Implements the information-theoretically hiding commitment scheme:
|
|
164
|
+
C = g^value * h^randomness
|
|
165
|
+
|
|
166
|
+
where g and h are generators with unknown discrete log relationship.
|
|
167
|
+
|
|
168
|
+
Properties:
|
|
169
|
+
- Computationally binding (under DLP assumption)
|
|
170
|
+
- Information-theoretically hiding
|
|
171
|
+
- Additively homomorphic
|
|
172
|
+
|
|
173
|
+
Parameters
|
|
174
|
+
----------
|
|
175
|
+
group : ECGroup
|
|
176
|
+
An elliptic curve group object
|
|
177
|
+
g : GElement, optional
|
|
178
|
+
First generator (random if not provided)
|
|
179
|
+
h : GElement, optional
|
|
180
|
+
Second generator (random if not provided)
|
|
181
|
+
|
|
182
|
+
Examples
|
|
183
|
+
--------
|
|
184
|
+
>>> from charm.toolbox.eccurve import secp256k1
|
|
185
|
+
>>> from charm.toolbox.ecgroup import ECGroup, ZR
|
|
186
|
+
>>> group = ECGroup(secp256k1)
|
|
187
|
+
>>> pc = PedersenCommitment(group)
|
|
188
|
+
>>> pc.setup()
|
|
189
|
+
>>> value = group.random(ZR)
|
|
190
|
+
>>> c, r = pc.commit(value)
|
|
191
|
+
>>> pc.open(c, value, r)
|
|
192
|
+
True
|
|
193
|
+
"""
|
|
194
|
+
|
|
195
|
+
def __init__(self, group: ECGroup, g: Optional[GElement] = None,
|
|
196
|
+
h: Optional[GElement] = None):
|
|
197
|
+
if group is None:
|
|
198
|
+
raise ValueError("group cannot be None")
|
|
199
|
+
self.group = group
|
|
200
|
+
self.order = int(group.order())
|
|
201
|
+
self._g = g
|
|
202
|
+
self._h = h
|
|
203
|
+
|
|
204
|
+
def setup(self) -> Tuple[GElement, GElement]:
|
|
205
|
+
"""Generate random generators if not already set."""
|
|
206
|
+
if self._g is None:
|
|
207
|
+
self._g = self.group.random(G)
|
|
208
|
+
if self._h is None:
|
|
209
|
+
self._h = self.group.random(G)
|
|
210
|
+
return self._g, self._h
|
|
211
|
+
|
|
212
|
+
@property
|
|
213
|
+
def g(self) -> GElement:
|
|
214
|
+
"""First generator."""
|
|
215
|
+
if self._g is None:
|
|
216
|
+
raise RuntimeError("Call setup() first")
|
|
217
|
+
return self._g
|
|
218
|
+
|
|
219
|
+
@property
|
|
220
|
+
def h(self) -> GElement:
|
|
221
|
+
"""Second generator."""
|
|
222
|
+
if self._h is None:
|
|
223
|
+
raise RuntimeError("Call setup() first")
|
|
224
|
+
return self._h
|
|
225
|
+
|
|
226
|
+
def commit(self, value: Any, randomness: Optional[ZRElement] = None
|
|
227
|
+
) -> Tuple[GElement, ZRElement]:
|
|
228
|
+
"""
|
|
229
|
+
Create Pedersen commitment: C = g^value * h^randomness.
|
|
230
|
+
|
|
231
|
+
Parameters
|
|
232
|
+
----------
|
|
233
|
+
value : ZRElement or int
|
|
234
|
+
Value to commit to
|
|
235
|
+
randomness : ZRElement, optional
|
|
236
|
+
Randomness for commitment (generated if not provided)
|
|
237
|
+
|
|
238
|
+
Returns
|
|
239
|
+
-------
|
|
240
|
+
tuple
|
|
241
|
+
(commitment, randomness)
|
|
242
|
+
"""
|
|
243
|
+
if randomness is None:
|
|
244
|
+
randomness = self.group.random(ZR)
|
|
245
|
+
|
|
246
|
+
if isinstance(value, int):
|
|
247
|
+
value = self.group.init(ZR, value % self.order)
|
|
248
|
+
|
|
249
|
+
commitment = (self.g ** value) * (self.h ** randomness)
|
|
250
|
+
return commitment, randomness
|
|
251
|
+
|
|
252
|
+
def open(self, commitment: GElement, value: Any,
|
|
253
|
+
randomness: ZRElement) -> bool:
|
|
254
|
+
"""
|
|
255
|
+
Verify that a commitment opens to the given value.
|
|
256
|
+
|
|
257
|
+
Parameters
|
|
258
|
+
----------
|
|
259
|
+
commitment : GElement
|
|
260
|
+
The commitment to verify
|
|
261
|
+
value : ZRElement or int
|
|
262
|
+
The claimed value
|
|
263
|
+
randomness : ZRElement
|
|
264
|
+
The randomness used in commitment
|
|
265
|
+
|
|
266
|
+
Returns
|
|
267
|
+
-------
|
|
268
|
+
bool
|
|
269
|
+
True if commitment opens correctly
|
|
270
|
+
"""
|
|
271
|
+
if isinstance(value, int):
|
|
272
|
+
value = self.group.init(ZR, value % self.order)
|
|
273
|
+
|
|
274
|
+
expected = (self.g ** value) * (self.h ** randomness)
|
|
275
|
+
return commitment == expected
|
|
276
|
+
|
|
277
|
+
def add(self, c1: GElement, c2: GElement) -> GElement:
|
|
278
|
+
"""
|
|
279
|
+
Homomorphically add two commitments.
|
|
280
|
+
|
|
281
|
+
If c1 = Commit(v1, r1) and c2 = Commit(v2, r2),
|
|
282
|
+
then c1 * c2 = Commit(v1 + v2, r1 + r2).
|
|
283
|
+
|
|
284
|
+
Parameters
|
|
285
|
+
----------
|
|
286
|
+
c1 : GElement
|
|
287
|
+
First commitment
|
|
288
|
+
c2 : GElement
|
|
289
|
+
Second commitment
|
|
290
|
+
|
|
291
|
+
Returns
|
|
292
|
+
-------
|
|
293
|
+
GElement
|
|
294
|
+
Combined commitment
|
|
295
|
+
"""
|
|
296
|
+
return c1 * c2
|
charm/toolbox/msp.py
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This class is adapted from the SecretUtil class in charm/toolbox/secretutil.py.
|
|
3
|
+
It provides the following methods:
|
|
4
|
+
- createPolicy: convert a Boolean formula encoded as a string into a policy represented like a tree;
|
|
5
|
+
- convertPolicyToMSP: convert a policy into a monotone span program (MSP);
|
|
6
|
+
- getCoefficients: given a policy, returns a coefficient for every attribute;
|
|
7
|
+
- strip_index: remove the index from an attribute (i.e., x_y -> x);
|
|
8
|
+
- prune: determine whether a given set of attributes satisfies the policy
|
|
9
|
+
(returns false if it doesn't, otherwise a good enough subset of attributes);
|
|
10
|
+
- getAttributeList: retrieve the attributes that occur in a policy tree in order (left to right).
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from charm.core.math.pairing import ZR
|
|
14
|
+
from charm.toolbox.policytree import *
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class MSP:
|
|
18
|
+
|
|
19
|
+
def __init__(self, groupObj, verbose=True):
|
|
20
|
+
self.len_longest_row = 1
|
|
21
|
+
self.group = groupObj
|
|
22
|
+
|
|
23
|
+
def createPolicy(self, policy_string):
|
|
24
|
+
"""
|
|
25
|
+
Convert a Boolean formula represented as a string into a policy represented like a tree.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
assert type(policy_string) in [bytes, str], "invalid type for policy_string"
|
|
29
|
+
if type(policy_string) == bytes:
|
|
30
|
+
policy_string = policy_string.decode('utf-8')
|
|
31
|
+
parser = PolicyParser()
|
|
32
|
+
policy_obj = parser.parse(policy_string)
|
|
33
|
+
_dictCount, _dictLabel = {}, {}
|
|
34
|
+
parser.findDuplicates(policy_obj, _dictCount)
|
|
35
|
+
for i in _dictCount.keys():
|
|
36
|
+
if _dictCount[i] > 1: _dictLabel[i] = 0
|
|
37
|
+
parser.labelDuplicates(policy_obj, _dictLabel)
|
|
38
|
+
return policy_obj
|
|
39
|
+
|
|
40
|
+
def convert_policy_to_msp(self, tree):
|
|
41
|
+
"""
|
|
42
|
+
Convert a policy into a monotone span program (MSP)
|
|
43
|
+
represented by a dictionary with (attribute, row) pairs
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
root_vector = [1]
|
|
47
|
+
# listOfAttributeRowPairs = {}
|
|
48
|
+
self.len_longest_row = 1
|
|
49
|
+
return self._convert_policy_to_msp(tree, root_vector)
|
|
50
|
+
|
|
51
|
+
def _convert_policy_to_msp(self, subtree, curr_vector):
|
|
52
|
+
"""
|
|
53
|
+
Given a vector for the current node,
|
|
54
|
+
returns the vectors for its children in the form of a dictionary
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
if subtree is None:
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
type = subtree.getNodeType()
|
|
61
|
+
|
|
62
|
+
if type == OpType.ATTR:
|
|
63
|
+
# print ('ATTR: ', subtree, subtree.getAttributeAndIndex(), currVector)
|
|
64
|
+
return {subtree.getAttributeAndIndex(): curr_vector}
|
|
65
|
+
|
|
66
|
+
if type == OpType.OR:
|
|
67
|
+
left_list = self._convert_policy_to_msp(subtree.getLeft(), curr_vector)
|
|
68
|
+
right_list = self._convert_policy_to_msp(subtree.getRight(), curr_vector)
|
|
69
|
+
# print ('OR l: ', leftList, 'r: ', rightList)
|
|
70
|
+
left_list.update(right_list)
|
|
71
|
+
return left_list
|
|
72
|
+
|
|
73
|
+
if type == OpType.AND:
|
|
74
|
+
length = len(curr_vector)
|
|
75
|
+
left_vector = curr_vector + [0] * (self.len_longest_row - length) + [1]
|
|
76
|
+
right_vector = [0] * self.len_longest_row + [-1] # [0]*k creates a vector of k zeroes
|
|
77
|
+
# extendedVector = currVector + [0]*(self.lengthOfLongestRow-length)
|
|
78
|
+
# leftVector = extendedVector + [1]
|
|
79
|
+
# rightVector = extendedVector + [2] # [0]*k creates a vector of k zeroes
|
|
80
|
+
self.len_longest_row += 1
|
|
81
|
+
left_list = self._convert_policy_to_msp(subtree.getLeft(), left_vector)
|
|
82
|
+
right_list = self._convert_policy_to_msp(subtree.getRight(), right_vector)
|
|
83
|
+
# print ('AND l: ', leftList, 'r: ', rightList)
|
|
84
|
+
left_list.update(right_list)
|
|
85
|
+
return left_list
|
|
86
|
+
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
def getCoefficients(self, tree):
|
|
90
|
+
"""
|
|
91
|
+
Given a policy, returns a coefficient for every attribute.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
coeffs = {}
|
|
95
|
+
self._getCoefficientsDict(tree, coeffs)
|
|
96
|
+
return coeffs
|
|
97
|
+
|
|
98
|
+
def recoverCoefficients(self, list):
|
|
99
|
+
"""
|
|
100
|
+
recovers the coefficients over a binary tree.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
coeff = {}
|
|
104
|
+
list2 = [self.group.init(ZR, i) for i in list]
|
|
105
|
+
for i in list2:
|
|
106
|
+
result = 1
|
|
107
|
+
for j in list2:
|
|
108
|
+
if not (i == j):
|
|
109
|
+
# lagrange basis poly
|
|
110
|
+
result *= (0 - j) / (i - j)
|
|
111
|
+
# print("coeff '%d' => '%s'" % (i, result))
|
|
112
|
+
coeff[int(i)] = result
|
|
113
|
+
return coeff
|
|
114
|
+
|
|
115
|
+
def _getCoefficientsDict(self, tree, coeff_list, coeff=1):
|
|
116
|
+
"""
|
|
117
|
+
recover coefficient over a binary tree where possible node types are OR = (1 of 2)
|
|
118
|
+
and AND = (2 of 2) secret sharing. The leaf nodes are attributes and the coefficients are
|
|
119
|
+
recorded in a coeff-list dictionary.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
if tree:
|
|
123
|
+
node = tree.getNodeType()
|
|
124
|
+
if (node == OpType.AND):
|
|
125
|
+
this_coeff = self.recoverCoefficients([1, 2])
|
|
126
|
+
# left child => coeff[1], right child => coeff[2]
|
|
127
|
+
self._getCoefficientsDict(tree.getLeft(), coeff_list, coeff * this_coeff[1])
|
|
128
|
+
self._getCoefficientsDict(tree.getRight(), coeff_list, coeff * this_coeff[2])
|
|
129
|
+
elif (node == OpType.OR):
|
|
130
|
+
this_coeff = self.recoverCoefficients([1])
|
|
131
|
+
self._getCoefficientsDict(tree.getLeft(), coeff_list, coeff * this_coeff[1])
|
|
132
|
+
self._getCoefficientsDict(tree.getRight(), coeff_list, coeff * this_coeff[1])
|
|
133
|
+
elif (node == OpType.ATTR):
|
|
134
|
+
attr = tree.getAttributeAndIndex()
|
|
135
|
+
coeff_list[attr] = coeff
|
|
136
|
+
else:
|
|
137
|
+
return None
|
|
138
|
+
|
|
139
|
+
def strip_index(self, node_str):
|
|
140
|
+
"""
|
|
141
|
+
Remove the index from an attribute (i.e., x_y -> x).
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
if node_str.find('_') != -1:
|
|
145
|
+
return node_str.split('_')[0]
|
|
146
|
+
return node_str
|
|
147
|
+
|
|
148
|
+
def prune(self, policy, attributes):
|
|
149
|
+
"""
|
|
150
|
+
Determine whether a given set of attributes satisfies the policy
|
|
151
|
+
(returns false if it doesn't, otherwise a good enough subset of attributes).
|
|
152
|
+
"""
|
|
153
|
+
|
|
154
|
+
parser = PolicyParser()
|
|
155
|
+
return parser.prune(policy, attributes)
|
|
156
|
+
|
|
157
|
+
def getAttributeList(self, Node):
|
|
158
|
+
"""
|
|
159
|
+
Retrieve the attributes that occur in a policy tree in order (left to right).
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
aList = []
|
|
163
|
+
self._getAttributeList(Node, aList)
|
|
164
|
+
return aList
|
|
165
|
+
|
|
166
|
+
def _getAttributeList(self, Node, List):
|
|
167
|
+
if (Node == None):
|
|
168
|
+
return None
|
|
169
|
+
# V, L, R
|
|
170
|
+
if (Node.getNodeType() == OpType.ATTR):
|
|
171
|
+
List.append(Node.getAttributeAndIndex()) # .getAttribute()
|
|
172
|
+
else:
|
|
173
|
+
self._getAttributeList(Node.getLeft(), List)
|
|
174
|
+
self._getAttributeList(Node.getRight(), List)
|
|
175
|
+
return None
|