def decrypt(ik, sk, ct, pk=None): group = PairingGroup('SS512') if pk is None: pk = getPK(stsConfig['TS_ip'],stsConfig['api_getPK']) if type(pk['g']) == type(''): pk = dictToObject(pk_dict=pk, group=group) if type(ct['C0']) == type(''): ct = dictToObject(ct_dict=ct) if type(ik['K0']) == type(''): ik = dictToObject(ik_dict=ik) if type(sk) == type(''): sk = dictToObject(pairingElement_dict=sk) group = PairingGroup('SS512') util = SecretUtil(group, False) w = pk['w'] u = pk['u'] S = ik['S'] #['THREE', 'ONE', 'TWO'] K0 = ik['K0'] K1 = ik['K1'] Kj2 = ik['Ki2'] Kj3 = ik['Ki3'] C0 = ct['C0'] Ci1 = ct['C_j_1'] Ci2 = ct['C_j_2'] Ci3 = ct['C_j_3'] Ci4 = ct['C_j_4'] Ci5 = ct['C_j_5'] policy = util.createPolicy(ct['policy']) #((ONE or THREE) and (TWO or FOUR)) print('access policy of this file :', policy) try: pruned = util.prune(policy, S) #[ONE, TWO] except Exception,e: raise Exception('your attributes do not satisfy the policy!')
def predecrypt(pk, ik, ct): group = PairingGroup('SS512') util = SecretUtil(group, debug) w = pk['w'] u = pk['u'] S = ik['S'] #['THREE', 'ONE', 'TWO'] K0 = ik['K0'] K1 = ik['K1'] Kj2 = ik['Ki2'] Kj3 = ik['Ki3'] C0 = ct['C0'] Ci1 = ct['C_j_1'] Ci2 = ct['C_j_2'] Ci3 = ct['C_j_3'] Ci4 = ct['C_j_4'] Ci5 = ct['C_j_5'] policy = util.createPolicy(ct['policy']) #((ONE or THREE) and (TWO or FOUR)) print('policy in predecrypt===', policy) print('S in predecrypt===', S) pruned = util.prune(policy, S) #[ONE, TWO] if pruned is False: raise Exception('Prune error in pre-decrypt') wi = util.getCoefficients(policy) #{u'TWO': <pairing.Element>, u'FOUR': <pairing.Element>, u'THREE': <pairing.Element>, u'ONE': <pairing.Element>} eC0K0 = pair(C0,K0) ECi4wi = 0 for each in pruned: i = each.getAttribute() ECi4wi += Ci4[i] * wi[i] ewECi4wiK1 = pair(w ** ECi4wi,K1) PIeCi1K1eCi2uCi5Kj2eCi3Kj3wi = 1 for each in pruned: j = each.getAttributeAndIndex() i = each.getAttribute() eCi1K1 = pair(Ci1[i],K1) eCi2uCi5Kj2 = pair(Ci2[i] * (u ** -Ci5[i]), Kj2[j]) eCi3Kj3 = pair(Ci3[i],Kj3[j]) PIeCi1K1eCi2uCi5Kj2eCi3Kj3wi *= (eCi1K1 * eCi2uCi5Kj2 * eCi3Kj3) ** wi[i] return objectToBytes(eC0K0/(ewECi4wiK1 * PIeCi1K1eCi2uCi5Kj2eCi3Kj3wi), group)
def encrypt(policy_str, pool, group=None): print('policy_str in ABEnc=',policy_str) if group is None: group = PairingGroup('SS512') util = SecretUtil(group, False) policy = util.createPolicy(policy_str) secret = pool.pop('s') print('policy in ABEnc=',policy) sshares = util.calculateSharesList(secret, policy) sshares = dict([(x[0].getAttributeAndIndex(), x[1]) for x in sshares]) print('sshares in ABEnc=',sshares) C0 = pool.pop('C0') C_x_1, C_x_2, C_x_3, C_x_4, C_x_5 = {},{},{},{},{} for attr, s_share in sshares.items(): component = pool['components'].pop() C_x_1[attr] = component['C_j_1'] C_x_2[attr] = component['C_j_2'] C_x_3[attr] = component['C_j_3'] C_x_4[attr] = s_share - component['lambda_prime_j'] C_x_5[attr] = component['t_j'] * (group.hash(unicode(attr),ZR) - component['x_j']) ct = {'policy':policy_str, 'C0':C0,'C_j_1':C_x_1, 'C_j_2':C_x_2, 'C_j_3':C_x_3, 'C_j_4':C_x_4, 'C_j_5':C_x_5} print('ct in ABEnc=',ct) return (pool, ct)
def __init__(self, group): ABEnc.__init__(self) self.group = group self.util = SecretUtil(self.group)
class YLLC15(ABEnc): """ Possibly a subclass of BSW07? """ def __init__(self, group): ABEnc.__init__(self) self.group = group self.util = SecretUtil(self.group) @Output(params_t, msk_t) def setup(self): g, gp = self.group.random(G1), self.group.random(G2) alpha, beta = self.group.random(ZR), self.group.random(ZR) # initialize pre-processing for generators g.initPP() gp.initPP() h = g**beta e_gg_alpha = pair(g, gp**alpha) params = {'g': g, 'g2': gp, 'h': h, 'e_gg_alpha': e_gg_alpha} msk = {'beta': beta, 'alpha': alpha} return params, msk @Input(params_t) @Output(pku_t, sku_t) def ukgen(self, params): g2 = params['g2'] x = self.group.random(ZR) pku = g2**x sku = x return pku, sku @Input(params_t, msk_t, pku_t, pku_t, [str]) # @Output(pxku_t) def proxy_keygen(self, params, msk, pkcs, pku, attribute_list): """ attributes specified in the `attribute_list` are converted to uppercase """ r1 = self.group.random(ZR) r2 = self.group.random(ZR) g = params['g'] g2 = params['g2'] k = ((pkcs**r1) * (pku**msk['alpha']) * (g2**r2))**~msk['beta'] k_prime = g2**r1 k_attrs = {} for attr in attribute_list: attr_caps = attr.upper() r_attr = self.group.random(ZR) k_attr1 = (g2**r2) * (self.group.hash(str(attr_caps), G2)**r_attr) k_attr2 = g**r_attr k_attrs[attr_caps] = (k_attr1, k_attr2) proxy_key_user = {'k': k, 'k_prime': k_prime, 'k_attrs': k_attrs} return proxy_key_user @Input(params_t, GT, str) # @Output(ct_t) def encrypt(self, params, msg, policy_str): """ Encrypt a message M under a policy string. attributes specified in policy_str are converted to uppercase policy_str must use parentheses e.g. (A) and (B) """ policy = self.util.createPolicy(policy_str) s = self.group.random(ZR) shares = self.util.calculateSharesDict(s, policy) C = (params['e_gg_alpha']**s) * msg c_prime = params['h']**s c_prime_prime = params['g']**s c_attrs = {} for attr in shares.keys(): attr_stripped = self.util.strip_index(attr) c_i1 = params['g']**shares[attr] c_i2 = self.group.hash(attr_stripped, G1)**shares[attr] c_attrs[attr] = (c_i1, c_i2) ciphertext = { 'policy_str': policy_str, 'C': C, 'C_prime': c_prime, 'C_prime_prime': c_prime_prime, 'c_attrs': c_attrs } return ciphertext # @Input(sku_t, pxku_t, ct_t) @Output(v_t) def proxy_decrypt(self, skcs, proxy_key_user, ciphertext): policy_root_node = ciphertext['policy_str'] k = proxy_key_user['k'] k_prime = proxy_key_user['k_prime'] c_prime = ciphertext['C_prime'] c_prime_prime = ciphertext['C_prime_prime'] c_attrs = ciphertext['c_attrs'] k_attrs = proxy_key_user['k_attrs'] policy = self.util.createPolicy(policy_root_node) attributes = proxy_key_user['k_attrs'].keys() pruned_list = self.util.prune(policy, attributes) if not pruned_list: return None z = self.util.getCoefficients(policy) # reconstitute the policy random secret (A) which was used to encrypt the message A = 1 for i in pruned_list: attr_idx = i.getAttributeAndIndex() attr = i.getAttribute() A *= (pair(c_attrs[attr_idx][0], k_attrs[attr][0]) / pair(k_attrs[attr][1], c_attrs[attr_idx][1]))**z[attr_idx] e_k_c_prime = pair(k, c_prime) denominator = (pair(k_prime, c_prime_prime)**skcs) * A encrypted_element_for_user_pkenc_scheme = e_k_c_prime / denominator intermediate_value = { 'C': ciphertext['C'], 'e_term': encrypted_element_for_user_pkenc_scheme } return intermediate_value @Input(type(None), sku_t, v_t) @Output(GT) def decrypt(self, params, sku, intermediate_value): """ :param params: Not required - pass None instead. For interface compatibility only. :param sku: the secret key of the user as generated by `ukgen()`. :param intermediate_value: the partially decrypted ciphertext returned by `proxy_decrypt()`. :return: the plaintext message """ ciphertext = intermediate_value['C'] e_term = intermediate_value['e_term'] denominator = e_term**(sku**-1) msg = ciphertext / denominator return msg
def __init__(self, groupObj, verbose=False): ABEnc.__init__(self) global group, util group = groupObj util = SecretUtil(group, verbose)
def __init__(self, groupObj): ABEnc.__init__(self) global util, group util = SecretUtil(groupObj, verbose=False) group = groupObj
def __init__(self, groupObj): global util, group util = SecretUtil(groupObj, debug) self.group = groupObj
def __init__(self, groupObj): self.util = SecretUtil(groupObj, verbose=False) #Create Secret Sharing Scheme self.group = groupObj #:Prime order group
def __init__(self, group, verbose=False): ABEncMultiAuth.__init__(self) self.group = group self.util = SecretUtil(group, verbose)
class MaabeRW15(ABEncMultiAuth): """ Efficient Statically-Secure Large-Universe Multi-Authority Attribute-Based Encryption Rouselakis - Waters """ def __init__(self, group, verbose=False): ABEncMultiAuth.__init__(self) self.group = group self.util = SecretUtil(group, verbose) def H(self, x): return self.group.hash(x, G2) def F(self, x): return self.group.hash(x, G2) def setup(self): g1 = self.group.random(G1) g2 = self.group.random(G2) egg = pair(g1, g2) gp = {'g1': g1, 'g2': g2, 'egg': egg} if debug: print("Setup") print(gp) return gp def unpack_attribute(self, attribute): """ Unpacks an attribute in attribute name, authority name and index :param attribute: The attribute to unpack :return: The attribute name, authority name and the attribute index, if present. group = PairingGroup('SS512') maabe = MaabeRW15(group) maabe.unpack_attribute('STUDENT@UT') ('STUDENT', 'UT', None) maabe.unpack_attribute('STUDENT@UT_2') ('STUDENT', 'UT', '2') """ parts = re.split(r"[@_]", attribute) assert len(parts) > 1, "No @ char in [attribute@authority] name" return parts[0], parts[1], None if len(parts) < 3 else parts[2] def authsetup(self, gp, name): """ Setup an attribute authority. :param gp: The global parameters :param name: The name of the authority :return: The public and private key of the authority """ alpha, y = self.group.random(), self.group.random() egga = gp['egg']**alpha gy = gp['g1']**y pk = {'name': name, 'egga': egga, 'gy': gy} sk = {'name': name, 'alpha': alpha, 'y': y} if debug: print("Authsetup: %s" % name) print(pk) print(sk) return pk, sk def keygen(self, gp, sk, gid, attribute): """ Generate a user secret key for the attribute. :param gp: The global parameters. :param sk: The secret key of the attribute authority. :param gid: The global user identifier. :param attribute: The attribute. :return: The secret key for the attribute for the user with identifier gid. """ _, auth, _ = self.unpack_attribute(attribute) assert sk[ 'name'] == auth, "Attribute %s does not belong to authority %s" % ( attribute, sk['name']) t = self.group.random() K = gp['g2']**sk['alpha'] * self.H(gid)**sk['y'] * self.F(attribute)**t KP = gp['g1']**t if debug: print("Keygen") print("User: %s, Attribute: %s" % (gid, attribute)) print({'K': K, 'KP': KP}) return {'K': K, 'KP': KP} def multiple_attributes_keygen(self, gp, sk, gid, attributes): """ Generate a dictionary of secret keys for a user for a list of attributes. :param gp: The global parameters. :param sk: The secret key of the attribute authority. :param gid: The global user identifier. :param attributes: The list of attributes. :return: A dictionary with attribute names as keys, and secret keys for the attributes as values. """ uk = {} for attribute in attributes: uk[attribute] = self.keygen(gp, sk, gid, attribute) return uk def encrypt(self, gp, pks, message, policy_str): """ Encrypt a message under an access policy :param gp: The global parameters. :param pks: The public keys of the relevant attribute authorities, as dict from authority name to public key. :param message: The message to encrypt. :param policy_str: The access policy to use. :return: The encrypted message. """ s = self.group.random() # secret to be shared w = self.group.init(ZR, 0) # 0 to be shared policy = self.util.createPolicy(policy_str) attribute_list = self.util.getAttributeList(policy) secret_shares = self.util.calculateSharesDict( s, policy) # These are correctly set to be exponents in Z_p zero_shares = self.util.calculateSharesDict(w, policy) C0 = message * (gp['egg']**s) C1, C2, C3, C4 = {}, {}, {}, {} for i in attribute_list: attribute_name, auth, _ = self.unpack_attribute(i) attr = "%s@%s" % (attribute_name, auth) tx = self.group.random() C1[i] = gp['egg']**secret_shares[i] * pks[auth]['egga']**tx C2[i] = gp['g1']**(-tx) C3[i] = pks[auth]['gy']**tx * gp['g1']**zero_shares[i] C4[i] = self.F(attr)**tx if debug: print("Encrypt") print(message) print({ 'policy': policy_str, 'C0': C0, 'C1': C1, 'C2': C2, 'C3': C3, 'C4': C4 }) return { 'policy': policy_str, 'C0': C0, 'C1': C1, 'C2': C2, 'C3': C3, 'C4': C4 } def decrypt(self, gp, sk, ct): """ Decrypt the ciphertext using the secret keys of the user. :param gp: The global parameters. :param sk: The secret keys of the user. :param ct: The ciphertext to decrypt. :return: The decrypted message. :raise Exception: When the access policy can not be satisfied with the user's attributes. """ policy = self.util.createPolicy(ct['policy']) coefficients = self.util.getCoefficients(policy) pruned_list = self.util.prune(policy, sk['keys'].keys()) if not pruned_list: raise Exception( "You don't have the required attributes for decryption!") B = self.group.init(GT, 1) for i in range(len(pruned_list)): x = pruned_list[i].getAttribute() # without the underscore y = pruned_list[i].getAttributeAndIndex() # with the underscore B *= (ct['C1'][y] * pair(ct['C2'][y], sk['keys'][x]['K']) * pair(ct['C3'][y], self.H(sk['GID'])) * pair(sk['keys'][x]['KP'], ct['C4'][y]))**coefficients[y] if debug: print("Decrypt") print("SK:") print(sk) print("Decrypted Message:") print(ct['C0'] / B) return ct['C0'] / B
def __init__(self, groupObj): ABEnc.__init__(self) global util, group util = SecretUtil(groupObj, debug) group = groupObj
def __init__(self, groupObj): ABEncMultiAuth.__init__(self) global util, group util = SecretUtil(groupObj, verbose=False) #Create Secret Sharing Scheme group = groupObj #:Prime order group
def __init__(self, group_object): # initialize class object with secret sharing utility # and appropriate group object self.util = SecretUtil(group_object, verbose=False) self.group = group_object
class OMACPABE(object): def __init__(self, group_object): # initialize class object with secret sharing utility # and appropriate group object self.util = SecretUtil(group_object, verbose=False) self.group = group_object # certificate authority (CA) setup function def abenc_casetup(self): """ Global setup function run by the CA to generate the Global Master Key (GMK) and the Global Public Parameters (GPP) :return: GMK, GPP """ # initialize bilinear group G of prime p with generator g g = self.group.random(G1) # initialize hash function that maps to an element of G H = lambda x: self.group.hash(x, G1) # select random elements from Z_p a = self.group.random(ZR) b = self.group.random(ZR) g_a = g**a g_b = g**b # Global Public Parameters (GPP) = g, g_a, g_b, H GPP = { 'g': g, 'g_a': g_a, 'g_b': g_b, 'H': H, } # Global Master Key (GMK) = a, b GMK = { 'a': a, 'b': b, } # return (GPP, GMK) def abenc_userreg(self, GPP, entity='user'): """ User registration by Certificate Authority (CA) to generate corresponding key pairs (i.e. Public and Private keys) :param GPP: Global Public Parameters (GPP) :param entity: the entity executing algorithm # :param registered_users: Dictionary of already registered users :return: User Global Secret and Public Keys (GSK_uid, GSK_uid_prime, GPK_uid, GPK_uid_prime) """ # group generator from GPP g = GPP['g'] # random numbers as user global secret keys u_uid = self.group.random(ZR) u_uid_prime = self.group.random(ZR) # user global public keys g_u_uid = g**u_uid g_u_uid_prime = g**(1 / u_uid_prime) # secret public key pair sent to user GSK_uid_prime = u_uid_prime GPK_uid = g_u_uid # secret public key pair to be sent to registered Attribute Authorities (AAs) GSK_uid = u_uid GPK_uid_prime = g_u_uid_prime return (GPK_uid, GSK_uid_prime), { 'GSK_uid': GSK_uid, 'GPK_uid_prime': GPK_uid_prime, 'u_uid': u_uid, } def abenc_aareg(self, GPP, authority_id, attributes, registered_authorities): """ Registration of Attribute Authorities (AA) by the Certificate Authority (CA) :param GPP: Global Public Parameters (GPP) :param authority_id: Unique ID for Attribute Authority :param attributes: Attributes managed by the authority :param registered_authorities: Dictionary of already registered authorities :return: Attribute Authority Secret and Public Key pairs with Version and Public keys for the attributes """ # check if authority has already been registered if authority_id not in registered_authorities: # generate random values to serves as attribute authority secret key alpha_aid = self.group.random(ZR) beta_aid = self.group.random(ZR) gamma_aid = self.group.random(ZR) # attribute authority secret key values SK_aid = { 'alpha_aid': alpha_aid, 'beta_aid': beta_aid, 'gamma_aid': gamma_aid } # attribute authority public key values PK_aid = { 'e_alpha': pair(GPP['g'], GPP['g'])**alpha_aid, 'g_beta_aid': GPP['g']**beta_aid, 'g_beta_aid_inv': GPP['g']**(1 / beta_aid), } authority_attributes = {} registered_authorities[authority_id] = (SK_aid, PK_aid, authority_attributes) else: SK_aid, PK_aid, authority_attributes = registered_authorities[ authority_id] # generate version and public keys for attributes for attribute in attributes: # check if attributes already exist with public and version keys # if they do, skip generation process if attribute in authority_attributes: continue # generate random element as version key version_key = self.group.random(ZR) h = GPP['H'](attribute) PK_1_attribute = h**version_key PK_2_attribute = h**(version_key * SK_aid['gamma_aid']) PK_attribute_aid = [PK_1_attribute, PK_2_attribute] authority_attributes[attribute] = { 'VK': version_key, 'PK': PK_attribute_aid, } return (SK_aid, PK_aid, authority_attributes) def abenc_keygen(self, GPP, authority, attribute, user_object, USK=None): """ Generate attribute authority related secret keys for users (executed by the corresponding attribute authority) :param GPP: Global Public Parameters :param authority: Attribute Authority Parameters :param attribute: Attribute for which secret key is being generated :param user_object: User :param USK: Generated attribute authority related user secret key :return: User Secret Key (USK) """ # generate random integer to tie attribute secret key to user if 't' not in user_object: user_object['t'] = self.group.random(ZR) t = user_object['t'] # assign corresponding attribute authority parameters ASK, APK, authority_attrs = authority u = user_object # create USK data set if none exists already if USK is None: USK = {} if 'K_uid_aid' not in USK or 'K_uid_aid_prime' not in USK or 'AK_uid_aid' not in USK: USK['K_uid_aid'] = (u['GPK_uid_prime']**ASK['alpha_aid']) * ( GPP['g_a']**u['u_uid']) * (GPP['g_b']**t) USK['K_uid_aid_prime'] = GPP['g']**t USK['AK_uid_aid'] = {} # generate attribute specific secret key parameters AK_uid_aid = (GPP['g'] ** (t * ASK['beta_aid'])) * authority_attrs[attribute]['PK'][0] \ ** (ASK['beta_aid'] * (u['u_uid'] + ASK['gamma_aid'])) USK['AK_uid_aid'][attribute] = AK_uid_aid return USK def abenc_encrypt(self, GPP, policy_string, k, authority): """ Encryption algorithm which encrypts the message given, based on the policy :param GPP: Global Public Parameters :param policy_string: Policy :param k: Content Key (i.e group element based on AES key) :param authority: Attribute Authority Parameters :return: Ciphertext """ APK = {} authority_attributes = {} authority_g_beta_inv = {} # extract the APK for the different authorities for authority_temp in authority.keys(): APK[authority_temp] = authority[authority_temp][1] # extract the PK values of the attributes of the attribute authorities # extract the corresponding g_beta_inverse values for the attribute authorities for item in authority[authority_temp][2].keys(): authority_attributes[item] = authority[authority_temp][2][item] authority_g_beta_inv[item] = APK[authority_temp][ 'g_beta_aid_inv'] # extract policy and use policy elements to slit the secret # into their corresponding shares for encryption policy = self.util.createPolicy(policy_string) # generate secret through random element secret = self.group.random(ZR) # split secret into shares (this returns a list) shares = self.util.calculateSharesList(secret, policy) # process shares list to create a dict with attribute as key # and corresponding shares as value shares = dict([(x[0].getAttributeAndIndex(), x[1]) for x in shares]) # initialize blinding factor to hide key blinding_factor = 1 for authority_temp in authority.keys(): blinding_factor *= APK[authority_temp]['e_alpha'] # create C elements of encrypted file C = k * (blinding_factor**secret) C_prime = GPP['g']**secret C_prime_prime = GPP['g_b']**secret # create structure (dict) to hold the C_i and D_i elements of the encrypted file # these are the components related to the attributes C_i = {} C_i_prime = {} D_i = {} D_i_prime = {} # generate C_i and D_i elements for attribute, secret_share in shares.items(): # attribute_temp = self.util.strip_index(attribute) # generate random r_i element k_attr = self.util.strip_index(attribute) r_i = self.group.random(ZR) attribute_PK = authority_attributes[attribute] C_i[attribute] = (GPP['g_a']** secret_share) * ~(attribute_PK['PK'][0]**r_i) C_i_prime[attribute] = GPP['g']**r_i D_i[attribute] = authority_g_beta_inv[attribute]**r_i D_i_prime[attribute] = attribute_PK['PK'][1]**r_i return { 'C': C, 'C_prime': C_prime, 'C_prime_prime': C_prime_prime, 'C_i': C_i, 'C_i_prime': C_i_prime, 'D_i': D_i, 'D_i_prime': D_i_prime, 'policy': policy_string, } def abenc_generatetoken(self, GPP, CT, UASK, user_keys): """ Partial decryption of the ciphertext :param GPP: Global Public Parameters :param CT: Ciphertext elements :param UASK: Secret Keys for user gotten from Attribute Authorities :param user_keys: User global keys :return: Partially decrypted ciphertext """ # list to hold corresponding attributes possessed by the user user_attributes = [] for authority in UASK.keys(): user_attributes.extend(UASK[authority]['AK_uid_aid'].keys()) # access ciphertext policy encryption_policy = self.util.createPolicy(CT['policy']) # generate list of minimum policy elements needed for encryption # returns False if user fails policy assessment minimal_policy_list = self.util.prune(encryption_policy, user_attributes) # print(minimal_policy_list) # this is an error handling implementation that should be fixed later if not minimal_policy_list: return False # get attribute coefficients to be able to access their share of the secret coefficients = self.util.getCoefficients(encryption_policy) # initialize the dividend value for the token generation computation dividend = 1 for authority in UASK.keys(): dividend *= ( pair(CT['C_prime'], UASK[authority]['K_uid_aid']) * ~pair(CT['C_prime_prime'], UASK[authority]['K_uid_aid_prime'])) # attribute authority index? n_a = 1 # initialize divisor value for token generation computation divisor = 1 # create dict to hold attributes for the authorities and their corresponding secret keys attribute_keys = {} # create dict to hold attributes contained in the pruned list and their corresponding secret keys pruned_attribute_keys = {} # populate attribute with with corresponding key value pairs for authority in UASK.keys(): attribute_keys.update(UASK[authority]['AK_uid_aid']) # populate pruned attribute with corresponding key value pairs # from attribute list for attribute in minimal_policy_list: pruned_attribute_keys[str(attribute)] = attribute_keys[str( attribute)] # compute divisor for authority in UASK.keys(): temp_divisor = 1 for attribute in minimal_policy_list: x = attribute.getAttributeAndIndex() y = attribute.getAttribute() temp_divisor *= ( (pair(CT['C_i'][y], user_keys) * pair(CT['D_i'][y], pruned_attribute_keys[y]) * ~pair(CT['C_i_prime'][y], UASK[authority]['K_uid_aid_prime']) * ~pair(GPP['g'], CT['D_i_prime'][y]))**(coefficients[x] * n_a)) divisor *= temp_divisor Token = dividend / divisor return (Token, CT['C']) def abenc_decrypt(self, CT, TK, user_keys): """ Final decryption algorithm to reveal original message. To be run by the user :param CT: Original component of ciphertext that contains the encrypted message :param TK: Token generated during partial decryption of ciphertext :param user_keys: User global keys :return: Decrypted message """ message = CT / (TK**user_keys[1]) return message def abenc_ukeygen(self, GPP, authority, attribute, user_object): """ Generate update keys used in the revocation process for users and the cloud service provider. This will be run by the Attribute Authority. :param GPP: Global Public Parameters :param authority: Attribute Authority :param attribute: Attribute to be updated :param user_object: User :return: User attribute update keys and ciphertext update keys """ ASK, _, authAttrs = authority # attribute version key to be updated old_version_key = authAttrs[attribute]['VK'] # set new version key to old value new_version_key = old_version_key # ensure that new version key is different from original version key while old_version_key == new_version_key: new_version_key = self.group.random() # update version key of the attribute in the dictionary authAttrs[attribute]['VK'] = new_version_key u_uid = user_object['u_uid'] # create update key for users i.e to update the attribute involved KUK = GPP['H'](attribute)**(ASK['beta_aid'] * (new_version_key - old_version_key) * (u_uid + ASK['gamma_aid'])) # create update key for ciphertexts encrypted with attribute involved CUK = (new_version_key / old_version_key, (old_version_key - new_version_key) / (old_version_key * ASK['gamma_aid'])) # update the public parameters of the attribute involvedauthAttrs[attribute]['PK'][0] = authAttrs[attribute]['PK'][0] ** CUK[0] authAttrs[attribute]['PK'][1] = authAttrs[attribute]['PK'][1]**CUK[0] return { 'KUK': KUK, 'CUK': CUK, } def abenc_skupdate(self, USK, attribute, KUK): """ Updates the attribute secret key for the specific attribute. This is executed by a non-revoked user. :param USK: User secret key :param attribute: Attribute whose secret key is to be updated :param KUK: Update key for users :return: NA """ # update the secret key component of the affected attribute # print(USK) USK['AK_uid_aid'][attribute] = USK['AK_uid_aid'][attribute] * KUK def abenc_ctupdate(self, GPP, CT, attribute, CUK): """ Updates the ciphertexts that contain the specific attribute (revoked attribute). This is executed by the cloud service provider. :param GPP: Global Public Parameters :param CT: The affected ciphertext :param attribute: Attribute that is affected by the revocation process :param CUK: The Ciphertext Update Key :return: NA """ # update the corresponding components of the ciphertext that are related to the affected attribute CT['C_i'][attribute] = CT['C_i'][attribute] * ( CT['D_i_prime'][attribute]**CUK[1]) CT['D_i_prime'][attribute] = CT['D_i_prime'][attribute]**CUK[0]