from charm.core.math.pairing import hashPair as sha1
int hash_to_bytes(uint8_t *input_buf, int input_len, uint8_t *output_buf, int hash_len, uint8_t hash_prefix)
{
SHA256_CTX sha2;
int i, new_input_len = input_len + 2; // extra byte for prefix
uint8_t first_block = 0;
uint8_t new_input[new_input_len+1];
// printf("orig input => \n");
// printf_buffer_as_hex(input_buf, input_len);
memset(new_input, 0, new_input_len+1);
new_input[0] = first_block; // block number (always 0 by default)
new_input[1] = hash_prefix; // set hash prefix
memcpy((uint8_t *)(new_input+2), input_buf, input_len); // copy input bytes
// printf("new input => \n");
// printf_buffer_as_hex(new_input, new_input_len);
// prepare output buf
memset(output_buf, 0, hash_len);
if (hash_len <= HASH_LEN) {
SHA256_Init(&sha2);
SHA256_Update(&sha2, new_input, new_input_len);
uint8_t md[HASH_LEN+1];
SHA256_Final(md, &sha2);
memcpy(output_buf, md, hash_len);
}
...PyMethodDef pairing_methods[] = {
{"init", (PyCFunction)Element_elem, METH_VARARGS, "Create an element in group Zr and optionally set value."},
{"pair", (PyCFunction)Apply_pairing, METH_VARARGS, "Apply pairing between an element of G1 and G2 and returns an element mapped to GT"},
{"hashPair", (PyCFunction)sha2_hash, METH_VARARGS, "Compute a sha1 hash of an element type"},
{"H", (PyCFunction)Element_hash, METH_VARARGS, "Hash an element type to a specific field: Zr, G1, or G2"},
{"random", (PyCFunction)Element_random, METH_VARARGS, "Return a random element in a specific group: G1, G2, Zr"},
{"serialize", (PyCFunction)Serialize_cmp, METH_VARARGS, "Serialize an element type into bytes."},
{"deserialize", (PyCFunction)Deserialize_cmp, METH_VARARGS, "De-serialize an bytes object into an element object"},
{"ismember", (PyCFunction) Group_Check, METH_VARARGS, "Group membership test for element objects."},
{"order", (PyCFunction) Get_Order, METH_VARARGS, "Get the group order for a particular field."},
...from hashlib import sha1 as sha1hashlib
import hmac
class MessageAuthenticator(object):
""" Abstraction for constructing and verifying authenticated messages
A large number of the schemes can only encrypt group elements
and do not provide an efficient mechanism for encoding byte in
those elements. As such we don't pick a symmetric key and encrypt
it asymmetrically. Rather, we hash a random group element to get the
symmetric key.
>>> from charm.toolbox.pairinggroup import PairingGroup,GT
>>> from charm.core.math.pairing import hashPair as extractor
>>> groupObj = PairingGroup('SS512')
>>> key = groupObj.random(GT)
>>> m = MessageAuthenticator(extractor(key))
>>> AuthenticatedMessage = m.mac('Hello World')
>>> m.verify(AuthenticatedMessage)
True
"""
def __init__(self,key, alg = "HMAC_SHA1"):
"""
Creates a message authenticator and verifier under the specified key
"""
if alg != "HMAC_SHA1":
raise ValueError("Currently only HMAC_SHA1 is supported as an algorithm")
self._algorithm = alg
self._key = key
def mac(self,msg):
"""
authenticates a message
"""
return {
"alg": self._algorithm,
"msg": msg,
"digest": hmac.new(self._key,bytes(self._algorithm + msg,"utf-8"),digestmod=sha1hashlib).hexdigest()
}
from charm.core.math.pairing import hashPair as sha1
from charm.toolbox.paddingschemes import PKCS7Padding
from charm.toolbox.securerandom import OpenSSLRand
from charm.core.crypto.cryptobase import MODE_CBC,AES,selectPRP
from hashlib import sha1 as sha1hashlib, sha256 as sha256hashlib
from math import ceil
import json
import hmac
from base64 import b64encode,b64decode
class MessageAuthenticator(object):
""" Abstraction for constructing and verifying authenticated messages
A large number of the schemes can only encrypt group elements
and do not provide an efficient mechanism for encoding byte in
those elements. As such we don't pick a symmetric key and encrypt
it asymmetrically. Rather, we hash a random group element to get the
symmetric key.
>>> from charm.toolbox.pairinggroup import PairingGroup,GT
>>> from charm.core.math.pairing import hashPair as extractor
>>> groupObj = PairingGroup('SS512')
>>> key = groupObj.random(GT)
>>> m = MessageAuthenticator(extractor(key))
>>> AuthenticatedMessage = m.mac('Hello World')
>>> m.verify(AuthenticatedMessage)
True
"""
# def __init__(self,key, alg = "HMAC_SHA1"):
def __init__(self,key, alg = "HMAC_SHA256"):
"""
Creates a message authenticator and verifier under the specified key
"""
# if alg not in ["HMAC_SHA1", "HMAC_SHA256"]:
# raise ValueError("Currently only HMAC_SHA1 and HMAC_SHA256 are supported as algorithms")
hmacAlgorithms = {'HMAC_SHA1':sha1hashlib, 'HMAC_SHA256':sha256hashlib}
self._errorMessage = "Currently only [" + ', '.join(list(hmacAlgorithms.keys())) + "] are supported as algorithms"
if alg not in hmacAlgorithms.keys():
raise ValueError(self._errorMessage)
self._hashFunction = hmacAlgorithms[alg]
self._algorithm = alg
self._key = key
def mac(self,msg):
"""
authenticates a message
"""
return {
"alg": self._algorithm,
"msg": msg,
"digest": hmac.new(self._key,bytes(self._algorithm + msg,"utf-8"),digestmod=self._hashFunction).hexdigest()
}
def verify(self,msgAndDigest):
"""
verifies the result returned by mac
"""
if msgAndDigest['alg'] != self._algorithm:
raise ValueError(self._errorMessage)
expected = bytes(self.mac(msgAndDigest['msg'])['digest'],'utf-8')
received = bytes(msgAndDigest['digest'],'utf-8')
return self._hashFunction(expected).digest() == self._hashFunction(received).digest() # we compare the hash instead of the direct value to avoid a timing attack
class SymmetricCryptoAbstraction(object):
"""
Abstraction for symmetric encryption and decryption of data.
Ideally provide an INDCCA2 secure symmetric container for arbitrary data.
Currently only supports primitives that JSON can encode and decode.
A large number of the schemes can only encrypt group elements
and do not provide an efficient mechanism for encoding byte in
those elements. As such we don't pick a symmetric key and encrypt
it asymmetrically. Rather, we hash a random group element to get the
symmetric key.
>>> from charm.toolbox.pairinggroup import PairingGroup,GT
>>> groupObj = PairingGroup('SS512')
>>> from charm.core.math.pairing import hashPair as extractor
>>> a = SymmetricCryptoAbstraction(extractor(groupObj.random(GT)))
>>> ct = a.encrypt(b"Friendly Fire Isn't")
>>> a.decrypt(ct)
b"Friendly Fire Isn't"
"""
def __init__(self,key, alg = AES, mode = MODE_CBC):
self._alg = alg
self.key_len = 16
self._block_size = 16
self._mode = mode
self._key = key[0:self.key_len]
self._padding = PKCS7Padding();
def _initCipher(self,IV = None):
if IV == None :
IV = OpenSSLRand().getRandomBytes(self._block_size)
self._IV = IV
return selectPRP(self._alg,(self._key,self._mode,self._IV))
def __encode_decode(self,data,func):
data['IV'] = func(data['IV'])
data['CipherText'] = func(data['CipherText'])
return data
#This code should be factored out into another class
#Because json is only defined over strings, we need to base64 encode the encrypted data
# and convert the base 64 byte array into a utf8 string
def _encode(self,data):
return self.__encode_decode(data,lambda x:b64encode(x).decode('utf-8'))
def _decode(self,data):
return self.__encode_decode(data,lambda x:b64decode(bytes(x,'utf-8')))
def encrypt(self, message):
#This should be removed when all crypto functions deal with bytes"
if type(message) != bytes :
message = bytes(message,"utf-8")
ct = self._encrypt(message)
#JSON strings cannot have binary data in them, so we must base64 encode cipher
cte = json.dumps(self._encode(ct))
return cte
def _encrypt(self,message):
#Because the IV cannot be set after instantiation, decrypt and encrypt
# must operate on their own instances of the cipher
cipher = self._initCipher()
ct= {'ALG':self._alg,
'MODE':self._mode,
'IV':self._IV,
'CipherText':cipher.encrypt(self._padding.encode(message))
}
return ct
def decrypt(self,cipherText):
f = json.loads(cipherText)
return self._decrypt(self._decode(f)) #.decode("utf-8")
def _decrypt(self,cipherText):
cipher = self._initCipher(cipherText['IV'])
msg = cipher.decrypt(cipherText['CipherText'])
return self._padding.decode(msg)
class AuthenticatedCryptoAbstraction(SymmetricCryptoAbstraction):
def encrypt(self,msg):
#mac = MessageAuthenticator(sha1hashlib(b'Poor Mans Key Extractor'+self._key).digest()) # warning only valid in the random oracle
mac = MessageAuthenticator(sha256hashlib(b'Poor Mans Key Extractor'+self._key).digest()) # warning only valid in the random oracle
enc = super(AuthenticatedCryptoAbstraction,self).encrypt(msg)
return mac.mac(enc)
def decrypt(self,cipherText):
#mac = MessageAuthenticator(sha1hashlib(b'Poor Mans Key Extractor'+self._key).digest()) # warning only valid in the random oracle
mac = MessageAuthenticator(sha256hashlib(b'Poor Mans Key Extractor'+self._key).digest()) # warning only valid in the random oracle
if not mac.verify(cipherText):
raise ValueError("Invalid mac. Your data was tampered with or your key is wrong")
else:
return super(AuthenticatedCryptoAbstraction,self).decrypt(cipherText['msg'])