'''
Brent Waters (Pairing-based)
| From: "Ciphertext-Policy Attribute-Based Encryption: An Expressive, Efficient, and Provably Secure Realization", Appendix C.
| Published in: 2008
| Available from: http://eprint.iacr.org/2008/290.pdf
| Notes: Security Assumption: parallel q-DBDHE. The sole disadvantage of this scheme is the high number of pairings
| that must be computed during the decryption process (2 + N) for N attributes mathing in the key.
* type: ciphertext-policy attribute-based encryption (public key)
* setting: Pairing
:Authors: J Ayo Akinyele
:Date: 11/2010
'''
from charm.toolbox.pairinggroup import PairingGroup,ZR,G1,G2,GT,pair
from charm.toolbox.secretutil import SecretUtil
from charm.toolbox.ABEnc import ABEnc
debug = False
[docs]class CPabe09(ABEnc):
"""
>>> from charm.toolbox.pairinggroup import PairingGroup,GT
>>> group = PairingGroup('SS512')
>>> cpabe = CPabe09(group)
>>> msg = group.random(GT)
>>> (master_secret_key, master_public_key) = cpabe.setup()
>>> policy = '((ONE or THREE) and (TWO or FOUR))'
>>> attr_list = ['THREE', 'ONE', 'TWO']
>>> secret_key = cpabe.keygen(master_public_key, master_secret_key, attr_list)
>>> cipher_text = cpabe.encrypt(master_public_key, msg, policy)
>>> decrypted_msg = cpabe.decrypt(master_public_key, secret_key, cipher_text)
>>> decrypted_msg == msg
True
"""
def __init__(self, groupObj):
ABEnc.__init__(self)
global util, group
util = SecretUtil(groupObj, debug)
group = groupObj
[docs] def setup(self):
g1, g2 = group.random(G1), group.random(G2)
alpha, a = group.random(), group.random()
e_gg_alpha = pair(g1,g2) ** alpha
msk = {'g1^alpha':g1 ** alpha, 'g2^alpha':g2 ** alpha}
pk = {'g1':g1, 'g2':g2, 'e(gg)^alpha':e_gg_alpha, 'g1^a':g1 ** a, 'g2^a':g2 ** a}
return (msk, pk)
[docs] def keygen(self, pk, msk, attributes):
t = group.random()
K = msk['g2^alpha'] * (pk['g2^a'] ** t)
L = pk['g2'] ** t
k_x = [group.hash(s, G1) ** t for s in attributes]
K_x = {}
for i in range(0, len(k_x)):
K_x[ attributes[i] ] = k_x[i]
key = { 'K':K, 'L':L, 'K_x':K_x, 'attributes':attributes }
return key
[docs] def encrypt(self, pk, M, policy_str):
# Extract the attributes as a list
policy = util.createPolicy(policy_str)
p_list = util.getAttributeList(policy)
s = group.random()
C_tilde = (pk['e(gg)^alpha'] ** s) * M
C_0 = pk['g1'] ** s
C, D = {}, {}
secret = s
shares = util.calculateSharesList(secret, policy)
# ciphertext
for i in range(len(p_list)):
r = group.random()
if shares[i][0] == p_list[i]:
attr = shares[i][0].getAttribute()
C[ p_list[i] ] = ((pk['g1^a'] ** shares[i][1]) * (group.hash(attr, G1) ** -r))
D[ p_list[i] ] = (pk['g2'] ** r)
if debug: print("SessionKey: %s" % C_tilde)
return { 'C0':C_0, 'C':C, 'D':D , 'C_tilde':C_tilde, 'policy':policy_str, 'attribute':p_list }
[docs] def decrypt(self, pk, sk, ct):
policy = util.createPolicy(ct['policy'])
pruned = util.prune(policy, sk['attributes'])
if pruned == False:
return False
coeffs = util.getCoefficients(policy)
numerator = pair(ct['C0'], sk['K'])
# create list for attributes in order...
k_x, w_i = {}, {}
for i in pruned:
j = i.getAttributeAndIndex()
k = i.getAttribute()
k_x[ j ] = sk['K_x'][k]
w_i[ j ] = coeffs[j]
#print('Attribute %s: coeff=%s, k_x=%s' % (j, w_i[j], k_x[j]))
C, D = ct['C'], ct['D']
denominator = 1
for i in pruned:
j = i.getAttributeAndIndex()
denominator *= ( pair(C[j] ** w_i[j], sk['L']) * pair(k_x[j] ** w_i[j], D[j]) )
return ct['C_tilde'] / (numerator / denominator)
[docs]def main():
#Get the eliptic curve with the bilinear mapping feature needed.
groupObj = PairingGroup('SS512')
cpabe = CPabe09(groupObj)
(msk, pk) = cpabe.setup()
pol = '((ONE or THREE) and (TWO or FOUR))'
attr_list = ['THREE', 'ONE', 'TWO']
if debug: print('Acces Policy: %s' % pol)
if debug: print('User credential list: %s' % attr_list)
m = groupObj.random(GT)
cpkey = cpabe.keygen(pk, msk, attr_list)
if debug: print("\nSecret key: %s" % attr_list)
if debug:groupObj.debug(cpkey)
cipher = cpabe.encrypt(pk, m, pol)
if debug: print("\nCiphertext...")
if debug:groupObj.debug(cipher)
orig_m = cpabe.decrypt(pk, cpkey, cipher)
assert m == orig_m, 'FAILED Decryption!!!'
if debug: print('Successful Decryption!')
del groupObj
if __name__ == '__main__':
debug = True
main()