def compute_denominators(k, q): """Computes denominators for Lagrange basis polynomials. Uses distinct points 1, ...,k Arguments: k -- number of basis polynomials q -- the order of the group """ denominators = [] temp = Bn(1) for i in range(1, k + 1): if i == 1: for j in range(2, k + 1): elem = i - j temp = temp.mod_mul(elem, q) elif i == k: elem = 1 - k temp = temp.mod_mul(elem, q) else: inverse = Bn(i - 1 - k) inverse = inverse.mod_inverse(q) elem = i - 1 temp = temp.mod_mul(elem, q) temp = temp.mod_mul(inverse, q) denominators.append(temp) return denominators
def point_double(a, b, p, x, y): """Define "doubling" an EC point. A special case, when a point needs to be added to itself. Reminder: lam = (3 * xp ^ 2 + a) * (2 * yp) ^ -1 (mod p) xr = lam ^ 2 - 2 * xp yr = lam * (xp - xr) - yp (mod p) Returns the point representing the double of the input (x, y). """ # ADD YOUR CODE BELOW if x is None and y is None: return None, None xsq = x.mod_mul(x, p) xsq3 = Bn(3).mod_mul(xsq, p) num = xsq3.mod_add(a, p) y2 = Bn(2).mod_mul(y, p) y2inv = y2.mod_inverse(m=p) lam = num.mod_mul(y2inv, p) xr = lam.mod_mul(lam, p) xr = xr.mod_sub(x, p) xr = xr.mod_sub(x, p) yr = lam.mod_mul(x.mod_sub(xr, p), p) yr = yr.mod_sub(y, p) return (xr, yr) xr, yr = None, None return xr, yr
def gen_key(): """Example naive RSA key generation""" p = Bn.get_prime(512) q = Bn.get_prime(512) m = p * q phi = (p - 1) * (q - 1) e = Bn(2**16 + 1) d = e.mod_inverse(phi) pub = (e, m) priv = (d,) return pub, priv
def __lagrange(i, index_list, p): ''' Calculate lagrange coefficient ''' top = Bn(1) bottom = Bn(1) for j in index_list: if j != i: top = (top * j) bottom = (bottom * (j-i)) return top.mod_mul(bottom.mod_inverse(p), p)
def compute_cardinalities( self, secret: Bn, reply: List[bytes], published: Tuple[int, CuckooFilter]) -> List[int]: """ Compute the cardinalyty of the intersection of sets between the reply to a query and the list of lists of points published by the server. :param secret: secret with which the query was encrypted :param reply: reply from the server :param published: list of lists of point published by the server :return: list of cardinalities for the intersection between the reply and each published list of points. """ n_docs = published[0] published_data = published[1] secret_inv = secret.mod_inverse(self.group.order()) cardinalities = [] # For optimisation the following assumptions are made # - all keywords in the query are different. # - all keywords in the document are different. kwds_dec = list() for kwd_h in reply: kwd_pt = EcPt.from_binary(kwd_h, self.group) kwd_pt_dec = secret_inv * kwd_pt kwd_bytes = kwd_pt_dec.export() kwds_dec.append(kwd_bytes) for doc_id in range(n_docs): n_matches = 0 encoded_doc_id = doc_id.to_bytes(DOC_ID_SIZE, byteorder="big") for kwd_dec in kwds_dec: kwd_docid_bytes = kwd_encode(encoded_doc_id, kwd_dec) if published_data.contains(kwd_docid_bytes): n_matches += 1 cardinalities.append(n_matches) return cardinalities
def lagrangian(i, n, chi, q): """Evaluates Lagrange basis polynomial l_i at point x. Distinct points are 1, 2, ..., n + 1. Returns nonzero field element. Arguments: i -- polynomial index in range 1, 2, ..., n + 1 chi -- input value of the polynomial q -- the order of the group """ numerator = Bn(1) denominator = Bn(1) for j in range(1, n + 2): if i == j: continue numerator = numerator.mod_mul(chi - j, q) elem = i - j denominator = denominator.mod_mul(elem, q) return numerator.mod_mul(denominator.mod_inverse(q), q)
def point_double(a, b, p, x, y): """Define "doubling" an EC point. A special case, when a point needs to be added to itself. Reminder: lam = (3 * xp ^ 2 + a) * (2 * yp) ^ -1 (mod p) xr = lam ^ 2 - 2 * xp yr = lam * (xp - xr) - yp (mod p) Returns the point representing the double of the input (x, y). """ assert Bn.is_prime(p) # Point at infinity if x is None and y is None: return (None, None) xr, yr = None, None lam = ((3 * (x * x) + a) * Bn.mod_inverse((2 * y), p)) % p xr = ((lam * lam) - 2 * x) % p yr = (lam * (x - xr) - y) % p return xr, yr
def point_add(a, b, p, x0, y0, x1, y1): """Define the "addition" operation for 2 EC Points. Reminder: (xr, yr) = (xq, yq) + (xp, yp) is defined as: lam = (yq - yp) * (xq - xp)^-1 (mod p) xr = lam^2 - xp - xq (mod p) yr = lam * (xp - xr) - yp (mod p) Return the point resulting from the addition. Raises an Exception if the points are equal. """ ## Curve: y^2 = x^3 + ax + b # ADD YOUR CODE BELOW assert isinstance(p, Bn) and p > 0 assert Bn.is_prime(p) if (x0 is None) and (y0 is None): if x1 is None and y1 is None: return None, None else: return x1, y1 elif x1 is None and y1 is None: return x0, y0 if x0 == x1 and y0 == y1: raise Exception('EC Points must not be equal') xr, yr = None, None try: lam = ((y0 - y1) * (Bn.mod_inverse((x0 - x1), p))) % p xr = (lam**2 - x0 - x1) % p yr = (lam * (x0 - xr) - y0) % p return (xr, yr) except Exception: return (None, None)
def compute_cardinality(self, secret: Bn, reply: List[bytes], published) -> int: """ Compute the cardinalyty of the intersection of sets between the reply to a query and the list of points published by the server. :param reply: reply from the server :param published: list of point published by the server :return: cardinalityof the intersection of sets """ secret_inv = secret.mod_inverse(self.group.order()) kwds = list() for kwd_h in reply: kwd_pt = EcPt.from_binary(kwd_h, self.group) kwd_pt_dec = secret_inv * kwd_pt kwd_bytes = kwd_pt_dec.export() kwds.append(kwd_bytes) # The intersection of the 2 sets is the number of matches. return len(set(kwds) & set(published))