Source code for abenc_dacmacs_yj14

'''
Kan Yang, Xiaohua Jia 
 
| From: DAC-MACS: Effective Data Access Control for Multi-Authority Cloud Storage Systems 
| Published in:  Security for Cloud Storage Systems  - SpringerBriefs in Computer Science 2014
| Available From: http://link.springer.com/chapter/10.1007/978-1-4614-7873-7_4
| 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 DACMACS(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() g_a = g ** a GPP = {'g': g, 'g_a': g_a, 'H': H} GMK = {'a': a} return (GPP, GMK)
[docs] def registerUser(self, GPP): '''Generate user keys (executed by the user).''' g = GPP['g'] u = self.group.random() z = self.group.random() g_u = g ** u g_z = g ** (1 / z) return ((g_u, z), { 'g_z': g_z, 'u': u }) # (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_inv': GPP['g'] ** (1/beta), 'g_beta_gamma': GPP['g'] ** (gamma/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 = ((GPP['g'] ** versionKey) * h) ** SK['gamma'] authAttrs[attrib] = { 'VK': versionKey, #secret 'PK': pk, #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 'L' not in USK or 'R' not in USK or 'AK' not in USK: USK['K'] = \ (u['g_z'] ** ASK['alpha']) * \ (GPP['g_a'] ** u['u']) * \ (GPP['g_a'] ** (t / ASK['beta'])) USK['L'] = u['g_z'] ** (ASK['beta'] * t) USK['R'] = GPP['g_a'] ** t USK['AK'] = {} AK = (u['g_z'] ** (ASK['beta'] * ASK['gamma'] * t)) * \ (authAttrs[attribute]['PK'] ** (ASK['beta'] * u['u'])) 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 = APK['g_beta_inv'] ** secret C = {} 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['PK'] ** r_i) D[attr] = APK['g_beta_inv'] ** r_i DS[attr] = ~(APK['g_beta_gamma'] ** r_i) return {'C1': C1, 'C2': C2, 'C3': C3, 'C': C, 'D': D, 'DS': DS, 'policy': policy_str}
[docs] def generateTK(self, GPP, CT, UASK, g_u): '''Generates a token using the user's attribute secret keys to offload the decryption process (executed by cloud provider)''' 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) dividend = pair(CT['C2'], UASK['K']) * ~pair(UASK['R'], CT['C3']) n_a = 1 divisor = 1 for attr in pruned: x = attr.getAttributeAndIndex() y = attr.getAttribute() temp = \ pair(CT['C'][y], g_u) * \ pair(CT['D'][y], UASK['AK'][y]) * \ pair(CT['DS'][y], UASK['L']) divisor *= temp ** (coeffs[x] * n_a) return dividend / divisor
[docs] def decrypt(self, CT, TK, z): '''Decrypts the content(-key) from the cipher-text using the token and the user secret key (executed by user/content consumer)''' return CT['C1'] / (TK ** z)
[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 = userObj['u'] AUK = ASK['gamma'] * (newVersionKey - oldVersionKey) KUK = GPP['g'] ** (u * ASK['beta'] * AUK) CUK = ASK['beta'] * AUK / ASK['gamma'] authAttrs[attribute]['PK'] = authAttrs[attribute]['PK'] * (GPP['g'] ** AUK) return { 'KUK': KUK, 'CUK': CUK }
[docs] def skupdate(self, USK, attribute, KUK): '''Updates the user attribute secret key for the specified attribute (executed by non-revoked user)''' USK['AK'][attribute] = USK['AK'][attribute] * KUK
[docs] def ctupdate(self, GPP, CT, attribute, CUK): '''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] ** CUK)
[docs]def basicTest(): print("RUN basicTest") groupObj = PairingGroup('SS512') dac = DACMACS(groupObj) GPP, GMK = dac.setup() users = {} # public user data authorities = {} authorityAttributes = ["ONE", "TWO", "THREE", "FOUR"] authority1 = "authority1" dac.setupAuthority(GPP, authority1, authorityAttributes, authorities) alice = { 'id': 'alice', 'authoritySecretKeys': {}, 'keys': None } alice['keys'], users[alice['id']] = dac.registerUser(GPP) for attr in authorityAttributes[0:-1]: dac.keygen(GPP, authorities[authority1], attr, users[alice['id']], alice['authoritySecretKeys']) k = groupObj.random(GT) policy_str = '((ONE or THREE) and (TWO or FOUR))' CT = dac.encrypt(GPP, policy_str, k, authorities[authority1]) TK = dac.generateTK(GPP, CT, alice['authoritySecretKeys'], alice['keys'][0]) PT = dac.decrypt(CT, TK, alice['keys'][1]) # print "k", k # print "PT", PT assert k == PT, 'FAILED DECRYPTION!' print('SUCCESSFUL DECRYPTION')
[docs]def revokedTest(): print("RUN revokedTest") groupObj = PairingGroup('SS512') dac = DACMACS(groupObj) GPP, GMK = dac.setup() users = {} # public user data authorities = {} authorityAttributes = ["ONE", "TWO", "THREE", "FOUR"] authority1 = "authority1" dac.setupAuthority(GPP, authority1, authorityAttributes, authorities) alice = { 'id': 'alice', 'authoritySecretKeys': {}, 'keys': None } alice['keys'], users[alice['id']] = dac.registerUser(GPP) bob = { 'id': 'bob', 'authoritySecretKeys': {}, 'keys': None } bob['keys'], users[bob['id']] = dac.registerUser(GPP) for attr in authorityAttributes[0:-1]: dac.keygen(GPP, authorities[authority1], attr, users[alice['id']], alice['authoritySecretKeys']) dac.keygen(GPP, authorities[authority1], attr, users[bob['id']], bob['authoritySecretKeys']) k = groupObj.random(GT) policy_str = '((ONE or THREE) and (TWO or FOUR))' CT = dac.encrypt(GPP, policy_str, k, authorities[authority1]) TK1a = dac.generateTK(GPP, CT, alice['authoritySecretKeys'], alice['keys'][0]) PT1a = dac.decrypt(CT, TK1a, alice['keys'][1]) TK1b = dac.generateTK(GPP, CT, bob['authoritySecretKeys'], bob['keys'][0]) PT1b = dac.decrypt(CT, TK1b, bob['keys'][1]) assert k == PT1a, 'FAILED DECRYPTION (1a)!' assert k == PT1b, 'FAILED DECRYPTION (1b)!' print('SUCCESSFUL DECRYPTION 1') # revoke bob on "ONE" attribute = "ONE" UK = dac.ukeygen(GPP, authorities[authority1], attribute, users[alice['id']]) dac.skupdate(alice['authoritySecretKeys'], attribute, UK['KUK']) dac.ctupdate(GPP, CT, attribute, UK['CUK']) TK2a = dac.generateTK(GPP, CT, alice['authoritySecretKeys'], alice['keys'][0]) PT2a = dac.decrypt(CT, TK2a, alice['keys'][1]) TK2b = dac.generateTK(GPP, CT, bob['authoritySecretKeys'], bob['keys'][0]) PT2b = dac.decrypt(CT, TK2b, bob['keys'][1]) 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()