Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
sagrawal87 authored and Formula S committed Aug 29, 2017
1 parent b4e8893 commit 9bf909a
Show file tree
Hide file tree
Showing 6 changed files with 1,002 additions and 0 deletions.
242 changes: 242 additions & 0 deletions ac17.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
'''
Shashank Agrawal, Melissa Chase
| From: "FAME: Fast Attribute-based Message Encryption"
| Published in: 2017
| Available from: https://eprint.iacr.org/2017/807
| Notes: Implemented the scheme in Section 3
| Security Assumption: a variant of k-linear, k>=2
|
| 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 msp import MSP

debug = False


class AC17CPABE(ABEnc):
def __init__(self, group_obj, assump_size, verbose=False):
ABEnc.__init__(self)
self.group = group_obj
self.assump_size = assump_size # size of linear assumption, at least 2
self.util = MSP(self.group, verbose)

def setup(self):
"""
Generates public key and master secret key.
"""

if debug:
print('\nSetup algorithm:\n')

# generate two instances of the k-linear assumption
A = []
B = []
for i in range(self.assump_size):
A.append(self.group.random(ZR))
B.append(self.group.random(ZR)) # note that A, B are vectors here

# vector
k = []
for i in range(self.assump_size + 1):
k.append(self.group.random(ZR))

# pick a random element from the two source groups and pair them
g = self.group.random(G1)
h = self.group.random(G2)
e_gh = pair(g, h)

# now compute various parts of the public parameters

# compute the [A]_2 term
h_A = []
for i in range(self.assump_size):
h_A.append(h ** A[i])
h_A.append(h)

# compute the e([k]_1, [A]_2) term
g_k = []
for i in range(self.assump_size + 1):
g_k.append(g ** k[i])

e_gh_kA = []
for i in range(self.assump_size):
e_gh_kA.append(e_gh ** (k[i] * A[i] + k[self.assump_size]))

# the public key
pk = {'h_A': h_A, 'e_gh_kA': e_gh_kA}

# the master secret key
msk = {'g': g, 'h': h, 'g_k': g_k, 'A': A, 'B': B}

return pk, msk

def keygen(self, pk, msk, attr_list):
"""
Generate a key for a list of attributes.
"""

if debug:
print('\nKey generation algorithm:\n')

# pick randomness
r = []
sum = 0
for i in range(self.assump_size):
rand = self.group.random(ZR)
r.append(rand)
sum += rand

# compute the [Br]_2 term

# first compute just Br as it will be used later too
Br = []
for i in range(self.assump_size):
Br.append(msk['B'][i] * r[i])
Br.append(sum)

# now compute [Br]_2
K_0 = []
for i in range(self.assump_size + 1):
K_0.append(msk['h'] ** Br[i])

# compute [W_1 Br]_1, ...
K = {}
A = msk['A']
g = msk['g']
for attr in attr_list:
key = []
sigma_attr = self.group.random(ZR)
for t in range(self.assump_size):
prod = 1
a_t = A[t]
for l in range(self.assump_size + 1):
input_for_hash = attr + str(l) + str(t)
prod *= (self.group.hash(input_for_hash, G1) ** (Br[l]/a_t))
prod *= (g ** (sigma_attr/a_t))
key.append(prod)
key.append(g ** (-sigma_attr))
K[attr] = key

# compute [k + VBr]_1
Kp = []
g_k = msk['g_k']
sigma = self.group.random(ZR)
for t in range(self.assump_size):
prod = g_k[t]
a_t = A[t]
for l in range(self.assump_size + 1):
input_for_hash = '01' + str(l) + str(t)
prod *= (self.group.hash(input_for_hash, G1) ** (Br[l] / a_t))
prod *= (g ** (sigma / a_t))
Kp.append(prod)
Kp.append(g_k[self.assump_size] * (g ** (-sigma)))

return {'attr_list': attr_list, 'K_0': K_0, 'K': K, 'Kp': Kp}

def encrypt(self, pk, msg, policy_str):
"""
Encrypt a message msg under a policy string.
"""

if debug:
print('\nEncryption 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
s = []
sum = 0
for i in range(self.assump_size):
rand = self.group.random(ZR)
s.append(rand)
sum += rand

# compute the [As]_2 term
C_0 = []
h_A = pk['h_A']
for i in range(self.assump_size):
C_0.append(h_A[i] ** s[i])
C_0.append(h_A[self.assump_size] ** sum)

# compute the [(V^T As||U^T_2 As||...) M^T_i + W^T_i As]_1 terms

# pre-compute hashes
hash_table = []
for j in range(num_cols):
x = []
input_for_hash1 = '0' + str(j + 1)
for l in range(self.assump_size + 1):
y = []
input_for_hash2 = input_for_hash1 + str(l)
for t in range(self.assump_size):
input_for_hash3 = input_for_hash2 + str(t)
hashed_value = self.group.hash(input_for_hash3, G1)
y.append(hashed_value)
# if debug: print ('Hash of', i+2, ',', j2, ',', j1, 'is', hashed_value)
x.append(y)
hash_table.append(x)

C = {}
for attr, row in mono_span_prog.items():
ct = []
attr_stripped = self.util.strip_index(attr) # no need, re-use not allowed
for l in range(self.assump_size + 1):
prod = 1
cols = len(row)
for t in range(self.assump_size):
input_for_hash = attr_stripped + str(l) + str(t)
prod1 = self.group.hash(input_for_hash, G1)
for j in range(cols):
# input_for_hash = '0' + str(j+1) + str(l) + str(t)
prod1 *= (hash_table[j][l][t] ** row[j])
prod *= (prod1 ** s[t])
ct.append(prod)
C[attr] = ct

# compute the e(g, h)^(k^T As) . m term
Cp = 1
for i in range(self.assump_size):
Cp = Cp * (pk['e_gh_kA'][i] ** s[i])
Cp = Cp * msg

return {'policy': policy, 'C_0': C_0, 'C': C, 'Cp': Cp}

def decrypt(self, pk, ctxt, key):
"""
Decrypt ciphertext ctxt with key key.
"""

if debug:
print('\nDecryption algorithm:\n')

nodes = self.util.prune(ctxt['policy'], key['attr_list'])
if not nodes:
print ("Policy not satisfied.")
return None

prod1_GT = 1
prod2_GT = 1
for i in range(self.assump_size + 1):
prod_H = 1
prod_G = 1
for node in nodes:
attr = node.getAttributeAndIndex()
attr_stripped = self.util.strip_index(attr) # no need, re-use not allowed
# prod_H *= key['K'][attr_stripped][i] ** coeff[attr]
# prod_G *= ctxt['C'][attr][i] ** coeff[attr]
prod_H *= key['K'][attr_stripped][i]
prod_G *= ctxt['C'][attr][i]
prod1_GT *= pair(key['Kp'][i] * prod_H, ctxt['C_0'][i])
prod2_GT *= pair(prod_G, key['K_0'][i])

return ctxt['Cp'] * prod2_GT / prod1_GT
135 changes: 135 additions & 0 deletions bsw07.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
'''
John Bethencourt, Amit Sahai, Brent Waters
| From: "Ciphertext-Policy Attribute-Based Encryption"
| Published in: 2007
| Available from: https://doi.org/10.1109/SP.2007.11
| Notes: Implemented an asymmetric version of the scheme in Section 4.2
| Security Assumption: Generic group model
|
| 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 msp import MSP

