Source code for abenc_unmcpabe_yahk14

'''
Yamada, Attrapadung, Hanaoka, Kunihiro

| From: "A Framework and Compact Constructions for Non-monotonic Attribute-Based Encryption"
| Published in:  Public-Key Cryptography--PKC 2014
| Pages: 275--292
| Available from: http://eprint.iacr.org/2014/181 Sec. 7
| Notes:

* type:          attribute-based encryption (public key)
* setting:       bilinear pairing group of prime order
* assumption:    complex q-type assumption

:Authors:        al, artjomb
:Date:          07/15
'''

from charm.toolbox.pairinggroup import *
from charm.toolbox.secretutil import SecretUtil
from charm.toolbox.ABEnc import *


debug = False
[docs]class CPABE_YAHK14(ABEnc): """ >>> from charm.toolbox.pairinggroup import PairingGroup,ZR,G1,G2,GT,pair >>> group = PairingGroup('SS512') >>> cpabe = CPABE_YAHK14(group) >>> msg = group.random(GT) >>> attributes = ['2', '3'] # must be integer strings >>> access_policy = '2 and !1' # must be integer strings >>> (master_public_key, master_key) = cpabe.setup() >>> secret_key = cpabe.keygen(master_public_key, master_key, attributes) >>> cipher_text = cpabe.encrypt(master_public_key, msg, access_policy) >>> decrypted_msg = cpabe.decrypt(master_public_key, secret_key, cipher_text) >>> msg == decrypted_msg True """ def __init__(self, groupObj, verbose = False): ABEnc.__init__(self) global util, group group = groupObj util = SecretUtil(group, verbose) # Defining a function to pick explicit exponents in the group
[docs] def exp(self,value): return group.init(ZR, value)
[docs] def setup(self): g = group.random(G1) # this element can also be in G2 and then PairingGroup('MNT224') can be used g2, u, h, w, v = group.random(G1), group.random(G1), group.random(G1), group.random(G1), group.random(G1) alpha, beta = group.random( ), group.random( )#from ZR vDot = u ** beta egg = pair(g2,g)**alpha pp = {'g':g, 'g2':g2, 'u':u, 'h':h, 'w':w, 'v':v, 'vDot':vDot,'egg':egg} mk = {'g2_alpha':g2 ** alpha, 'beta': beta } return (pp, mk)
[docs] def keygen(self, pp, mk, S): # S is a set of attributes written as STRINGS i.e. {'1', '2', '3',...} r = group.random( ) D1 = mk['g2_alpha'] * (pp['w']**r) D2 = pp['g']**r vR = pp['v']**(-r) K1, K1Dot, K2, K2Dot = {}, {}, {}, {} rDotCumulative = r for i, idx in zip(S, range(len(S))): ri = group.random( ) if idx + 1 is len(S): riDot = rDotCumulative else: riDot = group.random( ) rDotCumulative -= riDot omega_i = self.exp(int(i)) K1[i] = vR * (pp['u']**omega_i * pp['h'])**ri K1Dot[i] = (pp['u']**(omega_i * mk['beta']) * pp['h']**mk['beta'])**riDot K2[i] = pp['g']**ri K2Dot[i] = pp['g']**(mk['beta']*riDot) S = [s for s in S] #Have to be an array for util.prune return { 'S':S, 'D1': D1, 'D2' : D2, 'K1':K1, 'K1Dot':K1Dot, 'K2':K2, 'K2Dot':K2Dot }
[docs] def encrypt(self, pp, message, policy_str): s = group.random() policy = util.createPolicy(policy_str) a_list = util.getAttributeList(policy) shares = util.calculateSharesDict(s, policy) #These are correctly set to be exponents in Z_p C0 = message * (pp['egg']**s) C1 = pp['g']**s C_1, C_2, C_3 = {}, {}, {} for i in a_list: ti = group.random() if i[0] == '!': inti = util.strip_index(i[1:]) C_1[i] = pp['w']**shares[i] * pp['vDot']**ti else: inti = util.strip_index(i) C_1[i] = pp['w']**shares[i] * pp['v']**ti inti = self.exp(int(inti)) C_2[i] = (pp['u']**inti * pp['h'])**(-ti) C_3[i] = pp['g']**ti #print('The exponent is ',inti) return { 'Policy':policy_str, 'C0':C0, 'C1':C1, 'C_1':C_1, 'C_2':C_2, 'C_3':C_3 }
[docs] def decrypt(self, pp, sk, ct): policy = util.createPolicy(ct['Policy']) z = util.getCoefficients(policy) # workaround to let the charm policy parser successfully parse the non-monotonic attributes a_list = util.getAttributeList(policy) nS = sk['S'][:] for att in a_list: if att[0] == '!' and att[1:] not in sk['S']: nS.append(att) pruned_list = util.prune(policy, nS) if (pruned_list == False): return group.init(GT,1) B = pair(ct['C1'], sk['D1']) for i in range(len(pruned_list)): x = pruned_list[i].getAttribute( ) #without the underscore y = pruned_list[i].getAttributeAndIndex( ) #with the underscore a = pair( ct['C_1'][x], sk['D2']) if x[0] == '!': b = group.init(GT, 1) inti = self.exp(int(x[1:])) for xj in sk['S']: if xj[0] == '!': intj = self.exp(int(xj[1:])) else: intj = self.exp(int(xj)) b *= ( pair( ct['C_2'][x], sk['K2Dot'][str(intj)]) * pair( ct['C_3'][x], sk['K1Dot'][str(intj)]) ) ** (1 / (inti - intj)) else: b = pair( ct['C_2'][x], sk['K2'][x]) * pair( ct['C_3'][x], sk['K1'][x]) d = - z[y] B *= ( a * b )**d return ct['C0'] / B
[docs] def randomMessage(self): return group.random(GT)
[docs]def main(): curve = 'SS512' groupObj = PairingGroup(curve) scheme = CPABE_YAHK14(groupObj) (pp, mk) = scheme.setup() testCases = [ ( '2 and !1', [ ({'1', '2'}, False), ({'1'}, False), ({'2'}, True), ({'3'}, False), ({'2', '3'}, True) ] ), ( '2 and 1', [ ({'1', '2'}, True), ({'1'}, False), ({'2'}, False), ({'3'}, False) ] ), ( '2', [ ({'1', '2'}, True), ({'1'}, False), ({'2'}, True) ] ), ( '!2', [ ({'1', '2'}, False), ({'1'}, True), ({'2'}, False) ] ), ] for policy_str, users in testCases: for S, success in users: m = group.random(GT) sk = scheme.keygen(pp, mk, S) ct = scheme.encrypt(pp, m, policy_str) res = scheme.decrypt(pp, sk, ct) if (m == res) == success: print("PASS", S, '' if success else 'not', "in '" + policy_str + "'") else: print("FAIL", S, '' if success else 'not', "in '" + policy_str + "'") m = group.random(GT) sk = scheme.keygen(pp, mk, {'1', '2'}) ct = scheme.encrypt(pp, m, '!1 and 2') sk['S'].remove('1') res = scheme.decrypt(pp, sk, ct) if (m == res) == False: print("PASS: attack failed") else: print("FAIL: attack succeeded")
if __name__ == '__main__': debug = True main()