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,298 @@
|
|
|
1
|
+
'''
|
|
2
|
+
**DAC-MACS: Data Access Control for Multi-Authority Cloud Storage (YJ14)**
|
|
3
|
+
|
|
4
|
+
*Authors:* Kan Yang, Xiaohua Jia
|
|
5
|
+
|
|
6
|
+
| **Title:** "DAC-MACS: Effective Data Access Control for Multi-Authority Cloud Storage Systems"
|
|
7
|
+
| **Published in:** Security for Cloud Storage Systems - SpringerBriefs in Computer Science, 2014
|
|
8
|
+
| **Available from:** http://link.springer.com/chapter/10.1007/978-1-4614-7873-7_4
|
|
9
|
+
| **Notes:** Multi-authority scheme with efficient attribute revocation
|
|
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: artjomb
|
|
20
|
+
:Date: 07/2014
|
|
21
|
+
'''
|
|
22
|
+
|
|
23
|
+
from charm.toolbox.pairinggroup import PairingGroup,ZR,G1,GT,pair
|
|
24
|
+
from charm.toolbox.secretutil import SecretUtil
|
|
25
|
+
from charm.toolbox.ABEncMultiAuth import ABEncMultiAuth
|
|
26
|
+
|
|
27
|
+
class DACMACS(object):
|
|
28
|
+
def __init__(self, groupObj):
|
|
29
|
+
self.util = SecretUtil(groupObj, verbose=False) #Create Secret Sharing Scheme
|
|
30
|
+
self.group = groupObj #:Prime order group
|
|
31
|
+
|
|
32
|
+
def setup(self):
|
|
33
|
+
'''Global Setup (executed by CA)'''
|
|
34
|
+
#:In global setup, a bilinear group G of prime order p is chosen
|
|
35
|
+
#:The global public parameters, GP and p, and a generator g of G. A random oracle H maps global identities GID to elements of G
|
|
36
|
+
|
|
37
|
+
#:group contains
|
|
38
|
+
#:the prime order p is contained somewhere within the group object
|
|
39
|
+
g = self.group.random(G1)
|
|
40
|
+
#: The oracle that maps global identities GID onto elements of G
|
|
41
|
+
#:H = lambda str: g** group.hash(str)
|
|
42
|
+
H = lambda x: self.group.hash(x, G1)
|
|
43
|
+
a = self.group.random()
|
|
44
|
+
g_a = g ** a
|
|
45
|
+
GPP = {'g': g, 'g_a': g_a, 'H': H}
|
|
46
|
+
GMK = {'a': a}
|
|
47
|
+
|
|
48
|
+
return (GPP, GMK)
|
|
49
|
+
|
|
50
|
+
def registerUser(self, GPP):
|
|
51
|
+
'''Generate user keys (executed by the user).'''
|
|
52
|
+
g = GPP['g']
|
|
53
|
+
u = self.group.random()
|
|
54
|
+
z = self.group.random()
|
|
55
|
+
g_u = g ** u
|
|
56
|
+
g_z = g ** (1 / z)
|
|
57
|
+
|
|
58
|
+
return ((g_u, z), { 'g_z': g_z, 'u': u }) # (private, public)
|
|
59
|
+
|
|
60
|
+
def setupAuthority(self, GPP, authorityid, attributes, authorities):
|
|
61
|
+
'''Generate attribute authority keys (executed by attribute authority)'''
|
|
62
|
+
if authorityid not in authorities:
|
|
63
|
+
alpha = self.group.random()
|
|
64
|
+
beta = self.group.random()
|
|
65
|
+
gamma = self.group.random()
|
|
66
|
+
SK = {'alpha': alpha, 'beta': beta, 'gamma': gamma}
|
|
67
|
+
PK = {
|
|
68
|
+
'e_alpha': pair(GPP['g'], GPP['g']) ** alpha,
|
|
69
|
+
'g_beta_inv': GPP['g'] ** (1/beta),
|
|
70
|
+
'g_beta_gamma': GPP['g'] ** (gamma/beta)
|
|
71
|
+
}
|
|
72
|
+
authAttrs = {}
|
|
73
|
+
authorities[authorityid] = (SK, PK, authAttrs)
|
|
74
|
+
else:
|
|
75
|
+
SK, PK, authAttrs = authorities[authorityid]
|
|
76
|
+
for attrib in attributes:
|
|
77
|
+
if attrib in authAttrs:
|
|
78
|
+
continue
|
|
79
|
+
versionKey = self.group.random() # random or really 'choose' ?
|
|
80
|
+
h = GPP['H'](attrib)
|
|
81
|
+
pk = ((GPP['g'] ** versionKey) * h) ** SK['gamma']
|
|
82
|
+
authAttrs[attrib] = {
|
|
83
|
+
'VK': versionKey, #secret
|
|
84
|
+
'PK': pk, #public
|
|
85
|
+
}
|
|
86
|
+
return (SK, PK, authAttrs)
|
|
87
|
+
|
|
88
|
+
def keygen(self, GPP, authority, attribute, userObj, USK = None):
|
|
89
|
+
'''Generate user keys for a specific attribute (executed on attribute authority)'''
|
|
90
|
+
if 't' not in userObj:
|
|
91
|
+
userObj['t'] = self.group.random() #private to AA
|
|
92
|
+
t = userObj['t']
|
|
93
|
+
|
|
94
|
+
ASK, APK, authAttrs = authority
|
|
95
|
+
u = userObj
|
|
96
|
+
if USK is None:
|
|
97
|
+
USK = {}
|
|
98
|
+
if 'K' not in USK or 'L' not in USK or 'R' not in USK or 'AK' not in USK:
|
|
99
|
+
USK['K'] = \
|
|
100
|
+
(u['g_z'] ** ASK['alpha']) * \
|
|
101
|
+
(GPP['g_a'] ** u['u']) * \
|
|
102
|
+
(GPP['g_a'] ** (t / ASK['beta']))
|
|
103
|
+
USK['L'] = u['g_z'] ** (ASK['beta'] * t)
|
|
104
|
+
USK['R'] = GPP['g_a'] ** t
|
|
105
|
+
USK['AK'] = {}
|
|
106
|
+
AK = (u['g_z'] ** (ASK['beta'] * ASK['gamma'] * t)) * \
|
|
107
|
+
(authAttrs[attribute]['PK'] ** (ASK['beta'] * u['u']))
|
|
108
|
+
USK['AK'][attribute] = AK
|
|
109
|
+
return USK
|
|
110
|
+
|
|
111
|
+
def encrypt(self, GPP, policy_str, k, authority):
|
|
112
|
+
'''Generate the cipher-text from the content(-key) and a policy (executed by the content owner)'''
|
|
113
|
+
#GPP are global parameters
|
|
114
|
+
#k is the content key (group element based on AES key)
|
|
115
|
+
#policy_str is the policy string
|
|
116
|
+
#authority is the authority tuple
|
|
117
|
+
|
|
118
|
+
_, APK, authAttrs = authority
|
|
119
|
+
|
|
120
|
+
policy = self.util.createPolicy(policy_str)
|
|
121
|
+
secret = self.group.random()
|
|
122
|
+
shares = self.util.calculateSharesList(secret, policy)
|
|
123
|
+
shares = dict([(x[0].getAttributeAndIndex(), x[1]) for x in shares])
|
|
124
|
+
|
|
125
|
+
C1 = k * (APK['e_alpha'] ** secret)
|
|
126
|
+
C2 = GPP['g'] ** secret
|
|
127
|
+
C3 = APK['g_beta_inv'] ** secret
|
|
128
|
+
C = {}
|
|
129
|
+
D = {}
|
|
130
|
+
DS = {}
|
|
131
|
+
|
|
132
|
+
for attr, s_share in shares.items():
|
|
133
|
+
k_attr = self.util.strip_index(attr)
|
|
134
|
+
r_i = self.group.random()
|
|
135
|
+
attrPK = authAttrs[attr]
|
|
136
|
+
C[attr] = (GPP['g_a'] ** s_share) * ~(attrPK['PK'] ** r_i)
|
|
137
|
+
D[attr] = APK['g_beta_inv'] ** r_i
|
|
138
|
+
DS[attr] = ~(APK['g_beta_gamma'] ** r_i)
|
|
139
|
+
|
|
140
|
+
return {'C1': C1, 'C2': C2, 'C3': C3, 'C': C, 'D': D, 'DS': DS, 'policy': policy_str}
|
|
141
|
+
|
|
142
|
+
def generateTK(self, GPP, CT, UASK, g_u):
|
|
143
|
+
'''Generates a token using the user's attribute secret keys to offload the decryption process (executed by cloud provider)'''
|
|
144
|
+
usr_attribs = list(UASK['AK'].keys())
|
|
145
|
+
policy = self.util.createPolicy(CT['policy'])
|
|
146
|
+
pruned = self.util.prune(policy, usr_attribs)
|
|
147
|
+
if pruned == False:
|
|
148
|
+
return False
|
|
149
|
+
coeffs = self.util.getCoefficients(policy)
|
|
150
|
+
|
|
151
|
+
dividend = pair(CT['C2'], UASK['K']) * ~pair(UASK['R'], CT['C3'])
|
|
152
|
+
n_a = 1
|
|
153
|
+
divisor = 1
|
|
154
|
+
|
|
155
|
+
for attr in pruned:
|
|
156
|
+
x = attr.getAttributeAndIndex()
|
|
157
|
+
y = attr.getAttribute()
|
|
158
|
+
temp = \
|
|
159
|
+
pair(CT['C'][y], g_u) * \
|
|
160
|
+
pair(CT['D'][y], UASK['AK'][y]) * \
|
|
161
|
+
pair(CT['DS'][y], UASK['L'])
|
|
162
|
+
divisor *= temp ** (coeffs[x] * n_a)
|
|
163
|
+
return dividend / divisor
|
|
164
|
+
|
|
165
|
+
def decrypt(self, CT, TK, z):
|
|
166
|
+
'''Decrypts the content(-key) from the cipher-text using the token and the user secret key (executed by user/content consumer)'''
|
|
167
|
+
return CT['C1'] / (TK ** z)
|
|
168
|
+
|
|
169
|
+
def ukeygen(self, GPP, authority, attribute, userObj):
|
|
170
|
+
'''Generate update keys for users and cloud provider (executed by attribute authority?)'''
|
|
171
|
+
ASK, _, authAttrs = authority
|
|
172
|
+
oldVersionKey = authAttrs[attribute]['VK']
|
|
173
|
+
newVersionKey = oldVersionKey
|
|
174
|
+
while oldVersionKey == newVersionKey:
|
|
175
|
+
newVersionKey = self.group.random()
|
|
176
|
+
authAttrs[attribute]['VK'] = newVersionKey
|
|
177
|
+
|
|
178
|
+
u = userObj['u']
|
|
179
|
+
|
|
180
|
+
AUK = ASK['gamma'] * (newVersionKey - oldVersionKey)
|
|
181
|
+
KUK = GPP['g'] ** (u * ASK['beta'] * AUK)
|
|
182
|
+
CUK = ASK['beta'] * AUK / ASK['gamma']
|
|
183
|
+
|
|
184
|
+
authAttrs[attribute]['PK'] = authAttrs[attribute]['PK'] * (GPP['g'] ** AUK)
|
|
185
|
+
|
|
186
|
+
return { 'KUK': KUK, 'CUK': CUK }
|
|
187
|
+
|
|
188
|
+
def skupdate(self, USK, attribute, KUK):
|
|
189
|
+
'''Updates the user attribute secret key for the specified attribute (executed by non-revoked user)'''
|
|
190
|
+
USK['AK'][attribute] = USK['AK'][attribute] * KUK
|
|
191
|
+
|
|
192
|
+
def ctupdate(self, GPP, CT, attribute, CUK):
|
|
193
|
+
'''Updates the cipher-text using the update key, because of the revoked attribute (executed by cloud provider)'''
|
|
194
|
+
CT['C'][attribute] = CT['C'][attribute] * (CT['DS'][attribute] ** CUK)
|
|
195
|
+
|
|
196
|
+
def basicTest():
|
|
197
|
+
print("RUN basicTest")
|
|
198
|
+
groupObj = PairingGroup('SS512')
|
|
199
|
+
dac = DACMACS(groupObj)
|
|
200
|
+
GPP, GMK = dac.setup()
|
|
201
|
+
|
|
202
|
+
users = {} # public user data
|
|
203
|
+
authorities = {}
|
|
204
|
+
|
|
205
|
+
authorityAttributes = ["ONE", "TWO", "THREE", "FOUR"]
|
|
206
|
+
authority1 = "authority1"
|
|
207
|
+
|
|
208
|
+
dac.setupAuthority(GPP, authority1, authorityAttributes, authorities)
|
|
209
|
+
|
|
210
|
+
alice = { 'id': 'alice', 'authoritySecretKeys': {}, 'keys': None }
|
|
211
|
+
alice['keys'], users[alice['id']] = dac.registerUser(GPP)
|
|
212
|
+
|
|
213
|
+
for attr in authorityAttributes[0:-1]:
|
|
214
|
+
dac.keygen(GPP, authorities[authority1], attr, users[alice['id']], alice['authoritySecretKeys'])
|
|
215
|
+
|
|
216
|
+
k = groupObj.random(GT)
|
|
217
|
+
|
|
218
|
+
policy_str = '((ONE or THREE) and (TWO or FOUR))'
|
|
219
|
+
|
|
220
|
+
CT = dac.encrypt(GPP, policy_str, k, authorities[authority1])
|
|
221
|
+
|
|
222
|
+
TK = dac.generateTK(GPP, CT, alice['authoritySecretKeys'], alice['keys'][0])
|
|
223
|
+
|
|
224
|
+
PT = dac.decrypt(CT, TK, alice['keys'][1])
|
|
225
|
+
|
|
226
|
+
# print "k", k
|
|
227
|
+
# print "PT", PT
|
|
228
|
+
|
|
229
|
+
assert k == PT, 'FAILED DECRYPTION!'
|
|
230
|
+
print('SUCCESSFUL DECRYPTION')
|
|
231
|
+
|
|
232
|
+
def revokedTest():
|
|
233
|
+
print("RUN revokedTest")
|
|
234
|
+
groupObj = PairingGroup('SS512')
|
|
235
|
+
dac = DACMACS(groupObj)
|
|
236
|
+
GPP, GMK = dac.setup()
|
|
237
|
+
|
|
238
|
+
users = {} # public user data
|
|
239
|
+
authorities = {}
|
|
240
|
+
|
|
241
|
+
authorityAttributes = ["ONE", "TWO", "THREE", "FOUR"]
|
|
242
|
+
authority1 = "authority1"
|
|
243
|
+
|
|
244
|
+
dac.setupAuthority(GPP, authority1, authorityAttributes, authorities)
|
|
245
|
+
|
|
246
|
+
alice = { 'id': 'alice', 'authoritySecretKeys': {}, 'keys': None }
|
|
247
|
+
alice['keys'], users[alice['id']] = dac.registerUser(GPP)
|
|
248
|
+
|
|
249
|
+
bob = { 'id': 'bob', 'authoritySecretKeys': {}, 'keys': None }
|
|
250
|
+
bob['keys'], users[bob['id']] = dac.registerUser(GPP)
|
|
251
|
+
|
|
252
|
+
for attr in authorityAttributes[0:-1]:
|
|
253
|
+
dac.keygen(GPP, authorities[authority1], attr, users[alice['id']], alice['authoritySecretKeys'])
|
|
254
|
+
dac.keygen(GPP, authorities[authority1], attr, users[bob['id']], bob['authoritySecretKeys'])
|
|
255
|
+
|
|
256
|
+
k = groupObj.random(GT)
|
|
257
|
+
|
|
258
|
+
policy_str = '((ONE or THREE) and (TWO or FOUR))'
|
|
259
|
+
|
|
260
|
+
CT = dac.encrypt(GPP, policy_str, k, authorities[authority1])
|
|
261
|
+
|
|
262
|
+
TK1a = dac.generateTK(GPP, CT, alice['authoritySecretKeys'], alice['keys'][0])
|
|
263
|
+
PT1a = dac.decrypt(CT, TK1a, alice['keys'][1])
|
|
264
|
+
TK1b = dac.generateTK(GPP, CT, bob['authoritySecretKeys'], bob['keys'][0])
|
|
265
|
+
PT1b = dac.decrypt(CT, TK1b, bob['keys'][1])
|
|
266
|
+
|
|
267
|
+
assert k == PT1a, 'FAILED DECRYPTION (1a)!'
|
|
268
|
+
assert k == PT1b, 'FAILED DECRYPTION (1b)!'
|
|
269
|
+
print('SUCCESSFUL DECRYPTION 1')
|
|
270
|
+
|
|
271
|
+
# revoke bob on "ONE"
|
|
272
|
+
attribute = "ONE"
|
|
273
|
+
UK = dac.ukeygen(GPP, authorities[authority1], attribute, users[alice['id']])
|
|
274
|
+
dac.skupdate(alice['authoritySecretKeys'], attribute, UK['KUK'])
|
|
275
|
+
dac.ctupdate(GPP, CT, attribute, UK['CUK'])
|
|
276
|
+
|
|
277
|
+
TK2a = dac.generateTK(GPP, CT, alice['authoritySecretKeys'], alice['keys'][0])
|
|
278
|
+
PT2a = dac.decrypt(CT, TK2a, alice['keys'][1])
|
|
279
|
+
TK2b = dac.generateTK(GPP, CT, bob['authoritySecretKeys'], bob['keys'][0])
|
|
280
|
+
PT2b = dac.decrypt(CT, TK2b, bob['keys'][1])
|
|
281
|
+
|
|
282
|
+
assert k == PT2a, 'FAILED DECRYPTION (2a)!'
|
|
283
|
+
assert k != PT2b, 'SUCCESSFUL DECRYPTION (2b)!'
|
|
284
|
+
print('SUCCESSFUL DECRYPTION 2')
|
|
285
|
+
|
|
286
|
+
def test():
|
|
287
|
+
groupObj = PairingGroup('SS512')
|
|
288
|
+
# k = groupObj.random()
|
|
289
|
+
#print "k", k, ~k, k * ~k
|
|
290
|
+
# g = groupObj.random(G1)
|
|
291
|
+
# print "g", g, pair(g, g)
|
|
292
|
+
# gt = groupObj.random(GT)
|
|
293
|
+
# print "gt", gt
|
|
294
|
+
|
|
295
|
+
if __name__ == '__main__':
|
|
296
|
+
basicTest()
|
|
297
|
+
revokedTest()
|
|
298
|
+
# test()
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
'''
|
|
2
|
+
**Key-Policy Attribute-Based Encryption (LSW08)**
|
|
3
|
+
|
|
4
|
+
*Authors:* Allison Lewko, Amit Sahai, Brent Waters
|
|
5
|
+
|
|
6
|
+
| **Title:** "Revocation Systems with Very Small Private Keys"
|
|
7
|
+
| **Published in:** IEEE Symposium on Security and Privacy, 2010
|
|
8
|
+
| **Available from:** http://eprint.iacr.org/2008/309.pdf
|
|
9
|
+
| **Notes:** Large Universe Construction
|
|
10
|
+
|
|
11
|
+
.. rubric:: Scheme Properties
|
|
12
|
+
|
|
13
|
+
* **Type:** key-policy attribute-based encryption (public key)
|
|
14
|
+
* **Setting:** Pairing groups
|
|
15
|
+
* **Assumption:** Decisional Bilinear Diffie-Hellman
|
|
16
|
+
|
|
17
|
+
.. rubric:: Implementation
|
|
18
|
+
|
|
19
|
+
:Authors: J. Ayo Akinyele
|
|
20
|
+
:Date: 12/2010
|
|
21
|
+
'''
|
|
22
|
+
|
|
23
|
+
from charm.toolbox.pairinggroup import PairingGroup,ZR,G1,G2,GT,pair
|
|
24
|
+
from charm.toolbox.secretutil import SecretUtil
|
|
25
|
+
from charm.toolbox.ABEnc import ABEnc
|
|
26
|
+
|
|
27
|
+
debug = False
|
|
28
|
+
class KPabe(ABEnc):
|
|
29
|
+
"""
|
|
30
|
+
>>> from charm.toolbox.pairinggroup import PairingGroup,GT
|
|
31
|
+
>>> group = PairingGroup('MNT224')
|
|
32
|
+
>>> kpabe = KPabe(group)
|
|
33
|
+
>>> (master_public_key, master_key) = kpabe.setup()
|
|
34
|
+
>>> policy = '(ONE or THREE) and (THREE or TWO)'
|
|
35
|
+
>>> attributes = [ 'ONE', 'TWO', 'THREE', 'FOUR' ]
|
|
36
|
+
>>> secret_key = kpabe.keygen(master_public_key, master_key, policy)
|
|
37
|
+
>>> msg=group.random(GT)
|
|
38
|
+
>>> cipher_text = kpabe.encrypt(master_public_key, msg, attributes)
|
|
39
|
+
>>> decrypted_msg = kpabe.decrypt(cipher_text, secret_key)
|
|
40
|
+
>>> decrypted_msg == msg
|
|
41
|
+
True
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(self, groupObj, verbose=False):
|
|
45
|
+
ABEnc.__init__(self)
|
|
46
|
+
global group, util
|
|
47
|
+
group = groupObj
|
|
48
|
+
util = SecretUtil(group, verbose)
|
|
49
|
+
|
|
50
|
+
def setup(self):
|
|
51
|
+
# pick random exponents
|
|
52
|
+
alpha1, alpha2, b = group.random(ZR), group.random(ZR), group.random(ZR)
|
|
53
|
+
|
|
54
|
+
alpha = alpha1 * alpha2
|
|
55
|
+
g_G1, g_G2 = group.random(G1), group.random(G2) # PK 1,2
|
|
56
|
+
h_G1, h_G2 = group.random(G1), group.random(G2) # PK 3
|
|
57
|
+
g1b = g_G1 ** b
|
|
58
|
+
e_gg_alpha = pair(g_G1,g_G2) ** alpha
|
|
59
|
+
|
|
60
|
+
#public parameters # 'g_G2^b':(g_G2 ** b), 'g_G2^b2':g_G2 ** (b * b),
|
|
61
|
+
pk = { 'g_G1':g_G1, 'g_G2':g_G2, 'g_G1_b':g1b,
|
|
62
|
+
'g_G1_b2':g1b ** b, 'h_G1_b':h_G1 ** b, 'e(gg)_alpha':e_gg_alpha }
|
|
63
|
+
#secret parameters
|
|
64
|
+
mk = { 'alpha1':alpha1, 'alpha2':alpha2, 'b':b, 'h_G1':h_G1, 'h_G2':h_G2 }
|
|
65
|
+
return (pk, mk)
|
|
66
|
+
|
|
67
|
+
def keygen(self, pk, mk, policy_str):
|
|
68
|
+
policy = util.createPolicy(policy_str)
|
|
69
|
+
attr_list = util.getAttributeList(policy)
|
|
70
|
+
|
|
71
|
+
s = mk['alpha1']; secret = s
|
|
72
|
+
shares = util.calculateSharesDict(secret, policy)
|
|
73
|
+
|
|
74
|
+
D = { 'policy': policy_str }
|
|
75
|
+
for x in attr_list:
|
|
76
|
+
y = util.strip_index(x)
|
|
77
|
+
d = []; r = group.random(ZR)
|
|
78
|
+
if not self.negatedAttr(x): # meaning positive
|
|
79
|
+
d.append((pk['g_G1'] ** (mk['alpha2'] * shares[x])) * (group.hash(y, G1) ** r)) # compute D1 for attribute x
|
|
80
|
+
d.append((pk['g_G2'] ** r)) # compute D2 for attribute x
|
|
81
|
+
#else:
|
|
82
|
+
#d.append((pk['g2_G1'] ** shares[x]) * (pk['g_G1_b2'] ** r)) # compute D3
|
|
83
|
+
#d.append((pk['g_G1_b'] ** (r * group.hash(x))) * (pk['h_G1'] ** r)) # compute D4
|
|
84
|
+
#d.append(pk['g_G1'] ** -r) # compute D5
|
|
85
|
+
D[x] = d
|
|
86
|
+
if debug: print("Access Policy for key: %s" % policy)
|
|
87
|
+
if debug: print("Attribute list: %s" % attr_list)
|
|
88
|
+
return D
|
|
89
|
+
|
|
90
|
+
def negatedAttr(self, attribute):
|
|
91
|
+
if type(attribute) != str: attr = attribute.getAttribute()
|
|
92
|
+
else: attr = attribute
|
|
93
|
+
if attr[0] == '!':
|
|
94
|
+
if debug: print("Checking... => %s" % attr[0])
|
|
95
|
+
return True
|
|
96
|
+
return False
|
|
97
|
+
|
|
98
|
+
def encrypt(self, pk, M, attr_list):
|
|
99
|
+
if debug: print('Encryption Algorithm...')
|
|
100
|
+
# s will hold secret
|
|
101
|
+
t = group.init(ZR, 0)
|
|
102
|
+
s = group.random(); sx = [s]
|
|
103
|
+
for i in range(len(attr_list)):
|
|
104
|
+
sx.append(group.random(ZR))
|
|
105
|
+
sx[0] -= sx[i]
|
|
106
|
+
|
|
107
|
+
E3 = {}
|
|
108
|
+
#E4, E5 = {}, {}
|
|
109
|
+
for i in range(len(attr_list)):
|
|
110
|
+
attr = attr_list[i]
|
|
111
|
+
E3[attr] = group.hash(attr, G1) ** s
|
|
112
|
+
#E4[attr] = pk['g_G1_b'] ** sx[i]
|
|
113
|
+
#E5[attr] = (pk['g_G1_b2'] ** (sx[i] * group.hash(attr))) * (pk['h_G1_b'] ** sx[i])
|
|
114
|
+
|
|
115
|
+
E1 = (pk['e(gg)_alpha'] ** s) * M
|
|
116
|
+
E2 = pk['g_G2'] ** s
|
|
117
|
+
return {'E1':E1, 'E2':E2, 'E3':E3, 'attributes':attr_list }
|
|
118
|
+
|
|
119
|
+
def decrypt(self, E, D):
|
|
120
|
+
policy = util.createPolicy(D['policy'])
|
|
121
|
+
attrs = util.prune(policy, E['attributes'])
|
|
122
|
+
if attrs == False:
|
|
123
|
+
return False
|
|
124
|
+
coeff = util.getCoefficients(policy)
|
|
125
|
+
|
|
126
|
+
Z = {}; prodT = 1
|
|
127
|
+
for i in range(len(attrs)):
|
|
128
|
+
x = attrs[i].getAttribute()
|
|
129
|
+
y = attrs[i].getAttributeAndIndex()
|
|
130
|
+
if not self.negatedAttr(y):
|
|
131
|
+
Z[y] = pair(D[y][0], E['E2']) / pair(E['E3'][x], D[y][1])
|
|
132
|
+
prodT *= Z[y] ** coeff[y]
|
|
133
|
+
|
|
134
|
+
return E['E1'] / prodT
|
|
135
|
+
|
|
136
|
+
def main():
|
|
137
|
+
groupObj = PairingGroup('MNT224')
|
|
138
|
+
kpabe = KPabe(groupObj)
|
|
139
|
+
|
|
140
|
+
(pk, mk) = kpabe.setup()
|
|
141
|
+
|
|
142
|
+
policy = '(ONE or THREE) and (THREE or TWO)'
|
|
143
|
+
attributes = [ 'ONE', 'TWO', 'THREE', 'FOUR' ]
|
|
144
|
+
msg = groupObj.random(GT)
|
|
145
|
+
|
|
146
|
+
mykey = kpabe.keygen(pk, mk, policy)
|
|
147
|
+
|
|
148
|
+
if debug: print("Encrypt under these attributes: ", attributes)
|
|
149
|
+
ciphertext = kpabe.encrypt(pk, msg, attributes)
|
|
150
|
+
if debug: print(ciphertext)
|
|
151
|
+
|
|
152
|
+
rec_msg = kpabe.decrypt(ciphertext, mykey)
|
|
153
|
+
|
|
154
|
+
assert msg == rec_msg
|
|
155
|
+
if debug: print("Successful Decryption!")
|
|
156
|
+
|
|
157
|
+
if __name__ == "__main__":
|
|
158
|
+
debug = True
|
|
159
|
+
main()
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
'''
|
|
2
|
+
**Multi-Authority Attribute-Based Encryption (RW15)**
|
|
3
|
+
|
|
4
|
+
*Authors:* Yannis Rouselakis, Brent Waters
|
|
5
|
+
|
|
6
|
+
| **Title:** "Efficient Statically-Secure Large-Universe Multi-Authority Attribute-Based Encryption"
|
|
7
|
+
| **Published in:** Financial Cryptography and Data Security, 2015
|
|
8
|
+
| **Available from:** http://eprint.iacr.org/2015/016.pdf
|
|
9
|
+
| **Notes:** Implementation based on maabe_rw12.py (https://sites.google.com/site/yannisrouselakis/rwabe)
|
|
10
|
+
|
|
11
|
+
.. rubric:: Scheme Properties
|
|
12
|
+
|
|
13
|
+
* **Type:** multi-authority attribute-based encryption (public key)
|
|
14
|
+
* **Setting:** Bilinear pairing group of prime order
|
|
15
|
+
* **Assumption:** Complex q-type assumption
|
|
16
|
+
|
|
17
|
+
.. rubric:: Implementation
|
|
18
|
+
|
|
19
|
+
:Authors: Yannis Rouselakis
|
|
20
|
+
:Date: 11/2012
|
|
21
|
+
'''
|
|
22
|
+
|
|
23
|
+
from charm.toolbox.pairinggroup import *
|
|
24
|
+
from charm.toolbox.secretutil import SecretUtil
|
|
25
|
+
from charm.toolbox.ABEncMultiAuth import ABEncMultiAuth
|
|
26
|
+
import re
|
|
27
|
+
|
|
28
|
+
debug = False
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def merge_dicts(*dict_args):
|
|
32
|
+
"""
|
|
33
|
+
Given any number of dicts, shallow copy and merge into a new dict,
|
|
34
|
+
precedence goes to key value pairs in latter dicts.
|
|
35
|
+
"""
|
|
36
|
+
result = {}
|
|
37
|
+
for dictionary in dict_args:
|
|
38
|
+
result.update(dictionary)
|
|
39
|
+
return result
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class MaabeRW15(ABEncMultiAuth):
|
|
43
|
+
"""
|
|
44
|
+
Efficient Statically-Secure Large-Universe Multi-Authority Attribute-Based Encryption
|
|
45
|
+
Rouselakis - Waters
|
|
46
|
+
|
|
47
|
+
>>> group = PairingGroup('SS512')
|
|
48
|
+
>>> maabe = MaabeRW15(group)
|
|
49
|
+
>>> public_parameters = maabe.setup()
|
|
50
|
+
|
|
51
|
+
Setup the attribute authorities
|
|
52
|
+
>>> attributes1 = ['ONE', 'TWO']
|
|
53
|
+
>>> attributes2 = ['THREE', 'FOUR']
|
|
54
|
+
>>> (public_key1, secret_key1) = maabe.authsetup(public_parameters, 'UT')
|
|
55
|
+
>>> (public_key2, secret_key2) = maabe.authsetup(public_parameters, 'OU')
|
|
56
|
+
>>> public_keys = {'UT': public_key1, 'OU': public_key2}
|
|
57
|
+
|
|
58
|
+
Setup a user and give him some keys
|
|
59
|
+
>>> gid = "bob"
|
|
60
|
+
>>> user_attributes1 = ['STUDENT@UT', 'PHD@UT']
|
|
61
|
+
>>> user_attributes2 = ['STUDENT@OU']
|
|
62
|
+
>>> user_keys1 = maabe.multiple_attributes_keygen(public_parameters, secret_key1, gid, user_attributes1)
|
|
63
|
+
>>> user_keys2 = maabe.multiple_attributes_keygen(public_parameters, secret_key2, gid, user_attributes2)
|
|
64
|
+
>>> user_keys = {'GID': gid, 'keys': merge_dicts(user_keys1, user_keys2)}
|
|
65
|
+
|
|
66
|
+
Create a random message
|
|
67
|
+
>>> message = group.random(GT)
|
|
68
|
+
|
|
69
|
+
Encrypt the message
|
|
70
|
+
>>> access_policy = '(STUDENT@UT or PROFESSOR@OU) and (STUDENT@UT or MASTERS@OU)'
|
|
71
|
+
>>> cipher_text = maabe.encrypt(public_parameters, public_keys, message, access_policy)
|
|
72
|
+
|
|
73
|
+
Decrypt the message
|
|
74
|
+
>>> decrypted_message = maabe.decrypt(public_parameters, user_keys, cipher_text)
|
|
75
|
+
>>> decrypted_message == message
|
|
76
|
+
True
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
def __init__(self, group, verbose=False):
|
|
80
|
+
ABEncMultiAuth.__init__(self)
|
|
81
|
+
self.group = group
|
|
82
|
+
self.util = SecretUtil(group, verbose)
|
|
83
|
+
|
|
84
|
+
def setup(self):
|
|
85
|
+
g1 = self.group.random(G1)
|
|
86
|
+
g2 = self.group.random(G2)
|
|
87
|
+
egg = pair(g1, g2)
|
|
88
|
+
H = lambda x: self.group.hash(x, G2)
|
|
89
|
+
F = lambda x: self.group.hash(x, G2)
|
|
90
|
+
gp = {'g1': g1, 'g2': g2, 'egg': egg, 'H': H, 'F': F}
|
|
91
|
+
if debug:
|
|
92
|
+
print("Setup")
|
|
93
|
+
print(gp)
|
|
94
|
+
return gp
|
|
95
|
+
|
|
96
|
+
def unpack_attribute(self, attribute):
|
|
97
|
+
"""
|
|
98
|
+
Unpacks an attribute in attribute name, authority name and index
|
|
99
|
+
:param attribute: The attribute to unpack
|
|
100
|
+
:return: The attribute name, authority name and the attribute index, if present.
|
|
101
|
+
|
|
102
|
+
>>> group = PairingGroup('SS512')
|
|
103
|
+
>>> maabe = MaabeRW15(group)
|
|
104
|
+
>>> maabe.unpack_attribute('STUDENT@UT')
|
|
105
|
+
('STUDENT', 'UT', None)
|
|
106
|
+
>>> maabe.unpack_attribute('STUDENT@UT_2')
|
|
107
|
+
('STUDENT', 'UT', '2')
|
|
108
|
+
"""
|
|
109
|
+
parts = re.split(r"[@_]", attribute)
|
|
110
|
+
assert len(parts) > 1, "No @ char in [attribute@authority] name"
|
|
111
|
+
return parts[0], parts[1], None if len(parts) < 3 else parts[2]
|
|
112
|
+
|
|
113
|
+
def authsetup(self, gp, name):
|
|
114
|
+
"""
|
|
115
|
+
Setup an attribute authority.
|
|
116
|
+
:param gp: The global parameters
|
|
117
|
+
:param name: The name of the authority
|
|
118
|
+
:return: The public and private key of the authority
|
|
119
|
+
"""
|
|
120
|
+
alpha, y = self.group.random(), self.group.random()
|
|
121
|
+
egga = gp['egg'] ** alpha
|
|
122
|
+
gy = gp['g1'] ** y
|
|
123
|
+
pk = {'name': name, 'egga': egga, 'gy': gy}
|
|
124
|
+
sk = {'name': name, 'alpha': alpha, 'y': y}
|
|
125
|
+
if debug:
|
|
126
|
+
print("Authsetup: %s" % name)
|
|
127
|
+
print(pk)
|
|
128
|
+
print(sk)
|
|
129
|
+
return pk, sk
|
|
130
|
+
|
|
131
|
+
def keygen(self, gp, sk, gid, attribute):
|
|
132
|
+
"""
|
|
133
|
+
Generate a user secret key for the attribute.
|
|
134
|
+
:param gp: The global parameters.
|
|
135
|
+
:param sk: The secret key of the attribute authority.
|
|
136
|
+
:param gid: The global user identifier.
|
|
137
|
+
:param attribute: The attribute.
|
|
138
|
+
:return: The secret key for the attribute for the user with identifier gid.
|
|
139
|
+
"""
|
|
140
|
+
_, auth, _ = self.unpack_attribute(attribute)
|
|
141
|
+
assert sk['name'] == auth, "Attribute %s does not belong to authority %s" % (attribute, sk['name'])
|
|
142
|
+
|
|
143
|
+
t = self.group.random()
|
|
144
|
+
K = gp['g2'] ** sk['alpha'] * gp['H'](gid) ** sk['y'] * gp['F'](attribute) ** t
|
|
145
|
+
KP = gp['g1'] ** t
|
|
146
|
+
if debug:
|
|
147
|
+
print("Keygen")
|
|
148
|
+
print("User: %s, Attribute: %s" % (gid, attribute))
|
|
149
|
+
print({'K': K, 'KP': KP})
|
|
150
|
+
return {'K': K, 'KP': KP}
|
|
151
|
+
|
|
152
|
+
def multiple_attributes_keygen(self, gp, sk, gid, attributes):
|
|
153
|
+
"""
|
|
154
|
+
Generate a dictionary of secret keys for a user for a list of attributes.
|
|
155
|
+
:param gp: The global parameters.
|
|
156
|
+
:param sk: The secret key of the attribute authority.
|
|
157
|
+
:param gid: The global user identifier.
|
|
158
|
+
:param attributes: The list of attributes.
|
|
159
|
+
:return: A dictionary with attribute names as keys, and secret keys for the attributes as values.
|
|
160
|
+
"""
|
|
161
|
+
uk = {}
|
|
162
|
+
for attribute in attributes:
|
|
163
|
+
uk[attribute] = self.keygen(gp, sk, gid, attribute)
|
|
164
|
+
return uk
|
|
165
|
+
|
|
166
|
+
def encrypt(self, gp, pks, message, policy_str):
|
|
167
|
+
"""
|
|
168
|
+
Encrypt a message under an access policy
|
|
169
|
+
:param gp: The global parameters.
|
|
170
|
+
:param pks: The public keys of the relevant attribute authorities, as dict from authority name to public key.
|
|
171
|
+
:param message: The message to encrypt.
|
|
172
|
+
:param policy_str: The access policy to use.
|
|
173
|
+
:return: The encrypted message.
|
|
174
|
+
"""
|
|
175
|
+
s = self.group.random() # secret to be shared
|
|
176
|
+
w = self.group.init(ZR, 0) # 0 to be shared
|
|
177
|
+
|
|
178
|
+
policy = self.util.createPolicy(policy_str)
|
|
179
|
+
attribute_list = self.util.getAttributeList(policy)
|
|
180
|
+
|
|
181
|
+
secret_shares = self.util.calculateSharesDict(s, policy) # These are correctly set to be exponents in Z_p
|
|
182
|
+
zero_shares = self.util.calculateSharesDict(w, policy)
|
|
183
|
+
|
|
184
|
+
C0 = message * (gp['egg'] ** s)
|
|
185
|
+
C1, C2, C3, C4 = {}, {}, {}, {}
|
|
186
|
+
for i in attribute_list:
|
|
187
|
+
attribute_name, auth, _ = self.unpack_attribute(i)
|
|
188
|
+
attr = "%s@%s" % (attribute_name, auth)
|
|
189
|
+
tx = self.group.random()
|
|
190
|
+
C1[i] = gp['egg'] ** secret_shares[i] * pks[auth]['egga'] ** tx
|
|
191
|
+
C2[i] = gp['g1'] ** (-tx)
|
|
192
|
+
C3[i] = pks[auth]['gy'] ** tx * gp['g1'] ** zero_shares[i]
|
|
193
|
+
C4[i] = gp['F'](attr) ** tx
|
|
194
|
+
if debug:
|
|
195
|
+
print("Encrypt")
|
|
196
|
+
print(message)
|
|
197
|
+
print({'policy': policy_str, 'C0': C0, 'C1': C1, 'C2': C2, 'C3': C3, 'C4': C4})
|
|
198
|
+
return {'policy': policy_str, 'C0': C0, 'C1': C1, 'C2': C2, 'C3': C3, 'C4': C4}
|
|
199
|
+
|
|
200
|
+
def decrypt(self, gp, sk, ct):
|
|
201
|
+
"""
|
|
202
|
+
Decrypt the ciphertext using the secret keys of the user.
|
|
203
|
+
:param gp: The global parameters.
|
|
204
|
+
:param sk: The secret keys of the user.
|
|
205
|
+
:param ct: The ciphertext to decrypt.
|
|
206
|
+
:return: The decrypted message.
|
|
207
|
+
:raise Exception: When the access policy can not be satisfied with the user's attributes.
|
|
208
|
+
"""
|
|
209
|
+
policy = self.util.createPolicy(ct['policy'])
|
|
210
|
+
coefficients = self.util.getCoefficients(policy)
|
|
211
|
+
pruned_list = self.util.prune(policy, sk['keys'].keys())
|
|
212
|
+
|
|
213
|
+
if not pruned_list:
|
|
214
|
+
raise Exception("You don't have the required attributes for decryption!")
|
|
215
|
+
|
|
216
|
+
B = self.group.init(GT, 1)
|
|
217
|
+
for i in range(len(pruned_list)):
|
|
218
|
+
x = pruned_list[i].getAttribute() # without the underscore
|
|
219
|
+
y = pruned_list[i].getAttributeAndIndex() # with the underscore
|
|
220
|
+
B *= (ct['C1'][y] * pair(ct['C2'][y], sk['keys'][x]['K']) * pair(ct['C3'][y], gp['H'](sk['GID'])) * pair(
|
|
221
|
+
sk['keys'][x]['KP'], ct['C4'][y])) ** coefficients[y]
|
|
222
|
+
if debug:
|
|
223
|
+
print("Decrypt")
|
|
224
|
+
print("SK:")
|
|
225
|
+
print(sk)
|
|
226
|
+
print("Decrypted Message:")
|
|
227
|
+
print(ct['C0'] / B)
|
|
228
|
+
return ct['C0'] / B
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
if __name__ == '__main__':
|
|
232
|
+
debug = True
|
|
233
|
+
|
|
234
|
+
import doctest
|
|
235
|
+
|
|
236
|
+
doctest.testmod()
|