Source code for abenc_maabe_yj14

'''
Kan Yang, Xiaohua Jia 
 
| From: Expressive, Efficient, and Revocable Data Access Control for Multi-Authority Cloud Storage 
| Published in: Parallel and Distributed Systems, IEEE Transactions on  (Volume: 25,  Issue: 7) 
| Available From: http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=6620875
| Notes: 

* type:      ciphertext-policy attribute-based encryption (public key)
* setting:   Pairing

:Authors:	artjomb
:Date:		07/2014
'''

from charm.toolbox.pairinggroup import PairingGroup,ZR,G1,GT,pair
from charm.toolbox.secretutil import SecretUtil
from charm.toolbox.ABEncMultiAuth import ABEncMultiAuth

[docs]class MAABE(object): def __init__(self, groupObj): self.util = SecretUtil(groupObj, verbose=False) #Create Secret Sharing Scheme self.group = groupObj #:Prime order group
[docs] def setup(self): '''Global Setup (executed by CA)''' #:In global setup, a bilinear group G of prime order p is chosen #: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 #:group contains #:the prime order p is contained somewhere within the group object g = self.group.random(G1) #: The oracle that maps global identities GID onto elements of G #:H = lambda str: g** group.hash(str) H = lambda x: self.group.hash(x, G1) a = self.group.random() b = self.group.random() g_a = g ** a g_b = g ** b GPP = {'g': g, 'g_a': g_a, 'g_b': g_b, 'H': H} GMK = {'a': a, 'b': b} return (GPP, GMK)
[docs] def registerUser(self, GPP): '''Generate user keys (executed by the user).''' g = GPP['g'] ugsk1 = self.group.random() ugsk2 = self.group.random() ugpk1 = g ** ugsk1 ugpk2 = g ** ugsk2 return ((ugpk1, ugsk2), { 'pk': ugpk2, 'sk': ugsk1 }) # (private, public)
[docs] def setupAuthority(self, GPP, authorityid, attributes, authorities): '''Generate attribute authority keys (executed by attribute authority)''' if authorityid not in authorities: alpha = self.group.random() beta = self.group.random() gamma = self.group.random() SK = {'alpha': alpha, 'beta': beta, 'gamma': gamma} PK = { 'e_alpha': pair(GPP['g'], GPP['g']) ** alpha, 'g_beta': GPP['g'] ** beta, 'g_beta_inv': GPP['g'] ** ~beta } authAttrs = {} authorities[authorityid] = (SK, PK, authAttrs) else: SK, PK, authAttrs = authorities[authorityid] for attrib in attributes: if attrib in authAttrs: continue versionKey = self.group.random() # random or really 'choose' ? h = GPP['H'](attrib) pk = h ** versionKey authAttrs[attrib] = { 'VK': versionKey, #secret 'PK1': pk, #public 'PK2': pk ** SK['gamma'] #public } return (SK, PK, authAttrs)
[docs] def keygen(self, GPP, authority, attribute, userObj, USK = None): '''Generate user keys for a specific attribute (executed on attribute authority)''' if 't' not in userObj: userObj['t'] = self.group.random() #private to AA t = userObj['t'] ASK, APK, authAttrs = authority u = userObj if USK is None: USK = {} if 'K' not in USK or 'KS' not in USK or 'AK' not in USK: USK['K'] = \ (GPP['g'] ** ASK['alpha']) * \ (GPP['g_a'] ** u['sk']) * \ (GPP['g_b'] ** t) USK['KS'] = GPP['g'] ** t USK['AK'] = {} AK = (u['pk'] ** (t * ASK['beta'])) * \ ((authAttrs[attribute]['PK1'] ** ASK['beta']) ** (u['sk'] + ASK['gamma'])) USK['AK'][attribute] = AK return USK
[docs] def encrypt(self, GPP, policy_str, k, authority): '''Generate the cipher-text from the content(-key) and a policy (executed by the content owner)''' #GPP are global parameters #k is the content key (group element based on AES key) #policy_str is the policy string #authority is the authority tuple _, APK, authAttrs = authority policy = self.util.createPolicy(policy_str) secret = self.group.random() shares = self.util.calculateSharesList(secret, policy) shares = dict([(x[0].getAttributeAndIndex(), x[1]) for x in shares]) C1 = k * (APK['e_alpha'] ** secret) C2 = GPP['g'] ** secret C3 = GPP['g_b'] ** secret C = {} CS = {} D = {} DS = {} for attr, s_share in shares.items(): k_attr = self.util.strip_index(attr) r_i = self.group.random() attrPK = authAttrs[attr] C[attr] = (GPP['g_a'] ** s_share) * ~(attrPK['PK1'] ** r_i) CS[attr] = GPP['g'] ** r_i D[attr] = APK['g_beta_inv'] ** r_i DS[attr] = attrPK['PK2'] ** r_i return {'C1': C1, 'C2': C2, 'C3': C3, 'C': C, 'CS': CS, 'D': D, 'DS': DS, 'policy': policy_str}
[docs] def decrypt(self, GPP, CT, user): '''Decrypts the content(-key) from the cipher-text (executed by user/content consumer)''' UASK = user['authoritySecretKeys'] USK = user['keys'] usr_attribs = list(UASK['AK'].keys()) policy = self.util.createPolicy(CT['policy']) pruned = self.util.prune(policy, usr_attribs) if pruned == False: return False coeffs = self.util.getCoefficients(policy) first = pair(CT['C2'], UASK['K']) * ~pair(CT['C3'], UASK['KS']) n_a = 1 ugpk1, ugsk2 = USK e_gg_auns = 1 for attr in pruned: x = attr.getAttributeAndIndex() y = attr.getAttribute() temp = \ pair(CT['C'][y], ugpk1) * \ pair(CT['D'][y], UASK['AK'][y]) * \ pair(CT['CS'][y], ~(UASK['KS'] ** ugsk2)) * \ ~pair(GPP['g'], CT['DS'][y]) e_gg_auns *= temp ** (coeffs[x] * n_a) return CT['C1'] / (first / e_gg_auns)
[docs] def ukeygen(self, GPP, authority, attribute, userObj): '''Generate update keys for users and cloud provider (executed by attribute authority?)''' ASK, _, authAttrs = authority oldVersionKey = authAttrs[attribute]['VK'] newVersionKey = oldVersionKey while oldVersionKey == newVersionKey: newVersionKey = self.group.random() authAttrs[attribute]['VK'] = newVersionKey u_uid = userObj['sk'] UKs = GPP['H'](attribute) ** (ASK['beta'] * (newVersionKey - oldVersionKey) * (u_uid + ASK['gamma'])) UKc = (newVersionKey/oldVersionKey, (oldVersionKey - newVersionKey)/(oldVersionKey * ASK['gamma'])) authAttrs[attribute]['PK1'] = authAttrs[attribute]['PK1'] ** UKc[0] authAttrs[attribute]['PK2'] = authAttrs[attribute]['PK2'] ** UKc[0] return { 'UKs': UKs, 'UKc': UKc }
[docs] def skupdate(self, USK, attribute, UKs): '''Updates the user attribute secret key for the specified attribute (executed by non-revoked user)''' USK['AK'][attribute] = USK['AK'][attribute] * UKs
[docs] def ctupdate(self, GPP, CT, attribute, UKc): '''Updates the cipher-text using the update key, because of the revoked attribute (executed by cloud provider)''' CT['C'][attribute] = CT['C'][attribute] * (CT['DS'][attribute] ** UKc[1]) CT['DS'][attribute] = CT['DS'][attribute] ** UKc[0]
[docs]def basicTest(): print("RUN basicTest") groupObj = PairingGroup('SS512') maabe = MAABE(groupObj) GPP, GMK = maabe.setup() users = {} # public user data authorities = {} authorityAttributes = ["ONE", "TWO", "THREE", "FOUR"] authority1 = "authority1" maabe.setupAuthority(GPP, authority1, authorityAttributes, authorities) alice = { 'id': 'alice', 'authoritySecretKeys': {}, 'keys': None } alice['keys'], users[alice['id']] = maabe.registerUser(GPP) for attr in authorityAttributes[0:-1]: maabe.keygen(GPP, authorities[authority1], attr, users[alice['id']], alice['authoritySecretKeys']) k = groupObj.random(GT) policy_str = '((ONE or THREE) and (TWO or FOUR))' CT = maabe.encrypt(GPP, policy_str, k, authorities[authority1]) PT = maabe.decrypt(GPP, CT, alice) # print "k", k # print "PT", PT assert k == PT, 'FAILED DECRYPTION!' print('SUCCESSFUL DECRYPTION')
[docs]def revokedTest(): print("RUN revokedTest") groupObj = PairingGroup('SS512') maabe = MAABE(groupObj) GPP, GMK = maabe.setup() users = {} # public user data authorities = {} authorityAttributes = ["ONE", "TWO", "THREE", "FOUR"] authority1 = "authority1" maabe.setupAuthority(GPP, authority1, authorityAttributes, authorities) alice = { 'id': 'alice', 'authoritySecretKeys': {}, 'keys': None } alice['keys'], users[alice['id']] = maabe.registerUser(GPP) bob = { 'id': 'bob', 'authoritySecretKeys': {}, 'keys': None } bob['keys'], users[bob['id']] = maabe.registerUser(GPP) for attr in authorityAttributes[0:-1]: maabe.keygen(GPP, authorities[authority1], attr, users[alice['id']], alice['authoritySecretKeys']) maabe.keygen(GPP, authorities[authority1], attr, users[bob['id']], bob['authoritySecretKeys']) k = groupObj.random(GT) policy_str = '((ONE or THREE) and (TWO or FOUR))' CT = maabe.encrypt(GPP, policy_str, k, authorities[authority1]) PT1a = maabe.decrypt(GPP, CT, alice) PT1b = maabe.decrypt(GPP, CT, bob) assert k == PT1a, 'FAILED DECRYPTION (1a)!' assert k == PT1b, 'FAILED DECRYPTION (1b)!' print('SUCCESSFUL DECRYPTION 1') # revoke bob on "ONE" attribute = "ONE" UK = maabe.ukeygen(GPP, authorities[authority1], attribute, users[alice['id']]) maabe.skupdate(alice['authoritySecretKeys'], attribute, UK['UKs']) maabe.ctupdate(GPP, CT, attribute, UK['UKc']) PT2a = maabe.decrypt(GPP, CT, alice) PT2b = maabe.decrypt(GPP, CT, bob) assert k == PT2a, 'FAILED DECRYPTION (2a)!' assert k != PT2b, 'SUCCESSFUL DECRYPTION (2b)!' print('SUCCESSFUL DECRYPTION 2')
[docs]def test(): groupObj = PairingGroup('SS512')
# k = groupObj.random() #print "k", k, ~k, k * ~k # g = groupObj.random(G1) # print "g", g, pair(g, g) # gt = groupObj.random(GT) # print "gt", gt if __name__ == '__main__': basicTest() revokedTest() # test()