debug = False


class BSW07(ABEnc):

def __init__(self, group_obj, verbose=False):
ABEnc.__init__(self)
self.group = group_obj
self.util = MSP(self.group, verbose)

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
g1 = self.group.random(G1)
g2 = self.group.random(G2)

beta = self.group.random(ZR)
h = g2 ** beta
f = g2 ** (1/beta)

alpha = self.group.random(ZR)
g1_alpha = g1 ** alpha
e_gg_alpha = pair (g1_alpha, g2)

pk = {'g1': g1, 'g2': g2, 'h': h, 'f': f, 'e_gg_alpha': e_gg_alpha}
msk = {'beta': beta, 'g1_alpha': g1_alpha}
return pk, msk

def keygen(self, pk, msk, attr_list):
"""
Generate a key for a set of attributes.
"""

if debug:
print('Key generation algorithm:\n')

r = self.group.random(ZR)
g1_r = pk['g1'] ** r
beta_inverse = 1 / msk['beta']
k0 = (msk['g1_alpha'] * g1_r) ** beta_inverse

K = {}
for attr in attr_list:
r_attr = self.group.random(ZR)
k_attr1 = g1_r * (self.group.hash(str(attr), G1) ** r_attr)
k_attr2 = pk['g2'] ** r_attr
K[attr] = (k_attr1, k_attr2)

return {'attr_list': attr_list, 'k0': k0, 'K': K}

def encrypt(self, pk, msg, policy_str):
"""
Encrypt a message M under a policy string.
"""

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['h'] ** s

C = {}
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)
c_i1 = pk['g2'] ** sum
c_i2 = self.group.hash(str(attr_stripped), G1) ** sum
C[attr] = (c_i1, c_i2)

c_m = (pk['e_gg_alpha'] ** s) * msg

return {'policy': policy, 'c0': c0, 'C': C, 'c_m': c_m}

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

prod = 1

for node in nodes:
attr = node.getAttributeAndIndex()
attr_stripped = self.util.strip_index(attr)
(c_attr1, c_attr2) = ctxt['C'][attr]
(k_attr1, k_attr2) = key['K'][attr_stripped]
prod *= (pair(k_attr1, c_attr1) / pair(c_attr2, k_attr2))

return (ctxt['c_m'] * prod) / (pair(key['k0'], ctxt['c0']))
Loading

0 comments on commit 9bf909a

Please sign in to comment.