def attr_to_bn(self, k, v, t): " Transforms attr to Bn" (_, _, _, o) = self.params key = Bn.from_binary(sha512("".join(k)).digest()) % o value = Bn.from_binary(sha512("".join(v)).digest()) % o timeout = Bn.from_binary(sha512(str(t)).digest()) % o return key, value, timeout
def verify(self, message, sig): """ Verify the message and the signature """ assert len(message) == 32 lr, r, ls, s = unpack("H32sH32s", sig) sig = Bn.from_binary(r[:lr]), Bn.from_binary(s[:ls]) return do_ecdsa_verify(self.G, self.pub, sig, message)
def test(parallel=0): from client import Client G = EcGroup(713) o = G.order() g = G.generator() o_bytes = int(math.ceil(math.log(float(int(o))) / math.log(256))) s = (G, o, g, o_bytes) mix1privk = Bn.from_binary( base64.b64decode("z7yGAen5eAgHBRB9nrafE6h9V0kW/VO2zC7cPQ==")) mix1pubk = mix1privk * g mix2privk = Bn.from_binary( base64.b64decode("266YjC8rEyiEpqXCNXCz1qXTEnwAsqz/tCyzcA==")) mix2pubk = mix2privk * g privk = Bn.from_binary( base64.b64decode("DCATXyhAkzSiKaTgCirNJqYh40ha6dcXPw3Pqw==")) recpubk = privk * g dbprivk = Bn.from_binary( base64.b64decode("/m8A5kOfWNhP4BMcUm7DF0/G0/TBs2YH8KAYzQ==")) dbpubk = dbprivk * g m1m2 = (mix1privk * G.order().random()) * mix2pubk m1db = (mix1privk * G.order().random()) * dbpubk m1c = (mix1privk * G.order().random()) * recpubk m2db = (mix2privk * G.order().random()) * dbpubk m2c = (mix2privk * G.order().random()) * recpubk cdb = (privk * G.order().random()) * dbpubk pub = [ Actor("M1", 8001, "127.0.0.1", (mix1pubk, s)), Actor("M2", 8002, "127.0.0.1", (mix2pubk, s)), Actor("C", 8007, "127.0.0.1", (dbpubk, s)), Actor("DB", 9999, "127.0.0.1", (recpubk, s)) ] print "C" receiver = Client('C', 9999, "127.0.0.1", s, privk, recpubk, pub, urandom(24)) receiver.privk = privk receiver.pubk = recpubk receiver.group = s receiver.shared_secrets = {"M1": m1c, "M2": m2c, "DB": cdb} receiver.cascade = parallel data = receiver.sendCascade() print "cascade -----------------------------------------------------" print data receiver.keys = [] data = receiver.sendParallel() print "\nparallel --------------------------------------------------" print data print "init finished"
def __init__(self, ip, port, n, m): #, arch, enc, el1, el2, el3, el4, ports): print("CF: init") self.done = Deferred() self.c_proto = None self.name = "C" self.ip = ip # ['34.251.168.214','34.249.66.110','34.250.248.33'] self.port = port #[8001,8002,8003] self.n = n self.m = m self.G = EcGroup(713) self.o = self.G.order() self.g = self.G.generator() self.o_bytes = int( math.ceil(math.log(float(int(self.o))) / math.log(256))) nn = int(math.ceil(self.n / self.m) * self.m) #self.data = pack.encode([self.name, "STT", 9842, -1, "", 0, 1, [1, 1, [[ Actor("DB", "127.0.0.1", 8000, ""), int(nn/self.m)], ["", Bn.from_binary(base64.b64decode("z7yGAen5eAgHBRB9nrafE6h9V0kW/VO2zC7cPQ=="))*self.g], nn, 1, [Actor("M1", "127.0.0.1",8001, ""), Actor("M2", "127.0.0.1",8002, ""), Actor("M3", "127.0.0.1", 8003, "")]]]]) # cascade layered self.data = pack.encode([ self.name, "STT", 1342, -1, "", 0, 1, [ 1, 0, [[Actor("DB", "127.0.0.1", 8000, ""), int(nn / self.m)], [ Bn.from_binary( base64.b64decode( "z7yGAen5eAgHBRB9nrafE6h9V0kW/VO2zC7cPQ==")) * self.g, Bn.from_binary( base64.b64decode( "z7yGAen5eAgHBRB9nrafE6h9V0kW/VO2zC7cPQ==")) * self.g ], nn, 1, [ Actor("M1", "127.0.0.1", 8001, ""), Actor("M2", "127.0.0.1", 8002, ""), Actor("M3", "127.0.0.1", 8003, "") ]] ] ]) #cascade rebuild #rounds= int(math.ceil(m *math.log(math.sqrt(nn)) /2)) #self.data = pack.encode([self.name, "STT", 98621, -1, "", 0, 1, [0, 1, [[ Actor("DB", "127.0.0.1", 8000, ""), int(nn/self.m)], ["", Bn.from_binary(base64.b64decode("z7yGAen5eAgHBRB9nrafE6h9V0kW/VO2zC7cPQ=="))*self.g], ["", Bn.from_binary(base64.b64decode("266YjC8rEyiEpqXCNXCz1qXTEnwAsqz/tCyzcA=="))*self.g], nn, rounds, [Actor("M1", "127.0.0.1",8001, ""), Actor("M2", "127.0.0.1",8002, ""), Actor("M3", "127.0.0.1", 8003, "")]]]]) #parallel layered #rounds= int(math.ceil(4 * m *(math.log(nn)+1))) #self.data = pack.encode([self.name, "STT", 91864, -1,"", 0, 1, [0,0,[[ Actor("DB", "localhost", 8000, ""), int(nn/self.m)], [Bn.from_binary(base64.b64decode("z7yGAen5eAgHBRB9nrafE6h9V0kW/VO2zC7cPQ=="))*self.g, Bn.from_binary(base64.b64decode("z7yGAen5eAgHBRB9nrafE6h9V0kW/VO2zC7cPQ=="))*self.g], [Bn.from_binary(base64.b64decode("266YjC8rEyiEpqXCNXCz1qXTEnwAsqz/tCyzcA=="))*self.g, Bn.from_binary(base64.b64decode("266YjC8rEyiEpqXCNXCz1qXTEnwAsqz/tCyzcA=="))*self.g], nn, rounds, [Actor("M1", "localhost",8001, ""), Actor("M2", "localhost",8002, ""), Actor("M3", "localhost", 8003, "")]]]]) #parallel rebuild '34.251.168.214','34.249.55.110','34.250.248.33' print(nn / self.m, self.m, nn, int(math.ceil(2 * self.m * math.log(nn))), math.log(nn))
def enc(self, params, pub, m): """Encrypts the values of a group element""" print("CCA2EG: Enc") G, g1, o = params r1 = o.random() r2 = o.random() c11 = r1 * pub[0] + m c21 = r2 * pub[1] + m c12 = r1 * g1 c22 = r2 * g1 d = o.random() * g1 s1 = o.random() s2 = o.random() e11 = s1 * pub[0] + d e21 = s2 * pub[1] + d e12 = s1 * g1 e22 = s2 * g1 state = [g1, pub[0], pub[1], c11, c21, c12, c22, e11, e21, e12, e22] hash_c = self.challenge(state) c = Bn.from_binary(hash_c) % o z = c*m +d z1 = (r1 * c + s1) % o z2 = (r2 * c + s2) % o return ((c11, c12), (c21, c22), (e11, e12), (e21, e22), c, z, z1, z2)
def hashG1(self, sbin): """ Hashes a byte string into a point of G1. Example: >>> G = BpGroup() >>> g1 = G.gen1() >>> g1p = G.hashG1(b"Hello") >>> x = g1 + g1p """ if self.p is None: p = Bn() a, b = Bn(), Bn() _check(_C.BP_GROUP_get_curve(self.bpg, p.bn, a.bn, b.bn, _FFI.NULL)) self.p = p pt = G1Elem(self) xhash = sbin y = 1 ret = 0 while ret == 0: xhash = sha512(xhash).digest() x = Bn.from_binary(xhash) % self.p ret = _C.G1_ELEM_set_compressed_coordinates( self.bpg, pt.elem, x.bn, y, _FFI.NULL) _check(_C.G1_ELEM_is_on_curve(self.bpg, pt.elem, _FFI.NULL)) return pt
def BL_user_validation(user_state, idp_pub, msg_to_user, message=b''): (G, q, g, h, z, hs) = user_state.params # (z1, gam, zet, zet1, zet2, tau, eta) = user_private_state (a, a1p, a2p) = msg_to_user (y,) = idp_pub assert G.check_point(a) assert G.check_point(a1p) assert G.check_point(a2p) t1,t2,t3,t4,t5 = [q.random() for _ in range(5)] alph = a + t1 * g + t2 * y alph1 = user_state.gam * a1p + t3 * g + t4 * user_state.zet1 alph2 = user_state.gam * a2p + t5 * h + t4 * user_state.zet2 # Make epsilon H = [user_state.zet, user_state.zet1, alph, alph1, alph2, user_state.eta] Hstr = list(map(EcPt.export, H)) + [message] Hhex = b"|".join(map(b64encode, Hstr)) epsilon = Bn.from_binary(sha256(Hhex).digest()) % q e = epsilon.mod_sub(t2,q).mod_sub(t4, q) user_state.ts = [t1, t2, t3, t4, t5] user_state.message = message msg_to_issuer = e return msg_to_issuer
def prove_knowledge(self, pparam, prand, values): """ A non-interactive proof of knowledge of opening an commitment. Args: pparam (CommitPram): prameters prand (PedersenRand): commitment's secret values (Bn[]): commitment's values Returns: (PedersenProof) """ # sigma protocol's commitment phase r_h = pparam.q.random() r_vs = [pparam.q.random() for _ in range(len(values))] R = r_h * pparam.H R += pparam.group.wsum(r_vs, pparam.HS[:len(r_vs)]) # sigma protocol's challenge: Fiat-Shamir chash = sha256(self.commit.export() + R.export()).digest() e = Bn.from_binary(chash) % pparam.q # sigma protocol's response phase s_h = r_h - prand * e s_vs = [r - x * e for (x, r) in zip(values, r_vs)] return PedersenProof(e, (s_h, s_vs))
def process_raw_value(self, raw): """"process raw values. Args: raw_values (int, Bn mod q/string/bytes): committed value. Raises: Error: bad value encoding. values can only be Bn, bytes, string, or None. Returns: (Bn mod q): processed value """ val = None if raw is None: return None elif isinstance(raw, Bn): return raw elif isinstance(raw, bytes): val = sha256(raw).digest() elif isinstance(raw, str): val = sha256(raw.encode('utf8')).digest() elif isinstance(raw, int): return Bn(raw) else: raise Exception( "Bad commitment value encoding." "values can only be int, Bn, bytes, string, or None.") return Bn.from_binary(val) % self.q
def enc(pub, plaintext): """Naive RSA encryption""" e, m = pub plain = Bn.from_binary(plaintext) assert 1 < plain < m cipher = pow(plain, e, m) return cipher.binary()
def __init__(self, name, ip, port, prvk, cascade=1, layered=1): print "Mix: init", name, ip, port, prvk, cascade, layered #Mix initialization self.name = name # Name of the mix self.port = port # Port of the mix self.ip = ip # IP of the mix #Mix keys self.G = EcGroup(713) self.o = self.G.order() self.g = self.G.generator() self.o_bytes = int( math.ceil(math.log(float(int(self.o))) / math.log(256))) self.s = (self.G, self.o, self.g, self.o_bytes) self.prvk = Bn.from_binary( base64.b64decode( "/m8A5kOfWNhP4BMcUm7DF0/G0/TBs2YH8KAYzQ==")) #mix private key self.pubk = self.prvk * self.g #mix public key self.setup = (self.G, self.o, self.g, self.o_bytes, self.prvk, self.pubk) self.sessions = {} # Eviction session self.sessionlock = threading.Lock( ) #lock for accessing any information
def dec(pub, priv, ciphertext): """Naive RSA decryption. NOT const. time.""" _, m = pub d, = priv cipher = Bn.from_binary(ciphertext) assert 1 < cipher < m plain = pow(cipher, d, m) return plain.binary()
def __init__(self, arch, enc, el1, el2, el3, el4, ports): print("CF: init") self.done = Deferred() self.c_proto = None self.G = EcGroup(713) self.o = self.G.order() self.g = self.G.generator() self.o_bytes = int(math.ceil(math.log(float(int(self.o))) / math.log(256))) self.data = ["STT", int(urandom(2).encode('hex'),16), [ Actor("DB", "127.0.0.1", 8000, ""), 3]] if arch: if enc: self.data[2].extend([["", Bn.from_binary(base64.b64decode(el2))]]) else: self.data[2].extend([[Bn.from_binary(base64.b64decode(el2)), Bn.from_binary(base64.b64decode(el2))]]) else: if enc: self.data[2].extend([["", Bn.from_binary(base64.b64decode(el2))],[["", Bn.from_binary(base64.b64decode(el4))]]]) else: self.data[2].extend([ [Bn.from_binary(base64.b64decode(el1)), Bn.from_binary(base64.b64decode(el2))], [Bn.from_binary(base64.b64decode(el3)), Bn.from_binary(base64.b64decode(el4))]]) actors=[] for i in range(len(ports)): actors.extend([Actor("M"+str(i), "127.0.0.1", 8001+i, "")]) self.data[2].extend([[actors]])
def challenge(elements): """Packages a challenge in a bijective way""" elem = [len(elements)] + elements elem_str = list(map(str, elem)) elem_len = list(map(lambda x: "%s||%s" % (len(x) , x), elem_str)) state = "|".join(elem_len) H = sha256() H.update(state.encode("utf8")) return Bn.from_binary(H.digest())
def compute_blind_challenge(self, commit_message, m): """Receive a SignerCommitMessage from the signer and start the procedure of getting a signature on message m from the signer. Args: commit_message (SignerCommitMessage):response from AbeSigner.commit() m (bytes): message to sign. If m is a string, then the procedure encodes it as 'utf8' """ self.rnd = commit_message.rnd self.Z1 = self._compute_z1(self.rnd) self.Z2 = self.public.Z - self.Z1 self.A, self.B1, self.B2 = ( commit_message.A, commit_message.B1, commit_message.B2, ) if isinstance(m, str): m = m.encode('utf8') if not isinstance(m, bytes): raise Exception("Bad encoding in message") self.message = m assert self.param.group.check_point(self.A) assert self.param.group.check_point(self.B1) assert self.param.group.check_point(self.B2) self.blinder = self.param.q.random() self.tau = self.param.q.random() self.Eta = self.tau * self.public.Z self.Zeta = self.blinder * self.public.Z self.Zeta1 = self.blinder * self.Z1 self.Zeta2 = self.Zeta - self.Zeta1 self.t = [self.param.q.random() for __ in range(5)] self.Alpha = self.A + self.t[0] * self.param.G + self.t[ 1] * self.public.PK self.Beta1 = (self.blinder * self.B1 + self.t[2] * self.param.G + self.t[3] * self.Zeta1) self.Beta2 = (self.blinder * self.B2 + self.t[4] * self.param.H + self.t[3] * self.Zeta2) h = sha256(b'||'.join([ self.Zeta.export(), self.Zeta1.export(), self.Alpha.export(), self.Beta1.export(), self.Beta2.export(), self.Eta.export(), self.message ])).digest() self.epsilon = Bn.from_binary(h) % self.param.q self.e = (self.epsilon - self.t[1] - self.t[3]) % self.param.q return self.e
def challenge(self, elements): """Packages a challenge in a bijective way""" elem = [len(elements)] + elements elem_str = map(str, elem) elem_len = map(lambda x: "%s||%s" % (len(x), x), elem_str) state = "|".join(elem_len) H = sha256() H.update(state.encode("utf8")) return Bn.from_binary(H.digest()) % self.o
def test_bsps_proof(): """ create GS proof that sig verifies with the signature and all but the first message secret """ gsp = GSProof() gsp.ExtGen() params = gsp.P sps = BSPS() sk, pk = sps.keygen(params) u, w, v, z = sk U, W, V, Z = pk t = Bn(7) m1 = [gsp.g1 * t, gsp.G.hashG1(b"Hello World!")] m2 = [Bn.from_binary(b"Hello you!") * gsp.g2] for i in range(len(W) - len(m1)): m1.append(G1Elem.inf(gsp.G)) for i in range(len(U) - len(m2)): m2.append(G2Elem.inf(gsp.G)) sig = sps.sign(params, sk, m1, m2) print("Does the signature verify?", sps.verify(params, pk, m1, m2, sig)) PK = [[], []] for i in range(len(U)): PK[0].append(gsp.Commit({"group": 1, "type": "pub", "value": U[i]})) for i in range(len(W)): PK[1].append(gsp.Commit({"group": 2, "type": "pub", "value": W[i]})) PK.append(gsp.Commit({"group": 2, "type": "pub", "value": V})) PK.append(gsp.Commit({"group": 2, "type": "pub", "value": Z})) M1 = [gsp.Commit({"group": 1, "type": "bas", "value": gsp.g1})] for i in range(len(m1) - 1): M1.append(gsp.Commit({"group": 1, "type": "com", "value": m1[i + 1]})) M2 = [] for i in range(len(m2)): M2.append(gsp.Commit({"group": 2, "type": "com", "value": m2[i]})) SIG = [ gsp.Commit({ "group": 1, "type": "com", "value": sig[0] }), gsp.Commit({ "group": 1, "type": "com", "value": sig[1] }), gsp.Commit({ "group": 2, "type": "com", "value": sig[2] }) ] verify, result = proof_bsps_hidemandsig(gsp, PK, M1, M2, t, SIG) assert verify
def pok_open_comm_verify(public_key, A, proof): #Verifies the ZKproof of knowledge of opening to a commitment A G, commitment_key = public_key x, f, z = proof C = commit(public_key, f, z) + x * A p = G.order() state = ['Opening', G.nid(), list(commitment_key), A, C] hash_x = challenge(state) y = Bn.from_binary(hash_x) % p return x == y
def verify(params, h, g, proof, m=""): """Verify the statement ZK(x ; h = g^x)""" G, _, o = params c, r = proof W = (r * g + c * h) state = ['schnorr', G.nid(), g, h, m, W] hash_c = challenge(state) c2 = Bn.from_binary(hash_c) % o return c == c2
def test_redeem(self): ## run service checker_service_process = Process( target=tumbler_contract.run_checker_service) checker_service_process.start() time.sleep(0.1) ## create transaction # init init_transaction = tumbler.init() token = init_transaction['transaction']['outputs'][0] # initialise petition create_transaction = tumbler.create_tumbler((token, ), None, None, vvk, auth_sig) old_list = create_transaction['transaction']['outputs'][1] # some crypto # ------------------------------------ hasher = sha256() hasher.update(dumps(ID).encode('utf8')) hasher.update(dumps(merchant_addr).encode('utf8')) m = Bn.from_binary(hasher.digest()) (priv, pub) = elgamal_keygen(bp_params) (cm, c, proof_s) = prepare_blind_sign(bp_params, m, pub) enc_sigs = [ blind_sign(bp_params, ski, cm, c, pub, proof_s) for ski in sk ] (h, enc_epsilon) = zip(*enc_sigs) sigs = [(h[0], elgamal_dec(bp_params, priv, enc)) for enc in enc_epsilon] sig = aggregate_th_sign(bp_params, sigs) sig = randomize(bp_params, sig) # reveal ID and merchant addr #print(verify(bp_params, vvk, m, sig)) # ------------------------------------ # add signature to th petition transaction = tumbler.redeem( (old_list, ), None, (dumps(ID), dumps(merchant_addr)), sig, vvk, ) ## submit transaction response = requests.post('http://127.0.0.1:5000/' + tumbler_contract.contract_name + '/redeem', json=transaction_to_solution(transaction)) self.assertTrue(response.json()['success']) ## stop service checker_service_process.terminate() checker_service_process.join()
def build_proof(self, env, message=""): """Generates a proof within an environment of assigned public and secret variables.""" self._check_env(env) # Do sanity check on the proofs if __debug__: for base, expr in self.proofs: xGen = base.val(env) xExpr = expr.val(env) try: assert xGen == xExpr except: raise Exception("Proof about '%s' does not hold." % base.name) G = self.G order = G.order() ## Make a list of all the public state state = ['ZKP', G.nid(), message] #print('1: ', state) for v in sorted(self.Const.keys()): state += [env[v]] for v in sorted(self.Pub.keys()): state += [env[v]] #print('2: ', state) ## Set witnesses for all secrets witnesses = dict(env.items()) for w in self.Sec.keys(): assert w in witnesses witnesses[w] = order.random() ## Compute the first message and add it to the state for base, expr in self.proofs: Cw = expr.val(witnesses) state += [Cw] #print('3: ', state) ## Compute the challenge using all the state hash_c = challenge(state) c = Bn.from_binary(hash_c) % order ## Compute all the resources responses = dict(env.items()) for w in self.Sec.keys(): responses[w] = (witnesses[w] - c * env[w]) % order for v in self.Const: del responses[v] return (c, responses)
def __init__(self, key_bytes, public=True): """ Make a key given a public or private key in bytes """ self.G = _globalECG if public: self.sec = None self.pub = EcPt.from_binary(key_bytes, self.G) self.optim = None else: self.sec = Bn.from_binary(sha256(key_bytes).digest()) self.pub = self.sec * self.G.generator() self.optim = do_ecdsa_setup(self.G, self.sec)
def verify(self, params, h, g, proof, m=""): #print("SOK: Verify") """Verify the statement ZK(x ; h = g^x)""" o, G, _ = params c, r = proof W = (r * g + c * h) state = ['schnorr', o, g.export(), h.export(), m, W.export()] hash_c = self.challenge(state) c2 = Bn.from_binary(hash_c) % o return c == c2
def mix_operate(message, triplet, setup): mname, mpub, msec = triplet elem, forward, backwards = message G, o, g, o_bytes = setup aes = Cipher("AES-128-CTR") # Derive first key k1 = KDF((msec * elem).export()) # Derive the blinding factor b = Bn.from_binary(k1.b) % o new_elem = b * elem # Check the forward MAC mac1 = hmac.new(k1.kmac, forward[20:], digestmod=sha1).digest() assert forward[:20] == mac1 # Decrypt the payload enc = aes.dec(k1.kenc, k1.iv) pt = enc.update(forward[20:]) pt += enc.finalize() # Parse the forward message xfrom, xto, the_bs, new_forw = pt[:4], pt[4:8], pt[8:8+o_bytes], pt[8+o_bytes:] old_bs = Bn.from_binary(the_bs) # Now encrypt the return part k2 = KDF(((msec * old_bs) * elem).export()) new_bs = old_bs.mod_inverse(o).binary() enc = aes.enc(k2.kenc, k2.iv) new_back_body = enc.update(xto + xfrom + new_bs + backwards) new_back_body += enc.finalize() mac2 = hmac.new(k2.kmac, new_back_body, digestmod=sha1).digest() new_back = mac2 + new_back_body return ((xfrom, xto), (new_elem, new_forw, new_back) )
def prove(params, h, g, x, m=""): """Schnorr proof of the statement ZK(x ; h = g^x)""" assert x * g == h G, _, o = params w = o.random() W = w * g state = ['schnorr', G.nid(), g, h, m, W] hash_c = challenge(state) c = Bn.from_binary(hash_c) % o r = (w - c * x) % o return (c, r)
def test_sign(): sps = BSPS() params = sps.setup() o, G, g1, g2, e = params sk, pk = sps.keygen(params) from petlib.bn import Bn m = [G.hashG1(b"Hello World!"), G.hashG1(b"Hello me!")] n = [Bn.from_binary(b"Hello you!").mod_add(Bn(0), o) * g2] sig = sps.sign(params, sk, m, n) print(sig)
def prove(self, params, h, g, x, m=""): #print("SOK: Prove") """Schnorr proof of the statement ZK(x ; h = g^x)""" assert x * g == h o, G, _ = params w = o.random() W = w * g state = ['schnorr', o, g.export(), h.export(), m, W.export()] hash_c = self.challenge(state) c = Bn.from_binary(hash_c) % o r = (w - c * x) % o return (c, r)
def ext_hook(code, data): if code==0: num = Bn.from_binary(data[1:]) if data[0] == ord("-") or data[0] == "-": return -num return num elif code==1: nid = msgpack.unpackb(data) return EcGroup(nid) elif code == 2: nid, ptdata = msgpack.unpackb(data) return EcPt.from_binary(ptdata, EcGroup(nid)) return msgpack.ExtType(code, data)
def build_proof(self, env, message=""): """Generates a proof within an environment of assigned public and secret variables.""" self._check_env(env) # Do sanity check on the proofs if __debug__: for base, expr in self.proofs: xGen = base.val(env) xExpr = expr.val(env) try: assert xGen == xExpr except: raise Exception("Proof about '%s' does not hold." % base.name) G = self.G order = G.order() ## Make a list of all the public state state = ['ZKP', G.nid(), message] for v in sorted(self.Const.keys()): state += [env[v]] for v in sorted(self.Pub.keys()): state += [env[v]] ## Set witnesses for all secrets witnesses = dict(env.items()) for w in self.Sec.keys(): assert w in witnesses witnesses[w] = order.random() ## Compute the first message and add it to the state for base, expr in self.proofs: Cw = expr.val(witnesses) state += [Cw] ## Compute the challenge using all the state hash_c = challenge(state) c = Bn.from_binary(hash_c) % order ## Compute all the resources responses = dict(env.items()) for w in self.Sec.keys(): responses[w] = (witnesses[w] - c * env[w]) % order for v in self.Const: del responses[v] return (c, responses)
def BL_check_signature(params, issuer_pub, signature): (G, q, g, h, z, hs) = params (y,) = issuer_pub (m, zet, zet1, zet2, om, omp, ro, ro1p, ro2p, mu) = signature lhs = (om + omp) % q rhs_h = [zet, zet1, ro * g + om * y, ro1p * g + omp * zet1, ro2p * h + omp * zet2, ## problem mu * z + omp * zet] Hstr = list(map(EcPt.export, rhs_h)) + [m] Hhex = b"|".join(map(b64encode, Hstr)) rhs = Bn.from_binary(sha256(Hhex).digest()) % q if rhs == lhs: return m else: return False
def verify_proof(self, env, sig, message="", strict=True): """Verifies a proof within an environment of assigned public only variables.""" ## Select the constants for the env env_l = [(k,v) for k,v in env.items() if k in self.Const] if __debug__ and strict: env_not = [k for k,v in env.items() if k not in self.Const] if len(env_not): raise Exception("Did not check: " + (", ".join(env_not))) c, responses = sig responses = dict(list(responses.items()) + env_l) ## Ensure all variables we need are here self._check_env(responses) ## Define the maths group we work in G = self.G order = G.order() ## Make a list of all the public state state = ['ZKP', G.nid(), message] for v in sorted(self.Const.keys()): state += [responses[v]] for v in sorted(self.Pub.keys()): state += [responses[v]] ## Compute the first message and add it to the state for base, expr in self.proofs: Cr = expr.val(responses) Cx = base.val(responses) Cw = Cr + c * Cx state += [Cw] ## Compute the challenge using all the state hash_c = challenge(state) c_prime = Bn.from_binary(hash_c) % order ## Check equality return (c == c_prime)
def BL_verify_age(params, issuer_pub, num_attributes, signature, sig, gam_hs, zet1p, gam_g): m = BL_check_signature(params, issuer_pub, signature) assert m != False (G, q, g, h, z, hs) = params (m, zet, zet1, zet2, om, omp, ro, ro1p, ro2p, mu) = signature zk = BL_show_zk_proof(params, num_attributes) #we get this from the user env = ZKEnv(zk) # Constants env.g = g env.z = z env.zet = zet env.zet1 = zet1p env.hs = gam_hs[:num_attributes + 1] ## Extract the proof res = zk.verify_proof(env.get(), sig) assert res lhs = (om + omp) % q rhs_h = [zet, zet1, ro * g + om * y, ro1p * g + omp * zet1, ro2p * h + omp * zet2, ## problem mu * z + omp * zet] Hstr = list(map(EcPt.export, rhs_h)) + [m] Hhex = b"|".join(map(b64encode, Hstr)) rhs = Bn.from_binary(sha256(Hhex).digest()) % q # Check the (future) ZK proof # assert rnd * gam_g + R * gam_hs[0] + L1 * gam_hs[1] + L2 * gam_hs[2] == zet1 assert rnd * gam_g + R * gam_hs[0] + L1 * gam_hs[1] == zet1 - Age * gam_hs[2] return m
def client(): reader, writer = yield from asyncio.streams.open_connection( '127.0.0.1', 12345, loop=loop)#Service Provider reader2, writer2 = yield from asyncio.streams.open_connection( '127.0.0.1', 7878, loop=loop)#Identity Provider def send(msg, writer): print("> " + str(msg)) writer.write((msg + '\n').encode("utf-8")) print(msg) print(type(msg.encode("utf8"))) def sendBin(data, writer): #print("bin>" + str(data)) writer.write(data + b'fireintheboof') #writer.write_eof() def recv(reader): msgback = (yield from reader.readline()).decode("utf-8").rstrip() #print("< " + msgback) return msgback # send a line #send("buy", writer) sendBin(b'buys', writer) msg = yield from recv(reader) #if repr('id') == msg: if True: startWait = time.time() print("ok i go get ID") #generating, encoding, and sending parameters to both sp and idp params = BL_setup() G, q, g, h, z, hs = params endWait = time.time() sendBin(b'para' + encode(params), writer) sendBin(b'para' + encode(params), writer2) print('Time to generate params: ', endWait-startWait) seri_enc_idp_pub = yield from reader2.readuntil(separator=b'fireinthepub') if seri_enc_idp_pub[0:4] == b'mypb': #idp_pub = tuple(list_enc_idp_pub) idp_pub = decode(seri_enc_idp_pub[4:-12]) sendBin(b'ipub' + encode(idp_pub) + b'fireintheboof', writer) #h = Hmac(b'sha256', b'ServiceProviderID') L2 = q.random() Age = 21 #new #N = params[0].hash_to_point('service_name') #pseudonym = x * N #encode and send user_commit to idp LT_user_state, user_commit = BL_user_setup(params, [L2, Age]) startTimeProof = time.time() C = LT_user_state.C R = LT_user_state.R q = LT_user_state.params[1] H = params[0].hash_to_point(b'service_name') ID = L2 * H wR_id = q.random() wx_id = q.random() Wit = wR_id * hs[0] + wx_id * hs[1] WID_id = wx_id * H print(hs) stuffToHash = (Wit, WID_id, C, g, h, z, hs[0], hs[1], hs[2], hs[3], H) cstr = b",".join([hexlify(x.export()) for x in stuffToHash]) chash = sha256(cstr).digest() c = Bn.from_binary(chash) rR_id = wR_id - c * R rx_id = wx_id - c * L2 endTimeProof = time.time() print('Proof took: ', endTimeProof - startTimeProof) responses = (rR_id, rx_id) values = (user_commit, C, c, responses, L2, Age) sendBin(b'ucmt' + encode(values), writer2) msg2 = yield from reader2.readuntil(separator=b'fireintheboof') msg_to_user = decode(msg2[:-13]) BL_user_prep(LT_user_state, msg_to_user) #request idp's pubkey #sendBin(b'pubk', writer2) #inform idp Im prepped and ready to go sendBin(b'prep', writer2) msg3 = yield from reader2.readuntil(separator=b'fireintheboof') msg_to_user2 = decode(msg3[:-13]) #generate msg to idp msg_to_idp = BL_user_validation(LT_user_state, idp_pub, msg_to_user2) #encode, serialise, and send msg to idp sendBin(b'msgi' + encode(msg_to_idp), writer2) #receive last message from idp, generate signature msg4 = yield from reader2.readuntil(separator=b'fireintheboof') msg_to_user3 = decode(msg4[:-13]) sig = BL_user_validation_2(LT_user_state, msg_to_user3) sendBin(b'vsig' + encode(sig) + b'fireintheboof', writer) print('idppub: ', idp_pub) signature_gamhs = BL_user_prove_cred(LT_user_state) signature = signature_gamhs[0] gam_hs = signature_gamhs[1] gam_g = signature_gamhs[2] sendBin(b'vsg2' + encode(signature) + b'fireintheboof', writer) zet1p = LT_user_state.zet1 - Age * gam_hs[2] newStuff = (gam_hs, Age) #prove age #get variabels rnd = LT_user_state.rnd R = LT_user_state.R q = LT_user_state.params[1] wrnd = q.random() wR = q.random() wx = q.random() Wzet1p = wrnd * gam_g + wR * gam_hs[0] + wx * gam_hs[1] #remember to get gam_g WID = wx * params[0].hash_to_point(b'service_name') stuffToHash = (gam_g, Wzet1p, WID, zet1p, gam_hs[0], gam_hs[1], gam_hs[2], H) cstr = b",".join([hexlify(x.export()) for x in stuffToHash]) chash = sha256(cstr).digest() c = Bn.from_binary(chash) rrnd = wrnd - c*rnd rR = wR - c*R rx = wx - c*L2 responses = (rrnd, rR, rx) newStuff = (c, responses, gam_g, gam_hs, Age, L2) """Wprime = rrnd * gam_g + rR * gam_hs[0] + rx * gam_hs[1] + c * zet1p print(Wzet1p) print(Wprime)""" sendBin(b'page' + encode(newStuff) + b'fireintheboof', writer) #Close the connections to get rid of IncompleteReadError cmd = "asd" #cmd, *args = msg2.rstrip().split(' ') if repr('IDCONFIRMED') == cmd: #for encryption """key = keyGen() print(repr(key)) ciphertext = encrypt_AES(key, "HAUHEUheuahehaeuhUAEHUHEAUh") serialisedCiphertext = pickle.dumps(ciphertext) send(('key ' + repr(key)) + " " + repr(serialisedCiphertext), writer)""" """params = setup() G = params[0] C = EcPt.from_binary(literal_eval(args[0]), G) r = Bn.from_binary(literal_eval(args[1])) secrets = pickle.loads(literal_eval(args[2])) proof = proveCommitment(params, C, r, secrets) c, responses = proof #Here is where I send the proof to the service provider seriRes = pickle.dumps(responses) send('Proof ' + repr(c) + " " + repr(seriRes), writer) print("the end")""" end = time.time() print("Time: ", end-start) writer.close() writer2.close()
def to_challenge(elements): """ Generates a Bn challenge by hashing a number of EC points """ Cstring = b",".join([hexlify(x.export()) for x in elements]) Chash = sha256(Cstring).digest() return Bn.from_binary(Chash)
def _handle_client(self, client_reader, client_writer): global paramsReceived while True: try: # data = (yield from client_reader.readline()).decode("utf-8") startWait = time.time() data = yield from client_reader.readuntil(separator=b'fireintheboof') endWait = time.time() print('IO wait: ', data[0:4], endWait - startWait) cmd = data[0:4] strippedData = data[4:-13] except asyncio.streams.IncompleteReadError: data = None if not data: # an empty string means the client disconnected break # cmd, *args = str(data).rstrip().split(' ') if cmd == 'id': """secrets = [3, 645, 3430, 420] seriSecrets = pickle.dumps(secrets) params = setup() C, r = commit(params, secrets) G = params[0] exportedC = C.export() retval = 'IDCONFIRMED' #client_writer.write("{!r}\n".format(retval).encode("utf-8")) #Interesting asyncio thingy here, if I send the data to the client first, the proof is never correct #THe client completes and sends the proof to the service provider before the SP receives the C from here.""" print(literal_eval(args[0])) print(type(literal_eval(args[0]))) reader_sp, writer_sp = yield from asyncio.streams.open_connection("localhost", 12345, loop = loop) params = BL_setup() LT_idp_state, idp_pub = BL_idp_keys(params) #conv_user_commit = bytes(args[0], "utf8") #user_commit = encdec.decode(conv_user_commit) user_commit = encdec.decode(literal_eval(args[0])) msg_to_user = BL_idp_prep(LT_idp_state, user_commit) elif cmd == b'para': #reader_sp, writer_sp = yield from asyncio.streams.open_connection("localhost", 12345, loop=loop) start = time.time() paramsReceived = True print('Starting...') params = decode(strippedData) G, q, g, h, z, hs = params LT_idp_state, idp_pub = BL_idp_keys(params) #send public key to user and service provider #writer_sp.write(b'ipub' + encode(idp_pub) + b'fireintheboof') client_writer.write(b'mypb' + encode(idp_pub) + b'fireinthepub') elif cmd == b'ucmt': user_commit, C, c, responses, L2, Age = decode(strippedData) rR, rx = responses H = G.hash_to_point(b'service_name') ID = L2 * H Cprime = C - Age * hs[2] Wprime = rR * hs[0] + rx * hs[1] + c * Cprime Wxprime = rx * H + c * ID stuffToHash = (Wprime, Wxprime, C, g, h, z, hs[0], hs[1], hs[2], hs[3], H) cstr = b",".join([hexlify(x.export()) for x in stuffToHash]) chash = sha256(cstr).digest() cprime = Bn.from_binary(chash) if c == cprime: print("success") else: print("no") #generate message to user msg_to_user = BL_idp_prep(LT_idp_state, user_commit) client_writer.write(encode(msg_to_user) + b'fireintheboof') elif cmd == b'prep': msg_to_user2 = BL_idp_validation(LT_idp_state) client_writer.write(encode(msg_to_user2) + b'fireintheboof') elif cmd == b'msgi': msg_to_idp = decode(strippedData) # generate 3rd message to user msg_to_user3 = BL_idp_validation_2(LT_idp_state, msg_to_idp) client_writer.write(encode(msg_to_user3) + b'fireintheboof') end = time.time() finalTime = end - start print('Total time taken: ', finalTime) else: #print("Bad command {!r}".format(data), file=sys.stderr) pass # This enables us to have flow control in our connection. yield from client_writer.drain()
def _handle_client(self, client_reader, client_writer): global count global paramsReceived IOtime = 0 while True: try:#data = (yield from client_reader.readline()).decode("utf-8") startWait = time.time() data = yield from client_reader.readuntil(separator=b'fireintheboof') endWait = time.time() #print('IO wait: ', data[0:4], endWait - startWait) IOtime += endWait-startWait cmd = data[0:4] strippedData = data[4:-13] except asyncio.streams.IncompleteReadError: data = None if not data: # an empty string means the client disconnected break #cmd, *args = str(data).rstrip().split(' ') if cmd == b'buys': retval = "id" client_writer.write("{!r}\n".format(retval).encode("utf-8")) start = time.time() count +=1 id = count print(id, 'Starting...') elif cmd == b'para': params = decode(strippedData) paramsReceived = True elif cmd == b'ipub': idp_pub = decode(strippedData) elif cmd == b'vsig': sig = decode(strippedData) elif cmd == b'vsg2': signature = decode(strippedData) startSigProof = time.time() m = BL_verify_cred(params, idp_pub, 2, sig, signature) endSigProof = time.time() finalSigProof = endSigProof - startSigProof if m != False: print('Signature Correct') else: print('Signature Incorrect') elif cmd == b'page': newStuff = decode(strippedData) c, responses, gam_g, gam_hs, Age, xran = newStuff rrnd, rR, rx = responses #print(gam_hs, Age) (G, q, g, h, z, hs) = params startProof = time.time() H = G.hash_to_point(b'service_name') ID = xran * H zet1 = sig[2] zet1p = zet1 - Age * gam_hs[2] Waprime = rrnd * gam_g + rR * gam_hs[0] + rx * gam_hs[1] + c * zet1p Wxprime = rx * H + c * ID stuffToHash = (gam_g, Waprime, Wxprime, zet1p, gam_hs[0], gam_hs[1], gam_hs[2], H) cstr = b",".join([hexlify(x.export()) for x in stuffToHash]) chash = sha256(cstr).digest() c_prime = Bn.from_binary(chash) if c == c_prime: end = time.time() finalTime = end-start timeList.append(finalTime) print(id, "Age & User match, time: ", finalTime, 'Time for proof: ', end - startProof, 'Sig proof: ', finalSigProof, 'IO time: ', IOtime) else: print("whops") elif cmd == 'Commitment': """params = setup() G = params[0] C = EcPt.from_binary(literal_eval(args[0]), G)""" elif cmd == 'Proof': """c = Bn.from_hex(literal_eval(args[0])) responses1 = pickle.loads(literal_eval(args[1])) params = setup() responses = [] for res in responses1: responses.append(Bn.from_hex(res)) proof = c, responses print(verifyCommitments(params, C, proof))""" # This enables us to have flow control in our connection. yield from client_writer.drain()
def mix_package(sender, receiver, triplets): ''' Package a message through a mix-net. ''' aes = Cipher("AES-128-CTR") Bs = [] _, ypub, y = sender pubs = [ ypub ] round_trip = triplets + [ receiver ] + list(reversed(triplets)) secrets = [] prod_bs = Bn(1) for i, (mname, mpub, msec) in enumerate(round_trip): xysec2 = (y * prod_bs) * mpub secrets += [ xysec2 ] if __debug__ and msec is not None: xysec1 = (msec * prod_bs) * ypub assert xysec2 == xysec1 # Blinding factor k = KDF(xysec2.export()) b = Bn.from_binary(k.b) % o Bs += [ b ] # y = (b * y) % o prod_bs = (b * prod_bs) % o #ypub = b * ypub pubs += [ prod_bs * ypub ] # Precompute the correction factors correction_factors = [] for i in range(len(triplets)): total_b = Bn(1) for j in range(i, 2 * len(triplets) - i): total_b = (total_b * Bs[j]) % o assert round_trip[i][0] == round_trip[2 * len(triplets) - i][0] assert total_b * pubs[i] == pubs[2 * len(triplets) - i] correction_factors += [ total_b ] all_factors = [] + correction_factors all_factors += [ Bn(1) ] all_factors += [bf.mod_inverse(o) for bf in reversed(correction_factors)] assert len(all_factors) == len(round_trip) # Generate data stream data = [ sender ] + round_trip + [ sender ] addressing = [] for i, _ in enumerate(round_trip): addressing += [(data[1 + i-1][0], data[1 + i+1][0])] # Derive all keys all_data = zip(round_trip, all_factors, pubs, addressing, secrets) all_keys = [] for (mname, mpub, msec), bs, yelem, (xfrom, xto), Ksec in all_data: k1 = KDF(Ksec.export()) k2 = KDF( (bs * Ksec).export()) all_keys += [(k1, k2)] all_data = zip(round_trip, all_factors, pubs, addressing, all_keys) # Build the backwards path prev = '' backwards_stages = [ ] for j in range(len(mix_names) + 1): (mname, mpub, msec), bs, yelem, (xfrom, xto), (k1, k2) = all_data[j] the_bs = bs.mod_inverse(o).binary() enc = aes.enc(k2.kenc, k2.iv) ciphertext = enc.update(xto + xfrom + the_bs + prev) ciphertext += enc.finalize() mac = hmac.new(k2.kmac, ciphertext, digestmod=sha1).digest() prev = mac + ciphertext backwards_stages += [ prev ] # Build the forwards path prev = '' forwards_stages = [] for jp in range(len(mix_names) + 1): j = len(mix_names) - jp (mname, mpub, msec), bs, yelem, (xfrom, xto), (k1, k2) = all_data[j] the_bs = bs.binary() enc = aes.enc(k1.kenc, k1.iv) ciphertext = enc.update(xfrom + xto + the_bs + prev) ciphertext += enc.finalize() mac = hmac.new(k1.kmac, ciphertext, digestmod=sha1).digest() prev = mac + ciphertext forwards_stages += [ prev ] forwards_stages = list(reversed(forwards_stages)) stages = zip(forwards_stages, backwards_stages) # Check all the MACs if __debug__: for j in range(len(mix_names) + 1): (msg_f, msg_b) = stages.pop(0) (mname, mpub, msec), bs, yelem, (xfrom, xto), (k1, k2) = all_data[j] mac1 = hmac.new(k1.kmac, msg_f[20:], digestmod=sha1).digest() assert msg_f[:20] == mac1 enc = aes.dec(k1.kenc, k1.iv) plaintext = enc.update(msg_f[20:]) plaintext += enc.finalize() assert xfrom == plaintext[:4] and xto == plaintext[4:8] mac2 = hmac.new(k2.kmac, msg_b[20:], digestmod=sha1).digest() assert msg_b[:20] == mac2 # End __debug__ return zip(pubs[:len(mix_names) + 1], forwards_stages + [''], [''] + backwards_stages)
def test_protocol(): # Parameters of the BL schemes G = EcGroup(713) q = G.order() g = G.hash_to_point(b"g") h = G.hash_to_point(b"h") z = G.hash_to_point(b"z") hs = [G.hash_to_point(("h%s" % i).encode("utf8")) for i in range(100)] # Inputs from user R = q.random() L1 = 10 L2 = 20 #age C = R * hs[0] + L1 * hs[1] + L2 * hs[2] m = b"Hello World!" # Inputs from the Issuer # TODO: check ZK on C x = q.random() y = x * g # Preparation rnd = q.random() z1 = C + rnd * g z2 = z + (-z1) ## Send: (rnd,) to user if rnd % q == 0: raise z1 = C + rnd * g gam = q.random() zet = gam * z zet1 = gam * z1 zet2 = zet + (-zet1) tau = q.random() eta = tau * z # Validation: Issuer u, r1p, r2p, cp = [q.random() for _ in range(4)] a = u * g a1p = r1p * g + cp * z1 a2p = r2p * h + cp * z2 ## Send(a, ap = (a1p, a2p)) # User side assert G.check_point(a) assert G.check_point(a1p) assert G.check_point(a2p) t1, t2, t3, t4, t5 = [q.random() for _ in range(5)] alph = a + t1 * g + t2 * y alph1 = gam * a1p + t3 * g + t4 * zet1 alph2 = gam * a2p + t5 * h + t4 * zet2 # Make epsilon H = [zet, zet1, alph, alph1, alph2, eta] Hstr = list(map(EcPt.export, H)) + [m] Hhex = b"|".join(map(b64encode, Hstr)) epsilon = Bn.from_binary(sha256(Hhex).digest()) % q e = epsilon.mod_sub(t2, q).mod_sub(t4, q) ## Send: (e,) to Issuer c = e.mod_sub(cp, q) r = u.mod_sub((c * x), q) ## Send: (c,r, cp, rp = (r1p, r2p)) to User ro = r.mod_add(t1, q) om = c.mod_add(t2, q) ro1p = (gam * r1p + t3) % q ro2p = (gam * r2p + t5) % q omp = (cp + t4) % q mu = (tau - omp * gam) % q signature = (m, zet, zet1, zet2, om, omp, ro, ro1p, ro2p) gam_hs = [gam * hsi for hsi in hs] zet1p = zet1 - L2 * gam_hs[2] # Check verification equation lhs = (om + omp) % q rhs_h = [zet, zet1p, ro * g + om * y, ro1p * g + omp * zet1p, ro2p * h + omp * zet2, ## problem mu * z + omp * zet] Hstr = list(map(EcPt.export, rhs_h)) + [m] Hhex = b"|".join(map(b64encode, Hstr)) rhs = Bn.from_binary(sha256(Hhex).digest()) % q # Check the (future) ZK proof assert zet == gam * z gam_hs = [gam * hsi for hsi in hs] gam_g = gam * g #assert rnd * gam_g + R * gam_hs[0] + L1 * gam_hs[1] + L2 * gam_hs[2] == zet1 assert rnd * gam_g + R * gam_hs[0] + L1 * gam_hs[1] == zet1 - L2 * gam_hs[2] print(rhs == lhs)
def mix_operate(message, triplet, setup, generate_return_message=False): ''' Operate a Mix with a received message, and its keys. ''' mname, mpub, msec = triplet elem, forward, backwards = message G, o, g, o_bytes = setup aes = Cipher("AES-128-CTR") # Derive first key k1 = KDF((msec * elem).export()) # Derive the blinding factor b = Bn.from_binary(k1.b) % o new_elem = b * elem # Check the forward MAC mac1 = hmac.new(k1.kmac, forward[20:], digestmod=sha1).digest() if not (forward[:20] == mac1): raise Exception("Wrong MAC1") # Decrypt the payload enc = aes.dec(k1.kenc, k1.iv) pt = enc.update(forward[20:]) pt += enc.finalize() # Parse the forward message xcode = pt[0] if not (xcode == "0" or xcode == "1"): raise Exception("Wrong routing code") pt = pt[1:] if xcode == "0": xfrom, xto, the_bs, new_forw = pt[:4], pt[4:8], pt[8:8+o_bytes], pt[8+o_bytes:] old_bs = Bn.from_binary(the_bs) # Now package the return part k2 = KDF(((msec * old_bs) * elem).export()) enc = aes.enc(k2.kenc, k2.iv) new_back_body = enc.update("1" + xto + xfrom + backwards) new_back_body += enc.finalize() mac2 = hmac.new(k2.kmac, new_back_body, digestmod=sha1).digest() new_back = mac2 + new_back_body if generate_return_message: ret_elem = old_bs * elem ret_forw = new_back ret_back = None return ((xto, xfrom), (ret_elem, ret_forw, ret_back) ) else: xfrom, xto, new_forw = pt[:4], pt[4:8], pt[8:] # Returns do not need to build returns if not (backwards == None): raise Exception("Backwards header should be None") new_back = None return ((xfrom, xto), (new_elem, new_forw, new_back) )