try:
from charm.toolbox.pairingcurves import params as param_info
from charm.core.math.pairing import pairing,pc_element,ZR,G1,G2,GT,init,pair,hashPair,H,random,serialize,deserialize,ismember,order
import charm.core.math.pairing as pg
from charm.config import libs,pairing_lib
except Exception as err:
print(err)
exit(-1)
[docs]
class PairingGroup():
def __init__(self, param_id, param_file = False, secparam = 512, verbose = False, seed1 = None, seed2 = None):
#legacy handler to handle calls that still pass in a file path
if param_file:
self.Pairing = pairing(file=param_id)
elif type(param_id) == str:
pairID = param_info.get(param_id)
assert pairID != None, "'%s' not recognized! See 'pairingcurves.py' in toolbox." % param_id
if pairing_lib == libs.pbc:
self.Pairing = pairing(string=pairID)
self.param = param_id
elif pairing_lib in [libs.miracl, libs.relic]:
self.Pairing = pairing(pairID)
self.param = pairID
elif type(param_id) == int:
self.Pairing = pairing(param_id)
self.param = param_id
""" the secure parameter $\\lambda$ should be a positive integer; otherwise, it may lead to computation errors in getting the message size """
assert isinstance(secparam, int) and secparam >= 1, "The security parameter $\\lambda$ should be a positive integer. "
self.secparam = secparam # number of bits
self._verbose = verbose
self.__gt = pair(self.random(G1, seed = seed1), self.random(G2, seed = seed2))
def __str__(self):
return str(self.Pairing)
[docs]
def order(self):
"""returns the order of the group"""
return order(self.Pairing)
[docs]
def paramgen(self, qbits, rbits):
return None
[docs]
def ismember(self, obj):
"""membership test for a pairing object"""
return ismember(self.Pairing, obj)
[docs]
def ismemberList(self, obj):
"""membership test for a list of pairing objects"""
for i in range(len(obj)):
if ismember(self.Pairing, obj[i]) == False: return False
return True
[docs]
def ismemberDict(self, obj):
"""membership test for a dict of pairing objects"""
for i in obj.keys():
if ismember(self.Pairing, obj[i]) == False: return False
return True
[docs]
def groupSetting(self):
return 'pairing'
[docs]
def groupType(self):
return self.param
[docs]
def messageSize(self):
""" after filling complete bytes with every 8 bits, any remaining 1, 2, ..., 7 more bits will occupy an additional byte, even if they do not form a complete byte """
return (self.secparam + 7) >> 3
[docs]
def init(self, type, value=None):
"""initializes an object with a specified type and value"""
if value != None:
return init(self.Pairing, type, value)
return init(self.Pairing, type)
[docs]
def random(self, _type = ZR, count = 1, seed = None):
"""selects one or more random elements in ZR, G1, G2 and GT"""
if _type == GT:
if 1 == count:
return self.__gt ** (random(self.Pairing, ZR) if seed is None else random(self.Pairing, ZR, seed))
elif count >= 2:
return tuple(self.__gt ** random(self.Pairing, ZR) for _ in range(count))
elif _type in (ZR, G1, G2):
if 1 == count:
return random(self.Pairing, _type) if seed is None else random(self.Pairing, _type, seed)
elif count >= 2:
return tuple(random(self.Pairing, _type) for _ in range(count))
else:
return None
[docs]
def encode(self, message):
raise NotImplementedException
[docs]
def decode(self, element):
raise NotImplementedException
[docs]
def hash(self, args, type=ZR):
"""hashes objects into ZR, G1 or G2 depending on the pairing curve"""
return H(self.Pairing, args, type)
[docs]
def serialize(self, obj, compression=True):
"""Serialize a pairing object into bytes.
:param compression: serialize the compressed representation of the
curve element, taking about half the space but potentially
incurring in non-negligible computation costs when
deserializing. Default is True for compatibility with previous
versions of charm.
>>> p = PairingGroup('SS512')
>>> v1 = p.random(G1)
>>> b1 = p.serialize(v1)
>>> b1 == p.serialize(v1, compression=True)
True
>>> v1 == p.deserialize(b1)
True
>>> b1 = p.serialize(v1, compression=False)
>>> v1 == p.deserialize(b1, compression=False)
True
"""
return serialize(obj, compression)
[docs]
def deserialize(self, obj, compression=True):
"""Deserialize a bytes serialized element into a pairing object.
:param compression: must be used for objects serialized with the
compression parameter set to True. Default is True for
compatibility with previous versions of charm.
"""
return deserialize(self.Pairing, obj, compression)
[docs]
def debug(self, data, prefix=None):
if not self._verbose:
return
if type(data) == dict:
for k,v in data.items():
print(k,v)
elif type(data) == list:
for i in range(0, len(data)):
print(prefix, (i+1),':',data[i])
print('')
elif type(data) == str:
print(data)
else:
print(type(data), ':', data)
return
[docs]
def pair_prod(self, lhs, rhs):
"""takes two lists of G1 & G2 and computes a pairing product"""
return pair(lhs, rhs, self.Pairing)
[docs]
def InitBenchmark(self):
"""initiates the benchmark state"""
return pg.InitBenchmark(self.Pairing)
[docs]
def StartBenchmark(self, options):
"""starts the benchmark with any of these options:
RealTime, CpuTime, Mul, Div, Add, Sub, Exp, Pair, Granular"""
return pg.StartBenchmark(self.Pairing, options)
[docs]
def EndBenchmark(self):
"""ends an ongoing benchmark"""
return pg.EndBenchmark(self.Pairing)
[docs]
def GetGeneralBenchmarks(self):
"""retrieves benchmark count for all group operations"""
return pg.GetGeneralBenchmarks(self.Pairing)
[docs]
def GetGranularBenchmarks(self):
"""retrieves group operation count per type: ZR, G1, G2, and GT"""
return pg.GetGranularBenchmarks(self.Pairing)
[docs]
def GetBenchmark(self, option):
"""retrieves benchmark results for any of these options:
RealTime, CpuTime, Mul, Div, Add, Sub, Exp, Pair, Granular"""
return pg.GetBenchmark(self.Pairing, option)