def main(): nr_of_clients = 200 G = IntegerGroupQ() G.paramgen(1024) g = G.randomG() clients_list = [Client(G, g, i) for i in range(nr_of_clients)] for client in clients_list: g_v , r = client.proof_x g_x, id = client.g_x, client.id hash = G.hash(g, g_v, g_x, id) assert g_v == (g**r) * (g_x **hash) g_xs = [client.g_x for client in clients_list] hashes = [] for client in clients_list: client.compute_g_y(g_xs) hashes.append(client.answer()) # print(hashes) answers = [] for client in clients_list: assert G.hash(client.g_c_y) == hashes[client.id] answers.append(client.g_c_y) print(reduce(lambda x, y: x * y, answers, integer(1, G.p)) % G.p)
def setup(security_parameter): G = IntegerGroupQ() G.paramgen(security_parameter) g = G.randomG() sk = G.random() return G, g, sk
class Params: def __init__(self, p=0, q=0, g=0, num_bits=2048): # IntegerGroupQ seems to be used as the Schnorr subgroup of order q self.group = IntegerGroupQ(0) self.num_bits = num_bits # Pick or set the Z_p and Z_q groups, along with the # residuosity parameter 'r' of the generator 'g' of Z_q if (p == 0 and q != 0) or (p != 0 and q == 0): raise ValueError('p and q must be either both set or unset') else: self.group.p, self.group.q, self.group.r = p, q, 2 self.p = self.group.p self.q = self.group.q self.r = self.group.r self.g = g; def generate(self, num_bits=None): # Passing r=2 here, even though it defaults to 2 if num_bits is not None: self.num_bits = num_bits self.group.paramgen(self.num_bits, 2) self.p = self.group.p self.q = self.group.q self.r = self.group.r # Randomly pick a generator g for Z_q # g \in [0, p), g = h^2 mod p, h \in [0, p) self.g = self.group.randomG() def __str__(self): return str({ 'p': str(self.p), 'q': str(self.q), 'g': str(self.g), 'r': str(self.r), 'num_bits': str(self.num_bits)}) def setParams(self, params=None): global default if params is None: params = default self.p = params.p self.q = params.q self.g = params.g self.group = params.group def groupHash(self, msg, r): msg = Conversion.siginput2integer(msg) if isinstance(r, integer) == False: raise TypeError("Expected r to be of type 'integer', got " + type(r)) return self.group.hash(msg, r) def serialize(self): return json.dumps({ 'p': serialize(self.p), 'q': serialize(self.q), 'g': serialize(self.g), 'r': str(self.r), 'num_bits': str(self.num_bits) }) @classmethod def unserialize(cls, data): params = json.loads(data) p = deserialize(params['p']) q = deserialize(params['q']) r = int(params['r']) g = deserialize(params['g']) num_bits = int(params['num_bits']) # TODO: assert num_bits is 'correctish' w.r.t. p/q/g ret = Params(p, q, g, num_bits) ret.r = r return ret def __eq__(self, other): return isinstance(other, self.__class__) and\ self.group.p == other.group.p and\ self.group.q == other.group.q and\ self.group.r == other.group.r and\ self.p == other.p and\ self.q == other.q and\ getMod(self.g) == getMod(other.g) and\ self.g == other.g def __ne__(self, other): return not self.__eq__(other)
from random import shuffle from charm.toolbox.integergroup import IntegerGroupQ, integer from charm.core.math.integer import reduce as reduce_mod from utils import Polynomial, LI G = IntegerGroupQ() G.paramgen(1024) g = G.randomG() def gen_coeffs(degree): return [G.random() for _ in range(degree + 1)] def main(): d_p = 5 # degree of polynomial P k = 4 # Security parameter and degree of polynomial s d = k * d_p # degree of polynomials P_x and Q m = 2 # Sender has polynomial P of degree d_p P = Polynomial(gen_coeffs(d_p)) # Sender generates random masking polynomial P_x of degree d P_x = Polynomial(gen_coeffs(d)) # P_x(0) = 0 P_x[0] = integer(0, G.q) # Sender defines bivariate polynomial Q which holds Q(0,y) = P(y) Q = lambda x, y: reduce_mod(P_x(x) + P(y)) # Receiver generates alpha alpha = G.random()