'''
**Boneh-Canetti-Halevi-Katz IBE-to-PKE Transform (BCHK05)**
*Description:* Transforms an Identity-Based Encryption scheme into a CCA-secure
Public Key Encryption scheme using the BCHK construction.
| **Based on:** Improved Efficiency for CCA-Secure Cryptosystems Built Using Identity-Based Encryption
| **Published in:** Topics in Cryptology, CT-RSA 2005
| **Available from:** https://eprint.iacr.org/2004/261.pdf
| **Notes:** Section 4 of the paper; more efficient than CHK04 transform
.. rubric:: Adapter Properties
* **Type:** IBE-to-PKE transform
* **Underlying Scheme:** any selective-ID secure IBE scheme
* **Purpose:** constructs CCA-secure public key encryption from IBE
.. rubric:: Implementation
:Authors: Christina Garman
:Date: 12/2011
'''
from charm.core.engine.util import pickleObject, serializeObject
import hmac, hashlib, math
from charm.schemes.ibenc.ibenc_bb03 import IBEnc, ZR, GT, sha2
debug = False
[docs]
class BCHKIBEnc(IBEnc):
"""
>>> from charm.schemes.encap_bchk05 import EncapBCHK
>>> from charm.schemes.ibenc.ibenc_bb03 import PairingGroup, IBE_BB04
>>> group = PairingGroup('SS512')
>>> ibe = IBE_BB04(group)
>>> encap = EncapBCHK()
>>> hyb_ibe = BCHKIBEnc(ibe, group, encap)
>>> (public_key, secret_key) = hyb_ibe.keygen()
>>> msg = b"Hello World!"
>>> cipher_text = hyb_ibe.encrypt(public_key, msg)
>>> decrypted_msg = hyb_ibe.decrypt(public_key, secret_key, cipher_text)
>>> decrypted_msg == msg
True
"""
[docs]
def str_XOR(self, m, k):
output = ""
for character in m:
for letter in k:
if(not type(character) == int):
character = ord(character)
if(not type(letter) == int):
letter = ord(letter)
character = chr(character ^ letter)
output += character
return output
[docs]
def elmtToString(self, g, length):
hash_len = 20
b = math.ceil(length / hash_len)
gStr = b''
for i in range(1, b+1):
gStr += sha2(g, i)
return gStr[:length]
def __init__(self, scheme, groupObj, encscheme):
global ibenc, group, encap
ibenc = scheme
group = groupObj
encap = encscheme
[docs]
def keygen(self):
(PK, msk) = ibenc.setup()
pub = encap.setup()
pk = { 'PK':PK, 'pub':pub }
sk = { 'msk': msk }
return (pk, sk)
[docs]
def encrypt(self, pk, m):
(k, ID, x) = encap.S(pk['pub'])
if type(m) != bytes:
m = bytes(m, 'utf8')
if type(x) != bytes:
x = bytes(x, 'utf8')
ID2 = group.hash(ID, ZR)
m2 = m + b':' + x
kprime = group.random(GT)
kprimeStr = self.elmtToString(kprime, len(m2))
C1 = ibenc.encrypt(pk['PK'], ID2, kprime)
C2 = self.str_XOR(m2, kprimeStr)
C2 = C2.encode('utf8')
C1prime = pickleObject(serializeObject(C1, group))
tag = hmac.new(k, C1prime+C2, hashlib.sha256).digest()
cipher = { 'ID':ID, 'C1':C1, 'C2':C2, 'tag':tag }
return cipher
[docs]
def decrypt(self, pk, sk, c):
ID2 = group.hash(c['ID'], ZR)
SK = ibenc.extract(sk['msk'], ID2)
kprime = ibenc.decrypt(pk, SK, c['C1'])
kprimeStr = self.elmtToString(kprime, len(c['C2']))
m2 = self.str_XOR(c['C2'], kprimeStr)
x = m2.split(':')[1]
k = encap.R(pk['pub'], c['ID'], x)
C1prime = pickleObject(serializeObject(c['C1'], group))
if hmac.compare_digest(c['tag'], hmac.new(k, C1prime+c['C2'], hashlib.sha256).digest()):
return bytes(m2.split(':')[0], 'utf8')
else:
return b'FALSE'