Source code for waters11
'''
Brent Waters
| From: "Ciphertext-Policy Attribute-Based Encryption: An Expressive, Efficient, and Provably Secure Realization"
| Published in: 2011
| Available from: https://doi.org/10.1007/978-3-642-19379-8_4
| Notes: Implemented an asymmetric version of the scheme in Section 3
| Security Assumption: Decisional Parallel Bilinear Diffie-Hellman Exponent
|
| type: ciphertext-policy attribute-based encryption
| setting: Pairing
:Authors: Shashank Agrawal
:Date: 05/2016
'''
from charm.toolbox.pairinggroup import PairingGroup, ZR, G1, G2, GT, pair
from charm.toolbox.ABEnc import ABEnc
from charm.toolbox.msp import MSP
debug = False
[docs]class Waters11(ABEnc):
def __init__(self, group_obj, uni_size, verbose=False):
ABEnc.__init__(self)
self.group = group_obj
self.uni_size = uni_size # bound on the size of the universe of attributes
self.util = MSP(self.group, verbose)
[docs] def setup(self):
"""
Generates public key and master secret key.
"""
if debug:
print('Setup algorithm:\n')
# pick a random element each from two source groups and pair them
g1 = self.group.random(G1)
g2 = self.group.random(G2)
alpha = self.group.random(ZR)
g1_alpha = g1 ** alpha
e_gg_alpha = pair(g1_alpha, g2)
a = self.group.random(ZR)
g1_a = g1 ** a
h = [0]
for i in range(self.uni_size):
h.append(self.group.random(G1))
pk = {'g1': g1, 'g2': g2, 'g1_a': g1_a, 'h': h, 'e_gg_alpha': e_gg_alpha}
msk = {'g1_alpha': g1_alpha}
return pk, msk
[docs] def keygen(self, pk, msk, attr_list):
"""
Generate a key for a set of attributes.
"""
if debug:
print('Key generation algorithm:\n')
t = self.group.random(ZR)
k0 = msk['g1_alpha'] * (pk['g1_a'] ** t)
L = pk['g2'] ** t
K = {}
for attr in attr_list:
K[attr] = pk['h'][int(attr)] ** t
return {'attr_list': attr_list, 'k0': k0, 'L': L, 'K': K}
[docs] def encrypt(self, pk, msg, policy_str):
"""
Encrypt a message M under a monotone span program.
"""
if debug:
print('Encryption algorithm:\n')
policy = self.util.createPolicy(policy_str)
mono_span_prog = self.util.convert_policy_to_msp(policy)
num_cols = self.util.len_longest_row
# pick randomness
u = []
for i in range(num_cols):
rand = self.group.random(ZR)
u.append(rand)
s = u[0] # shared secret
c0 = pk['g2'] ** s
C = {}
D = {}
for attr, row in mono_span_prog.items():
cols = len(row)
sum = 0
for i in range(cols):
sum += row[i] * u[i]
attr_stripped = self.util.strip_index(attr)
r_attr = self.group.random(ZR)
c_attr = (pk['g1_a'] ** sum) / (pk['h'][int(attr_stripped)] ** r_attr)
d_attr = pk['g2'] ** r_attr
C[attr] = c_attr
D[attr] = d_attr
c_m = (pk['e_gg_alpha'] ** s) * msg
return {'policy': policy, 'c0': c0, 'C': C, 'D': D, 'c_m': c_m}
[docs] def decrypt(self, pk, ctxt, key):
"""
Decrypt ciphertext ctxt with key key.
"""
if debug:
print('Decryption algorithm:\n')
nodes = self.util.prune(ctxt['policy'], key['attr_list'])
if not nodes:
print ("Policy not satisfied.")
return None
prodG = 1
prodGT = 1
for node in nodes:
attr = node.getAttributeAndIndex()
attr_stripped = self.util.strip_index(attr)
prodG *= ctxt['C'][attr]
prodGT *= pair(key['K'][attr_stripped], ctxt['D'][attr])
return (ctxt['c_m'] * pair(prodG, key['L']) * prodGT) / (pair(key['k0'], ctxt['c0']))