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,228 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Multi-Point Function Secret Sharing (MPFSS)
|
|
3
|
+
|
|
4
|
+
| From: "Efficient Pseudorandom Correlation Generators: Silent OT Extension and More"
|
|
5
|
+
| By: Elette Boyle, Geoffroy Couteau, Niv Gilboa, Yuval Ishai, Lisa Kohl, Peter Scholl
|
|
6
|
+
| Published: CRYPTO 2019
|
|
7
|
+
| URL: https://eprint.iacr.org/2019/448
|
|
8
|
+
|
|
9
|
+
* type: function secret sharing
|
|
10
|
+
* setting: symmetric key
|
|
11
|
+
* assumption: PRG security
|
|
12
|
+
|
|
13
|
+
:Authors: Elton de Souza
|
|
14
|
+
:Date: 01/2026
|
|
15
|
+
'''
|
|
16
|
+
|
|
17
|
+
from typing import List, Tuple
|
|
18
|
+
from charm.toolbox.ot.dpf import DPF
|
|
19
|
+
|
|
20
|
+
KEY_VERSION = 1
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class MPFSS:
|
|
24
|
+
"""
|
|
25
|
+
Multi-Point Function Secret Sharing (MPFSS).
|
|
26
|
+
|
|
27
|
+
Extends DPF to support multiple points. Shares a function f_{S,y} where S
|
|
28
|
+
is a set of points and y is a vector of values. For each point α_i in S,
|
|
29
|
+
f_{S,y}(α_i) = y_i, and f_{S,y}(x) = 0 for x not in S.
|
|
30
|
+
|
|
31
|
+
This implementation uses the simple approach from the paper: run independent
|
|
32
|
+
DPF for each point. Key size is O(t * λ * log n) where t is number of points,
|
|
33
|
+
λ is security parameter, and n is domain size.
|
|
34
|
+
|
|
35
|
+
The MPFSS key is constructed by composing DPF instances:
|
|
36
|
+
K_{fss,σ} = (K^1_{dpf,σ}, K^2_{dpf,σ}, ..., K^t_{dpf,σ})
|
|
37
|
+
|
|
38
|
+
The full_eval runs each DPF's full_eval and sums the outputs.
|
|
39
|
+
|
|
40
|
+
Example
|
|
41
|
+
-------
|
|
42
|
+
>>> mpfss = MPFSS(security_param=128, domain_bits=10)
|
|
43
|
+
>>> # Share function with points: f(5) = 100, f(20) = 200
|
|
44
|
+
>>> points = [(5, 100), (20, 200)]
|
|
45
|
+
>>> key0, key1 = mpfss.gen(points)
|
|
46
|
+
>>> # Evaluate at specific point
|
|
47
|
+
>>> v0 = mpfss.eval(0, key0, 5)
|
|
48
|
+
>>> v1 = mpfss.eval(1, key1, 5)
|
|
49
|
+
>>> (v0 + v1) % (2**64) == 100
|
|
50
|
+
True
|
|
51
|
+
>>> # Full domain evaluation sums each DPF
|
|
52
|
+
>>> full0 = mpfss.full_eval(0, key0)
|
|
53
|
+
>>> full1 = mpfss.full_eval(1, key1)
|
|
54
|
+
>>> domain_size = 2**10
|
|
55
|
+
>>> [(full0[i] + full1[i]) % (2**64) for i in [5, 20]] == [100, 200]
|
|
56
|
+
True
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
def __init__(self, security_param: int = 128, domain_bits: int = 20):
|
|
60
|
+
"""
|
|
61
|
+
Initialize MPFSS with security and domain parameters.
|
|
62
|
+
|
|
63
|
+
Parameters
|
|
64
|
+
----------
|
|
65
|
+
security_param : int
|
|
66
|
+
Security parameter in bits (default: 128)
|
|
67
|
+
domain_bits : int
|
|
68
|
+
Number of bits for domain size N = 2^domain_bits (default: 20)
|
|
69
|
+
"""
|
|
70
|
+
self.security_param = security_param
|
|
71
|
+
self.domain_bits = domain_bits
|
|
72
|
+
self.domain_size = 1 << domain_bits
|
|
73
|
+
self._dpf = DPF(security_param=security_param, domain_bits=domain_bits)
|
|
74
|
+
self._modulus = 1 << 64 # 2^64 for 64-bit arithmetic
|
|
75
|
+
|
|
76
|
+
def gen(self, points: List[Tuple[int, int]]) -> Tuple[bytes, bytes]:
|
|
77
|
+
"""
|
|
78
|
+
Generate MPFSS keys for a set of points.
|
|
79
|
+
|
|
80
|
+
Generates keys that share a function f where f(α_i) = y_i for each
|
|
81
|
+
(α_i, y_i) in points, and f(x) = 0 elsewhere.
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
points : List[Tuple[int, int]]
|
|
86
|
+
List of (α, y) pairs where α is the point and y is the value
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
-------
|
|
90
|
+
Tuple[bytes, bytes]
|
|
91
|
+
(key0, key1) - MPFSS keys for party 0 and party 1
|
|
92
|
+
|
|
93
|
+
Raises
|
|
94
|
+
------
|
|
95
|
+
ValueError
|
|
96
|
+
If any point α is outside the domain [0, 2^domain_bits)
|
|
97
|
+
"""
|
|
98
|
+
if not points:
|
|
99
|
+
# Empty function - return empty keys with proper version header
|
|
100
|
+
empty_key = self._serialize_keys([])
|
|
101
|
+
return empty_key, empty_key
|
|
102
|
+
|
|
103
|
+
# Check for duplicate alpha values
|
|
104
|
+
alphas = [alpha for alpha, _ in points]
|
|
105
|
+
seen = set()
|
|
106
|
+
duplicates = set()
|
|
107
|
+
for alpha in alphas:
|
|
108
|
+
if alpha in seen:
|
|
109
|
+
duplicates.add(alpha)
|
|
110
|
+
seen.add(alpha)
|
|
111
|
+
if duplicates:
|
|
112
|
+
raise ValueError(
|
|
113
|
+
f"Duplicate alpha values are not allowed: {sorted(duplicates)}"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Validate points are within domain
|
|
117
|
+
for alpha, _ in points:
|
|
118
|
+
if alpha < 0 or alpha >= self.domain_size:
|
|
119
|
+
raise ValueError(
|
|
120
|
+
f"Point {alpha} is outside domain [0, {self.domain_size})"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Generate independent DPF for each point
|
|
124
|
+
dpf_keys_0 = []
|
|
125
|
+
dpf_keys_1 = []
|
|
126
|
+
|
|
127
|
+
for alpha, y in points:
|
|
128
|
+
k0, k1 = self._dpf.gen(alpha, y)
|
|
129
|
+
dpf_keys_0.append(k0)
|
|
130
|
+
dpf_keys_1.append(k1)
|
|
131
|
+
|
|
132
|
+
# Serialize: count + list of (length, key) pairs
|
|
133
|
+
key0 = self._serialize_keys(dpf_keys_0)
|
|
134
|
+
key1 = self._serialize_keys(dpf_keys_1)
|
|
135
|
+
|
|
136
|
+
return key0, key1
|
|
137
|
+
|
|
138
|
+
def _serialize_keys(self, keys: List[bytes]) -> bytes:
|
|
139
|
+
"""Serialize a list of DPF keys into a single bytes object."""
|
|
140
|
+
# Format: 2 bytes version, 4 bytes count, then for each key: 4 bytes length + key data
|
|
141
|
+
result = KEY_VERSION.to_bytes(2, 'big')
|
|
142
|
+
result += len(keys).to_bytes(4, 'big')
|
|
143
|
+
for key in keys:
|
|
144
|
+
result += len(key).to_bytes(4, 'big')
|
|
145
|
+
result += key
|
|
146
|
+
return result
|
|
147
|
+
|
|
148
|
+
def _deserialize_keys(self, data: bytes) -> List[bytes]:
|
|
149
|
+
"""Deserialize a bytes object into a list of DPF keys."""
|
|
150
|
+
# Read and validate version (2 bytes)
|
|
151
|
+
version = int.from_bytes(data[:2], 'big')
|
|
152
|
+
if version != KEY_VERSION:
|
|
153
|
+
raise ValueError(
|
|
154
|
+
f"Unsupported key version {version}, expected {KEY_VERSION}"
|
|
155
|
+
)
|
|
156
|
+
count = int.from_bytes(data[2:6], 'big')
|
|
157
|
+
keys = []
|
|
158
|
+
offset = 6
|
|
159
|
+
for _ in range(count):
|
|
160
|
+
length = int.from_bytes(data[offset:offset + 4], 'big')
|
|
161
|
+
offset += 4
|
|
162
|
+
keys.append(data[offset:offset + length])
|
|
163
|
+
offset += length
|
|
164
|
+
return keys
|
|
165
|
+
|
|
166
|
+
def eval(self, sigma: int, key: bytes, x: int) -> int:
|
|
167
|
+
"""
|
|
168
|
+
Evaluate MPFSS at a single point.
|
|
169
|
+
|
|
170
|
+
Parameters
|
|
171
|
+
----------
|
|
172
|
+
sigma : int
|
|
173
|
+
Party index (0 or 1)
|
|
174
|
+
key : bytes
|
|
175
|
+
MPFSS key for this party
|
|
176
|
+
x : int
|
|
177
|
+
Point at which to evaluate
|
|
178
|
+
|
|
179
|
+
Returns
|
|
180
|
+
-------
|
|
181
|
+
int
|
|
182
|
+
The share of f(x) for this party
|
|
183
|
+
"""
|
|
184
|
+
dpf_keys = self._deserialize_keys(key)
|
|
185
|
+
|
|
186
|
+
# Sum evaluations from all DPF instances
|
|
187
|
+
total = 0
|
|
188
|
+
for dpf_key in dpf_keys:
|
|
189
|
+
total += self._dpf.eval(sigma, dpf_key, x)
|
|
190
|
+
|
|
191
|
+
return total % self._modulus
|
|
192
|
+
|
|
193
|
+
def full_eval(self, sigma: int, key: bytes) -> List[int]:
|
|
194
|
+
"""
|
|
195
|
+
Evaluate MPFSS on the entire domain.
|
|
196
|
+
|
|
197
|
+
Runs each DPF's full_eval and sums the outputs element-wise.
|
|
198
|
+
|
|
199
|
+
Parameters
|
|
200
|
+
----------
|
|
201
|
+
sigma : int
|
|
202
|
+
Party index (0 or 1)
|
|
203
|
+
key : bytes
|
|
204
|
+
MPFSS key for this party
|
|
205
|
+
|
|
206
|
+
Returns
|
|
207
|
+
-------
|
|
208
|
+
List[int]
|
|
209
|
+
List of shares for all points in domain [0, 2^domain_bits)
|
|
210
|
+
"""
|
|
211
|
+
dpf_keys = self._deserialize_keys(key)
|
|
212
|
+
|
|
213
|
+
if not dpf_keys:
|
|
214
|
+
# Empty function - return all zeros
|
|
215
|
+
return [0] * self.domain_size
|
|
216
|
+
|
|
217
|
+
# Initialize result with first DPF's full evaluation
|
|
218
|
+
result = self._dpf.full_eval(sigma, dpf_keys[0])
|
|
219
|
+
|
|
220
|
+
# Sum remaining DPF evaluations
|
|
221
|
+
for i in range(1, len(dpf_keys)):
|
|
222
|
+
dpf_eval = self._dpf.full_eval(sigma, dpf_keys[i])
|
|
223
|
+
for j in range(self.domain_size):
|
|
224
|
+
result[j] += dpf_eval[j]
|
|
225
|
+
|
|
226
|
+
# Apply modular reduction to ensure 64-bit arithmetic
|
|
227
|
+
return [x % self._modulus for x in result]
|
|
228
|
+
|