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,15 @@
|
|
|
1
|
+
#ifndef __BASE64_H__
|
|
2
|
+
#define __BASE64_H__
|
|
3
|
+
|
|
4
|
+
#include <stdio.h>
|
|
5
|
+
#include <string.h>
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
|
|
8
|
+
#define TRUE 1
|
|
9
|
+
#define FALSE 0
|
|
10
|
+
|
|
11
|
+
void *NewBase64Decode(const char *inputBuffer, size_t length, size_t *outputLength);
|
|
12
|
+
|
|
13
|
+
char *NewBase64Encode(const void *inputBuffer, size_t length, int separateLines, size_t *outputLength);
|
|
14
|
+
|
|
15
|
+
#endif
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,647 @@
|
|
|
1
|
+
'''
|
|
2
|
+
**ABE with Privacy Protection and Accountability (JYJXGD20)**
|
|
3
|
+
|
|
4
|
+
*Authors:* Jiguo Li, Yichen Zhang, Jianting Ning, Xinyi Huang, Geong Sen Poh, Debang Wang
|
|
5
|
+
|
|
6
|
+
| **Title:** "Attribute Based Encryption with Privacy Protection and Accountability for CloudIoT"
|
|
7
|
+
| **Published in:** IEEE Transactions on Cloud Computing, 2020
|
|
8
|
+
| **Available from:** https://ieeexplore.ieee.org/abstract/document/9003205
|
|
9
|
+
| **Notes:** Two schemes implemented: (1) CP policy hiding (class CP_Hiding_ABE), (2) CP policy hiding with accountability under white box assumption (class CP_Hiding_Accountability_ABE)
|
|
10
|
+
|
|
11
|
+
.. rubric:: Scheme Properties
|
|
12
|
+
|
|
13
|
+
* **Type:** ciphertext-policy attribute-based encryption (public key)
|
|
14
|
+
* **Setting:** Pairing groups
|
|
15
|
+
* **Assumption:** Decisional Bilinear Diffie-Hellman
|
|
16
|
+
|
|
17
|
+
.. rubric:: Implementation
|
|
18
|
+
|
|
19
|
+
:Authors: Ahmed Bakr
|
|
20
|
+
:Date: 08/2023
|
|
21
|
+
'''
|
|
22
|
+
|
|
23
|
+
from charm.toolbox.pairinggroup import PairingGroup,ZR,G1,G2,GT,pair
|
|
24
|
+
from charm.toolbox.ABEnc import ABEnc
|
|
25
|
+
|
|
26
|
+
from typing import Dict, List
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Attribute:
|
|
30
|
+
def __init__(self, attr_name, values_list: List[str] = []):
|
|
31
|
+
# Validation
|
|
32
|
+
self.__validate_attribute_values_name(attr_name)
|
|
33
|
+
for value_str in values_list:
|
|
34
|
+
self.__validate_attribute_values_name(value_str)
|
|
35
|
+
|
|
36
|
+
self.name = attr_name
|
|
37
|
+
self.values = values_list
|
|
38
|
+
|
|
39
|
+
@staticmethod
|
|
40
|
+
def __validate_attribute_values_name(attr_value_name: str):
|
|
41
|
+
assert attr_value_name.find('_') == -1, "Attribute name cannot contain an '_'"
|
|
42
|
+
|
|
43
|
+
def add_value(self, value: str):
|
|
44
|
+
self.__validate_attribute_values_name(value) # Validation
|
|
45
|
+
self.values.append(value)
|
|
46
|
+
|
|
47
|
+
def set_values(self, values_list: List[str]):
|
|
48
|
+
self.values = values_list
|
|
49
|
+
|
|
50
|
+
def get_attribute_values_full_name(self):
|
|
51
|
+
"""
|
|
52
|
+
Attribute values full name is in the following format: 'attrName_value'
|
|
53
|
+
"""
|
|
54
|
+
full_names_list = []
|
|
55
|
+
for value in self.values:
|
|
56
|
+
full_names_list.append(self.name + "_" + value)
|
|
57
|
+
|
|
58
|
+
return full_names_list
|
|
59
|
+
|
|
60
|
+
@staticmethod
|
|
61
|
+
def get_full_attribute_value_name(attr_name: str, value_name: str):
|
|
62
|
+
Attribute.__validate_attribute_values_name(attr_name) # Validation
|
|
63
|
+
Attribute.__validate_attribute_values_name(value_name) # Validation
|
|
64
|
+
return attr_name + '_' + value_name
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class CP_Hiding_ABE(ABEnc):
|
|
68
|
+
"""
|
|
69
|
+
Cipher text policy hiding attribute based encryption (Section 3 in the paper).
|
|
70
|
+
"""
|
|
71
|
+
def __init__(self, group_obj):
|
|
72
|
+
ABEnc.__init__(self)
|
|
73
|
+
self._group = group_obj
|
|
74
|
+
self.attributes_dict: Dict[str, List[str]] = None
|
|
75
|
+
|
|
76
|
+
def setup(self, attributes_dict: Dict[str, List[str]]):
|
|
77
|
+
"""
|
|
78
|
+
System Setup algorithm. This algorithm is performed by TA.
|
|
79
|
+
Inputs:
|
|
80
|
+
- None
|
|
81
|
+
Outputs:
|
|
82
|
+
- MSK: TA's master secret key.
|
|
83
|
+
- PK: Public Parameters.
|
|
84
|
+
"""
|
|
85
|
+
self.attributes_dict = attributes_dict
|
|
86
|
+
g = self._group.random(G1)
|
|
87
|
+
u = self._group.random(G1)
|
|
88
|
+
v = self._group.random(G1)
|
|
89
|
+
h = self._group.random(G1)
|
|
90
|
+
w = self._group.random(G1)
|
|
91
|
+
|
|
92
|
+
alpha = self._group.random(ZR)
|
|
93
|
+
|
|
94
|
+
MSK = alpha
|
|
95
|
+
PK = {'g': g,
|
|
96
|
+
'e_gg': pair(g, g),
|
|
97
|
+
'u': u,
|
|
98
|
+
'h': h,
|
|
99
|
+
'w': w,
|
|
100
|
+
'v': v,
|
|
101
|
+
'e_gg_alpha': pair(g, g) ** alpha}
|
|
102
|
+
return MSK, PK
|
|
103
|
+
|
|
104
|
+
def key_gen(self, MSK, PK, attributes_list):
|
|
105
|
+
"""
|
|
106
|
+
Key generation for a user based on his list of attributes. This algorithm is performed by TA.
|
|
107
|
+
Inputs:
|
|
108
|
+
- MSK: Master Secret Key of the TA.
|
|
109
|
+
- PK: Public parameters and the public key of the TA.
|
|
110
|
+
- attributes_list: List of attributes held by this user, where each attribute is in the format:
|
|
111
|
+
'attrName_value'
|
|
112
|
+
Outputs:
|
|
113
|
+
- SK: User's secret key.
|
|
114
|
+
"""
|
|
115
|
+
self._validate_attributes_list(attributes_list)
|
|
116
|
+
r = self._group.random(ZR)
|
|
117
|
+
g = PK['g']
|
|
118
|
+
w = PK['w']
|
|
119
|
+
u = PK['u']
|
|
120
|
+
h = PK['h']
|
|
121
|
+
v = PK['v']
|
|
122
|
+
alpha = MSK
|
|
123
|
+
|
|
124
|
+
K_0 = (g ** alpha) * (w ** r)
|
|
125
|
+
K_1 = g ** r
|
|
126
|
+
K_2 = {}
|
|
127
|
+
K_3 = {}
|
|
128
|
+
for full_attr_value_name in attributes_list:
|
|
129
|
+
# attr_name = full_attr_value_name.split('_')[0]
|
|
130
|
+
r_i = self._group.random(ZR)
|
|
131
|
+
K_i_2 = g ** r_i
|
|
132
|
+
hash_attr_val_in_z_p = self._group.hash(full_attr_value_name, type=ZR)
|
|
133
|
+
K_i_3 = (((u ** hash_attr_val_in_z_p) * h) ** r_i) * v ** (-r)
|
|
134
|
+
K_2[full_attr_value_name] = K_i_2
|
|
135
|
+
K_3[full_attr_value_name] = K_i_3
|
|
136
|
+
SK = {'attributes_list': attributes_list, 'K_0': K_0, 'K_1': K_1, 'K_2': K_2, 'K_3': K_3}
|
|
137
|
+
return SK
|
|
138
|
+
|
|
139
|
+
def _validate_attributes_list(self, attributes_list):
|
|
140
|
+
"""
|
|
141
|
+
each attribute is in the format: 'attrName_value'
|
|
142
|
+
"""
|
|
143
|
+
for attr_value in attributes_list:
|
|
144
|
+
assert attr_value.find('_') == attr_value.rfind('_') and attr_value.find('_') != -1, (
|
|
145
|
+
"The format is 'attrName_value'")
|
|
146
|
+
splitted_str = attr_value.split('_')
|
|
147
|
+
assert len(splitted_str[0]) > 0 and len(splitted_str[1])> 0, "The format is 'attrName_value'"
|
|
148
|
+
|
|
149
|
+
def encrypt(self, m, PK, access_policy: Dict[str, List[str]]):
|
|
150
|
+
"""
|
|
151
|
+
Encrypt a message using an access policy. This function is performed by a data user who wants to encrypt his
|
|
152
|
+
message with an access policy. They consider only and-gates in their policy.
|
|
153
|
+
Note: The access policy is hidden into the ciphertext.
|
|
154
|
+
Inputs:
|
|
155
|
+
- PK: Public parameters and the public key of the TA.
|
|
156
|
+
- m: Message to be encrypted in G_T.
|
|
157
|
+
- access_policy: Access policy that will be used to encrypt the message. It has to be and gated policy,
|
|
158
|
+
which means that each attribute can have only one value.
|
|
159
|
+
Outputs:
|
|
160
|
+
- CT: Cipher text.
|
|
161
|
+
"""
|
|
162
|
+
g = PK['g']
|
|
163
|
+
w = PK['w']
|
|
164
|
+
v = PK['v']
|
|
165
|
+
u = PK['u']
|
|
166
|
+
h = PK['h']
|
|
167
|
+
s = self._group.random(ZR)
|
|
168
|
+
s_n = s
|
|
169
|
+
access_policy_len = len(access_policy)
|
|
170
|
+
C = m * PK['e_gg_alpha'] ** s
|
|
171
|
+
C_1 = g ** s
|
|
172
|
+
C_i_1 = {}
|
|
173
|
+
C_i_3 = {}
|
|
174
|
+
C_i_2 = {}
|
|
175
|
+
for idx, attr_name in enumerate(access_policy):
|
|
176
|
+
if idx < access_policy_len - 1:
|
|
177
|
+
s_i = self._group.random(ZR)
|
|
178
|
+
s_n = s_n - s_i
|
|
179
|
+
else:
|
|
180
|
+
s_i = s_n
|
|
181
|
+
t_i = self._group.random(ZR)
|
|
182
|
+
C_i_1[attr_name] = (w ** s_i) * (v ** t_i)
|
|
183
|
+
C_i_3[attr_name] = g ** t_i
|
|
184
|
+
|
|
185
|
+
for attr_value in self.attributes_dict[attr_name]:
|
|
186
|
+
full_attr_value_name = Attribute.get_full_attribute_value_name(attr_name, attr_value)
|
|
187
|
+
if attr_value in access_policy[attr_name]:
|
|
188
|
+
hash_attr_val_in_z_p = self._group.hash(full_attr_value_name, type=ZR)
|
|
189
|
+
C_i_ai_2 = ((u ** hash_attr_val_in_z_p) * h) ** (-t_i)
|
|
190
|
+
else:
|
|
191
|
+
C_i_ai_2 = self._group.random(G1)
|
|
192
|
+
C_i_2[full_attr_value_name] = C_i_ai_2
|
|
193
|
+
CT = {'C': C,
|
|
194
|
+
'C_1': C_1,
|
|
195
|
+
'C_i_1': C_i_1,
|
|
196
|
+
'C_i_3': C_i_3,
|
|
197
|
+
'C_i_ai_2': C_i_2}
|
|
198
|
+
return CT
|
|
199
|
+
|
|
200
|
+
def decrypt(self, CT, PK, SK):
|
|
201
|
+
"""
|
|
202
|
+
Decrypt a cipher text. This algorithm is performed by a data user who has the required attributes to decipher
|
|
203
|
+
the ciphertext that was encrypted using an access policy.
|
|
204
|
+
Inputs:
|
|
205
|
+
- CT: Cipher text.
|
|
206
|
+
- PK: Public parameters and the public key of the TA.
|
|
207
|
+
- SK: User's secret key.
|
|
208
|
+
Outputs:
|
|
209
|
+
- m: The original decrypted message.
|
|
210
|
+
"""
|
|
211
|
+
nominator = pair(CT['C_1'], SK['K_0'])
|
|
212
|
+
denominator = self._group.init(GT, 1)
|
|
213
|
+
for attr_name in CT['C_i_1']:
|
|
214
|
+
# Find the attribute value that exists inside both the user's key for attr_name
|
|
215
|
+
found_attribute_value_full_name = None
|
|
216
|
+
for attr_value_full_name in SK['K_2']:
|
|
217
|
+
if attr_value_full_name.find(attr_name) == 0:
|
|
218
|
+
found_attribute_value_full_name = attr_value_full_name
|
|
219
|
+
if not found_attribute_value_full_name:
|
|
220
|
+
return False # The user does not have the necessary attributes to decrypt
|
|
221
|
+
|
|
222
|
+
denominator = (denominator * pair(CT['C_i_1'][attr_name], SK['K_1']) *
|
|
223
|
+
pair(CT['C_i_ai_2'][found_attribute_value_full_name],
|
|
224
|
+
SK['K_2'][found_attribute_value_full_name]) *
|
|
225
|
+
pair(CT['C_i_3'][attr_name], SK['K_3'][found_attribute_value_full_name]))
|
|
226
|
+
B = nominator / denominator
|
|
227
|
+
recovered_message = CT['C'] / B
|
|
228
|
+
return recovered_message
|
|
229
|
+
|
|
230
|
+
class CP_Hiding_Accountability_ABE(CP_Hiding_ABE):
|
|
231
|
+
"""
|
|
232
|
+
Cipher text policy hiding attribute based encryption (Section 4 in the paper).
|
|
233
|
+
"""
|
|
234
|
+
def __init__(self, group_obj):
|
|
235
|
+
CP_Hiding_ABE.__init__(self, group_obj)
|
|
236
|
+
self._user_ID_to_w_pow_k_dict = {} # Updated inside the key generation function to map the user ID to his
|
|
237
|
+
# associated R = w ** k.
|
|
238
|
+
|
|
239
|
+
def setup(self, attributes_dict: Dict[str, List[str]]):
|
|
240
|
+
"""
|
|
241
|
+
System Setup algorithm. This algorithm is performed by TA.
|
|
242
|
+
Inputs:
|
|
243
|
+
- None
|
|
244
|
+
Outputs:
|
|
245
|
+
- MSK: TA's master secret key.
|
|
246
|
+
- PK: Public Parameters.
|
|
247
|
+
"""
|
|
248
|
+
self.attributes_dict = attributes_dict
|
|
249
|
+
g = self._group.random(G1)
|
|
250
|
+
u = self._group.random(G1)
|
|
251
|
+
v = self._group.random(G1)
|
|
252
|
+
h = self._group.random(G1)
|
|
253
|
+
w = self._group.random(G1)
|
|
254
|
+
|
|
255
|
+
alpha = self._group.random(ZR)
|
|
256
|
+
x = self._group.random(ZR)
|
|
257
|
+
y = self._group.random(ZR)
|
|
258
|
+
|
|
259
|
+
X = g ** x
|
|
260
|
+
Y = g ** y
|
|
261
|
+
|
|
262
|
+
MSK = {
|
|
263
|
+
'alpha': alpha,
|
|
264
|
+
'x': x,
|
|
265
|
+
'y': y
|
|
266
|
+
}
|
|
267
|
+
PK = {'g': g,
|
|
268
|
+
'e_gg': pair(g, g),
|
|
269
|
+
'u': u,
|
|
270
|
+
'h': h,
|
|
271
|
+
'w': w,
|
|
272
|
+
'v': v,
|
|
273
|
+
'e_gg_alpha': pair(g, g) ** alpha,
|
|
274
|
+
'X': X,
|
|
275
|
+
'Y': Y
|
|
276
|
+
}
|
|
277
|
+
return MSK, PK
|
|
278
|
+
|
|
279
|
+
def key_gen(self, MSK, PK, ID, attributes_list):
|
|
280
|
+
"""
|
|
281
|
+
Key generation for a user based on his list of attributes. This algorithm is performed by TA and the user.
|
|
282
|
+
Part of the key generation is executed as an interaction between the user and the TA, as the user generates
|
|
283
|
+
a random number (k) that he does not share with the TA. However, he shares with it w**k, and proves knowledge of
|
|
284
|
+
(k) to TA using any ZKP algorithm.
|
|
285
|
+
Inputs:
|
|
286
|
+
- MSK: Master Secret Key of the TA.
|
|
287
|
+
- PK: Public parameters and the public key of the TA.
|
|
288
|
+
- ID: User's unique identifier.
|
|
289
|
+
- attributes_list: List of attributes held by this user, where each attribute is in the format:
|
|
290
|
+
'attrName_value'
|
|
291
|
+
Outputs:
|
|
292
|
+
- SK: User's secret key.
|
|
293
|
+
"""
|
|
294
|
+
w = PK['w']
|
|
295
|
+
|
|
296
|
+
# The part executed by the user
|
|
297
|
+
k = self._group.random(ZR) # Select a secret KFN (Key Family Number).
|
|
298
|
+
R = w ** k
|
|
299
|
+
|
|
300
|
+
# User is going to send R to the TA and prove knowledge of k using Shnorr's ZKP.
|
|
301
|
+
zkp_prover = ShnorrInteractiveZKP.Prover(k, self._group) # The user.
|
|
302
|
+
zkp_verifier = ShnorrInteractiveZKP.Verifier(self._group) # The TA.
|
|
303
|
+
pk = {'g': w} # Work around to user (w) as the group point instead of (g)
|
|
304
|
+
u = zkp_prover.create_prover_commitments(pk)
|
|
305
|
+
c = zkp_verifier.create_verifier_challenge()
|
|
306
|
+
z = zkp_prover.create_proof(c)
|
|
307
|
+
assert zkp_verifier.is_proof_verified(z, pk, u, R), \
|
|
308
|
+
"User failed to proof knowledge of (k) that is used to calculate R"
|
|
309
|
+
|
|
310
|
+
SK = self.key_gen_TA(MSK, PK, ID, R, attributes_list)
|
|
311
|
+
|
|
312
|
+
# The user gets the SK and adds his secret KFN to it.
|
|
313
|
+
SK['k'] = k
|
|
314
|
+
return SK
|
|
315
|
+
|
|
316
|
+
def key_gen_TA(self, MSK, PK, ID, R, attributes_list):
|
|
317
|
+
"""
|
|
318
|
+
Key generation for a user based on his list of attributes. This algorithm is performed by TA and the user.
|
|
319
|
+
Part of the key generation is executed as an interaction between the user and the TA, as the user generates
|
|
320
|
+
a random number (k) that he does not share with the TA. However, he shares with it w**k, and proves knowledge of
|
|
321
|
+
(k) to TA using any ZKP algorithm.
|
|
322
|
+
Inputs:
|
|
323
|
+
- MSK: Master Secret Key of the TA.
|
|
324
|
+
- PK: Public parameters and the public key of the TA.
|
|
325
|
+
- ID: User's unique identifier.
|
|
326
|
+
- R: w ** k, where (w) is a public point on the curve, and (k) is the secret KFN selected by the user.
|
|
327
|
+
- attributes_list: List of attributes held by this user, where each attribute is in the format:
|
|
328
|
+
'attrName_value'
|
|
329
|
+
Outputs:
|
|
330
|
+
- SK: User's secret key.
|
|
331
|
+
"""
|
|
332
|
+
self._validate_attributes_list(attributes_list)
|
|
333
|
+
r = self._group.random(ZR)
|
|
334
|
+
g = PK['g']
|
|
335
|
+
w = PK['w']
|
|
336
|
+
u = PK['u']
|
|
337
|
+
h = PK['h']
|
|
338
|
+
v = PK['v']
|
|
339
|
+
alpha = MSK['alpha']
|
|
340
|
+
x = MSK['x']
|
|
341
|
+
y = MSK['y']
|
|
342
|
+
|
|
343
|
+
d = self._group.random(ZR) # TODO: AB: If (x + ID + y * d) mod p = 0, then choose another d
|
|
344
|
+
|
|
345
|
+
K_0 = (g ** (alpha / (x + ID + y * d))) * (R ** r)
|
|
346
|
+
K_1 = g ** r
|
|
347
|
+
K_2 = g ** (x * r)
|
|
348
|
+
K_3 = g ** (y * r)
|
|
349
|
+
T1 = ID
|
|
350
|
+
T3 = d
|
|
351
|
+
K_i_2 = {}
|
|
352
|
+
K_i_3 = {}
|
|
353
|
+
for full_attr_value_name in attributes_list:
|
|
354
|
+
# attr_name = full_attr_value_name.split('_')[0]
|
|
355
|
+
r_i = self._group.random(ZR)
|
|
356
|
+
K_i_2[full_attr_value_name] = g ** r_i
|
|
357
|
+
hash_attr_val_in_z_p = self._group.hash(full_attr_value_name, type=ZR)
|
|
358
|
+
K_i_3[full_attr_value_name] = (((u ** hash_attr_val_in_z_p) * h) ** r_i) * v ** (-r * (x + ID + y * d))
|
|
359
|
+
|
|
360
|
+
self._user_ID_to_w_pow_k_dict[T1] = R
|
|
361
|
+
|
|
362
|
+
SK = {'attributes_list': attributes_list, 'K_0': K_0, 'K_1': K_1, 'K_2': K_2, 'K_3': K_3, 'K_i_2': K_i_2,
|
|
363
|
+
'K_i_3': K_i_3, 'T1': T1, 'T3': T3}
|
|
364
|
+
return SK
|
|
365
|
+
|
|
366
|
+
def encrypt(self, m, PK, access_policy: Dict[str, List[str]]):
|
|
367
|
+
"""
|
|
368
|
+
Encrypt a message using an access policy. This function is performed by a data user who wants to encrypt his
|
|
369
|
+
message with an access policy. They consider only and-gates in their policy.
|
|
370
|
+
Note: The access policy is hidden into the ciphertext.
|
|
371
|
+
Inputs:
|
|
372
|
+
- PK: Public parameters and the public key of the TA.
|
|
373
|
+
- m: Message to be encrypted in G_T.
|
|
374
|
+
- access_policy: Access policy that will be used to encrypt the message. It has to be and gated policy,
|
|
375
|
+
which means that each attribute can have only one value.
|
|
376
|
+
Outputs:
|
|
377
|
+
- CT: Cipher text.
|
|
378
|
+
"""
|
|
379
|
+
g = PK['g']
|
|
380
|
+
w = PK['w']
|
|
381
|
+
v = PK['v']
|
|
382
|
+
u = PK['u']
|
|
383
|
+
h = PK['h']
|
|
384
|
+
X = PK['X']
|
|
385
|
+
Y = PK['Y']
|
|
386
|
+
s = self._group.random(ZR)
|
|
387
|
+
s_n = s
|
|
388
|
+
access_policy_len = len(access_policy)
|
|
389
|
+
C = m * PK['e_gg_alpha'] ** s
|
|
390
|
+
C_1 = g ** s
|
|
391
|
+
C_2 = X ** s
|
|
392
|
+
C_3 = Y ** s
|
|
393
|
+
C_i_1 = {}
|
|
394
|
+
C_i_3 = {}
|
|
395
|
+
C_i_2 = {}
|
|
396
|
+
for idx, attr_name in enumerate(access_policy):
|
|
397
|
+
if idx < access_policy_len - 1:
|
|
398
|
+
s_i = self._group.random(ZR)
|
|
399
|
+
s_n = s_n - s_i
|
|
400
|
+
else:
|
|
401
|
+
s_i = s_n
|
|
402
|
+
t_i = self._group.random(ZR)
|
|
403
|
+
C_i_1[attr_name] = (w ** s_i) * (v ** t_i)
|
|
404
|
+
C_i_3[attr_name] = g ** t_i
|
|
405
|
+
|
|
406
|
+
for attr_value in self.attributes_dict[attr_name]:
|
|
407
|
+
full_attr_value_name = Attribute.get_full_attribute_value_name(attr_name, attr_value)
|
|
408
|
+
if attr_value in access_policy[attr_name]:
|
|
409
|
+
hash_attr_val_in_z_p = self._group.hash(full_attr_value_name, type=ZR)
|
|
410
|
+
C_i_ai_2 = ((u ** hash_attr_val_in_z_p) * h) ** (-t_i)
|
|
411
|
+
else:
|
|
412
|
+
C_i_ai_2 = self._group.random(G1)
|
|
413
|
+
C_i_2[full_attr_value_name] = C_i_ai_2
|
|
414
|
+
CT = {'C': C,
|
|
415
|
+
'C_1': C_1,
|
|
416
|
+
'C_2': C_2,
|
|
417
|
+
'C_3': C_3,
|
|
418
|
+
'C_i_1': C_i_1,
|
|
419
|
+
'C_i_3': C_i_3,
|
|
420
|
+
'C_i_ai_2': C_i_2}
|
|
421
|
+
return CT
|
|
422
|
+
|
|
423
|
+
def decrypt(self, CT, PK, SK):
|
|
424
|
+
"""
|
|
425
|
+
Decrypt a cipher text. This algorithm is performed by a data user who has the required attributes to decipher
|
|
426
|
+
the ciphertext that was encrypted using an access policy.
|
|
427
|
+
Inputs:
|
|
428
|
+
- CT: Cipher text.
|
|
429
|
+
- PK: Public parameters and the public key of the TA.
|
|
430
|
+
- SK: User's secret key.
|
|
431
|
+
Outputs:
|
|
432
|
+
- m: The original decrypted message.
|
|
433
|
+
"""
|
|
434
|
+
nominator = pair((CT['C_1'] ** SK['T1']) * CT['C_2'] * (CT['C_3'] ** SK['T3']), SK['K_0'])
|
|
435
|
+
denominator = self._group.init(GT, 1)
|
|
436
|
+
for attr_name in CT['C_i_1']:
|
|
437
|
+
# Find the attribute value that exists inside both the user's key for attr_name
|
|
438
|
+
found_attribute_value_full_name = None
|
|
439
|
+
for attr_value_full_name in SK['K_i_2']:
|
|
440
|
+
if attr_value_full_name.find(attr_name) == 0:
|
|
441
|
+
found_attribute_value_full_name = attr_value_full_name
|
|
442
|
+
if not found_attribute_value_full_name:
|
|
443
|
+
return False # The user does not have the necessary attributes to decrypt
|
|
444
|
+
|
|
445
|
+
denominator = (denominator * ((pair(CT['C_i_1'][attr_name], (SK['K_1'] ** SK['T1']) * SK['K_2'] * (SK['K_3'] ** SK['T3'])) *
|
|
446
|
+
pair(CT['C_i_ai_2'][found_attribute_value_full_name],
|
|
447
|
+
SK['K_i_2'][found_attribute_value_full_name]) *
|
|
448
|
+
pair(CT['C_i_3'][attr_name], SK['K_i_3'][found_attribute_value_full_name])) ** SK['k']))
|
|
449
|
+
B = nominator / denominator
|
|
450
|
+
recovered_message = CT['C'] / B
|
|
451
|
+
return recovered_message
|
|
452
|
+
|
|
453
|
+
def trace(self, SK_suspected, authentic_user_IDs_list, PK):
|
|
454
|
+
"""
|
|
455
|
+
Trace function is executed by the auditor. The auditor checks the suspected SK and determines who is misbehaving
|
|
456
|
+
: the user who owns SK or the TA. If this function is called, it means that either the user or the TA is
|
|
457
|
+
misbehaving. The trigger how this function is triggered and how the malicious activity is detected is out of
|
|
458
|
+
this paper's scope.
|
|
459
|
+
Inputs:
|
|
460
|
+
- SK_suspected: Secret key of the suspected user under the white box model, which means that it has access
|
|
461
|
+
to the full secret key of the user.
|
|
462
|
+
- authentic_user_IDs_list: A list of the authentic user IDs issued by a trusted third party outside the
|
|
463
|
+
system.
|
|
464
|
+
- PK: Public parameters and the public key of the TA.
|
|
465
|
+
Outputs:
|
|
466
|
+
- {'user': True/False,
|
|
467
|
+
'TA': True/False} ; Only one of them will be true and the other will be false.
|
|
468
|
+
"""
|
|
469
|
+
assert self._is_SK_well_formed(SK_suspected), "SK is not well formed."
|
|
470
|
+
user_id = SK_suspected['T1']
|
|
471
|
+
if user_id not in authentic_user_IDs_list:
|
|
472
|
+
return {'user': False, 'TA': True} # The TA issued a fake ID for a fake or not illegible user.
|
|
473
|
+
w_pow_k_ID = self._user_ID_to_w_pow_k_dict[user_id]
|
|
474
|
+
k = SK_suspected['k']
|
|
475
|
+
w = PK['w']
|
|
476
|
+
if w**k != w_pow_k_ID:
|
|
477
|
+
return {'user': True, 'TA': False} # User is misbehaving and gave his keys to someone else.
|
|
478
|
+
else:
|
|
479
|
+
return {'user': False, 'TA': True} # The TA is misbehaving.
|
|
480
|
+
|
|
481
|
+
def _is_SK_well_formed(self, SK):
|
|
482
|
+
search_keys = ['attributes_list', 'K_0', 'K_1', 'K_2', 'K_3', 'K_i_2', 'K_i_3', 'T1', 'T3', 'k']
|
|
483
|
+
for a_search_key in search_keys:
|
|
484
|
+
if a_search_key not in SK:
|
|
485
|
+
return False
|
|
486
|
+
return True
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
class ShnorrInteractiveZKP():
|
|
491
|
+
"""
|
|
492
|
+
Shnorr's Interactive ZKP
|
|
493
|
+
"""
|
|
494
|
+
class Prover:
|
|
495
|
+
def __init__(self, secret_x, groupObj):
|
|
496
|
+
self.__r = None
|
|
497
|
+
self.group = groupObj
|
|
498
|
+
self.__x = secret_x
|
|
499
|
+
|
|
500
|
+
def create_prover_commitments(self, pk):
|
|
501
|
+
"""
|
|
502
|
+
1) This function is executed by the prover to send a random value to the verifier
|
|
503
|
+
"""
|
|
504
|
+
self.__r = self.group.random()
|
|
505
|
+
u = (pk['g'] ** self.__r)
|
|
506
|
+
return u
|
|
507
|
+
|
|
508
|
+
def create_proof(self, c):
|
|
509
|
+
"""
|
|
510
|
+
3) This function is executed by the prover after he received the challenge value (c) from the verifier
|
|
511
|
+
"""
|
|
512
|
+
z = self.__r + c * self.__x
|
|
513
|
+
return z # proof
|
|
514
|
+
|
|
515
|
+
class Verifier:
|
|
516
|
+
|
|
517
|
+
def __init__(self, groupObj):
|
|
518
|
+
self.group = groupObj
|
|
519
|
+
|
|
520
|
+
def create_verifier_challenge(self):
|
|
521
|
+
"""
|
|
522
|
+
2) This function is executed by the verifier after he had received the value u from the prover to send a challenge value to the prover.
|
|
523
|
+
"""
|
|
524
|
+
self.c = self.group.random()
|
|
525
|
+
return self.c
|
|
526
|
+
|
|
527
|
+
def is_proof_verified(self, z, pk, u, h):
|
|
528
|
+
"""
|
|
529
|
+
4) This function is executed by the verifier to verify the authenticity of the proof sent by the prover
|
|
530
|
+
z: Created by the prover in create_proof function
|
|
531
|
+
u: Created by the prover in create_prover_commitments function
|
|
532
|
+
h: g^x, where x is the secret key of the prover that he wants to prove that he knows it.
|
|
533
|
+
"""
|
|
534
|
+
if (pk['g'] ** z) == u * h ** self.c:
|
|
535
|
+
return True
|
|
536
|
+
return False
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
def main():
|
|
540
|
+
CP_policy_hiding_ABE_test()
|
|
541
|
+
CP_policy_hiding_with_accountability_test()
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
def CP_policy_hiding_ABE_test():
|
|
545
|
+
print("************************************* CP policy hiding ABE test *******************************************")
|
|
546
|
+
attr1_values = ['val1', 'val2', 'val3']
|
|
547
|
+
attr2_values = ['val1', 'val4']
|
|
548
|
+
attributes_dict = {
|
|
549
|
+
'attr1': attr1_values,
|
|
550
|
+
'attr2': attr2_values
|
|
551
|
+
}
|
|
552
|
+
user1_attributes = ['attr1_val2', 'attr2_val4']
|
|
553
|
+
user2_attributes = ['attr1_val2', 'attr2_val1']
|
|
554
|
+
# The access policy that will be used to encrypt the message
|
|
555
|
+
access_policy = {'attr1': ['val1', 'val2'], # Set of attributes allowed for 'attr1' in the access policy.
|
|
556
|
+
'attr2': ['val4'] # Set of attributes allowed for 'attr2' in the access policy.
|
|
557
|
+
}
|
|
558
|
+
attr1 = Attribute('attr1', attr1_values)
|
|
559
|
+
attr2 = Attribute('attr2', attr2_values)
|
|
560
|
+
attr1_values = attr1.get_attribute_values_full_name()
|
|
561
|
+
attr2_values = attr2.get_attribute_values_full_name()
|
|
562
|
+
print("attribute 1 full values names: ", attr1_values)
|
|
563
|
+
print("attribute 2 full values names: ", attr2_values)
|
|
564
|
+
group_obj = PairingGroup('SS512')
|
|
565
|
+
cp_hiding_ABE = CP_Hiding_ABE(group_obj)
|
|
566
|
+
MSK, PK = cp_hiding_ABE.setup(attributes_dict) # TA's MSK, PK
|
|
567
|
+
print("MSK: ", MSK)
|
|
568
|
+
print("PK: ", PK)
|
|
569
|
+
user1_SK = cp_hiding_ABE.key_gen(MSK, PK, user1_attributes)
|
|
570
|
+
print('user1 SK: ', user1_SK)
|
|
571
|
+
user2_SK = cp_hiding_ABE.key_gen(MSK, PK, user2_attributes)
|
|
572
|
+
print('user2 SK: ', user1_SK)
|
|
573
|
+
rand_msg = group_obj.random(GT)
|
|
574
|
+
CT = cp_hiding_ABE.encrypt(rand_msg, PK, access_policy)
|
|
575
|
+
print("CT: ", CT)
|
|
576
|
+
recovered_message = cp_hiding_ABE.decrypt(CT, PK, user1_SK)
|
|
577
|
+
print("recovered message: ", recovered_message)
|
|
578
|
+
# No error is generated since user 1's attributes matches the access policy embedded inside the CT.
|
|
579
|
+
assert recovered_message == rand_msg, "Random message does not match the recovered message"
|
|
580
|
+
# User 2 tries to decrypt CT.
|
|
581
|
+
recovered_message = cp_hiding_ABE.decrypt(CT, PK, user2_SK)
|
|
582
|
+
print("recovered message: ", recovered_message)
|
|
583
|
+
# An error is generated since user 2 does not have the required attributes to decrypt CT.
|
|
584
|
+
# assert recovered_message == rand_msg, "Random message does not match the recovered message" # Uncomment to raise the error.
|
|
585
|
+
print("***********************************************************************************************************")
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
def CP_policy_hiding_with_accountability_test():
|
|
589
|
+
print("*************************** CP policy hiding ABE with accountability test *********************************")
|
|
590
|
+
attr1_values = ['val1', 'val2', 'val3']
|
|
591
|
+
attr2_values = ['val1', 'val4']
|
|
592
|
+
attributes_dict = {
|
|
593
|
+
'attr1': attr1_values,
|
|
594
|
+
'attr2': attr2_values
|
|
595
|
+
}
|
|
596
|
+
user1_attributes = ['attr1_val2', 'attr2_val4']
|
|
597
|
+
user2_attributes = ['attr1_val2', 'attr2_val1']
|
|
598
|
+
|
|
599
|
+
user1_ID = 123
|
|
600
|
+
user2_ID = 57534
|
|
601
|
+
# The access policy that will be used to encrypt the message
|
|
602
|
+
access_policy = {'attr1': ['val1', 'val2'], # Set of attributes allowed for 'attr1' in the access policy.
|
|
603
|
+
'attr2': ['val4'] # Set of attributes allowed for 'attr2' in the access policy.
|
|
604
|
+
}
|
|
605
|
+
attr1 = Attribute('attr1', attr1_values)
|
|
606
|
+
attr2 = Attribute('attr2', attr2_values)
|
|
607
|
+
attr1_values = attr1.get_attribute_values_full_name()
|
|
608
|
+
attr2_values = attr2.get_attribute_values_full_name()
|
|
609
|
+
print("attribute 1 full values names: ", attr1_values)
|
|
610
|
+
print("attribute 2 full values names: ", attr2_values)
|
|
611
|
+
group_obj = PairingGroup('SS512')
|
|
612
|
+
cp_hiding_ABE = CP_Hiding_Accountability_ABE(group_obj)
|
|
613
|
+
MSK, PK = cp_hiding_ABE.setup(attributes_dict) # TA's MSK, PK
|
|
614
|
+
print("MSK: ", MSK)
|
|
615
|
+
print("PK: ", PK)
|
|
616
|
+
|
|
617
|
+
user1_ID = group_obj.init(ZR, user1_ID)
|
|
618
|
+
user2_ID = group_obj.init(ZR, user2_ID)
|
|
619
|
+
|
|
620
|
+
user1_SK = cp_hiding_ABE.key_gen(MSK, PK, user1_ID, user1_attributes)
|
|
621
|
+
print('user1 SK: ', user1_SK)
|
|
622
|
+
user2_SK = cp_hiding_ABE.key_gen(MSK, PK, user2_ID, user2_attributes)
|
|
623
|
+
print('user2 SK: ', user1_SK)
|
|
624
|
+
rand_msg = group_obj.random(GT)
|
|
625
|
+
CT = cp_hiding_ABE.encrypt(rand_msg, PK, access_policy)
|
|
626
|
+
print("CT: ", CT)
|
|
627
|
+
recovered_message = cp_hiding_ABE.decrypt(CT, PK, user1_SK)
|
|
628
|
+
print("recovered message: ", recovered_message)
|
|
629
|
+
# No error is generated since user 1's attributes matches the access policy embedded inside the CT.
|
|
630
|
+
assert recovered_message == rand_msg, "Random message does not match the recovered message"
|
|
631
|
+
|
|
632
|
+
# User 2 tries to decrypt CT.
|
|
633
|
+
recovered_message = cp_hiding_ABE.decrypt(CT, PK, user2_SK)
|
|
634
|
+
print("recovered message: ", recovered_message)
|
|
635
|
+
# An error is generated since user 2 does not have the required attributes to decrypt CT.
|
|
636
|
+
# assert recovered_message == rand_msg, "Random message does not match the recovered message" # Uncomment to raise the error.
|
|
637
|
+
|
|
638
|
+
authentic_user_IDs_list = [123]
|
|
639
|
+
# User 2's ID is not in the authentic list, which means that his ID is fabricated and this malicious action is
|
|
640
|
+
# traced to the TA.
|
|
641
|
+
misbehaving_result = cp_hiding_ABE.trace(user2_SK, authentic_user_IDs_list, PK)
|
|
642
|
+
print("Misbehaving result for user2 SK: ", misbehaving_result)
|
|
643
|
+
print("***********************************************************************************************************")
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
if __name__ == "__main__":
|
|
647
|
+
main()
|