def pedersen_vector_prover(C_arr, x_arr, r_arr, rnd_bytes=os.urandom, RO=sha2): """ Params: x_arr, r_arr are arrays of elements in Fp C_arr are arrays of Points Returns: prf, of the form (K,sx,sr) where K is points and sx and sr are points in Fp Note that here you are able to prove that knowledge of n points with only communicating 1 ppints and 2 scalars. """ # Make sure all commitments are correct for C_elem, x_elem, r_elem in zip(C_arr, x_arr, r_arr): assert C_elem == x_elem * G + r_elem * H # TODO: Your code goes here: 10 points # commitment K = C_arr[0] c = Fp(uint256_from_str(RO(ser(K)))) sx = x_arr[0] sr = r_arr[0] e = c # responses for i in range(len(C_arr)): sx = Fp(sx + e.n * x_arr[i]) sr = Fp(sr + e.n * r_arr[i]) e = Fp(e * c) # print(e.n) return (K, sx, sr)
def arith_prover(a, b, A, B, C, rnd_bytes=os.urandom, RO=sha2): """ Params: a and b are elements of Fp A, B, C are Points Returns: prf, of the form (KA,KB,KC,sa,sb) Must satisfy verify_proof2(A, B, C, prf) Must be zero-knowledge """ assert a * G == A assert b * G == B assert (a * (b - 3)) * G == C # TODO: fill in your code here (10 points) ka = uint256_from_str(rnd_bytes(32)) % order kb = uint256_from_str(rnd_bytes(32)) % order KA = ka * G KB = kb * G KC = kb * A c = uint256_from_str(RO(ser(KA) + ser(KB) + ser(KC))) sa = Fp(ka + a * c) sb = Fp(kb + b * c) return (KA, KB, KC, sa, sb)
def pedersen_prover(C, X, x, r, rnd_bytes=os.urandom, RO=sha2): """ Params: x and r are elements of Fp C,X are Points Returns: prf, of the form (KX,KC,sx,sr) """ assert X == x * G assert C == x * G + r * H # TODO: fill in your code here (10 points) # blinding factor kx = uint256_from_str(rnd_bytes(32)) % order kr = uint256_from_str(rnd_bytes(32)) % order # commitment KX = kx * G KC = kx * G + kr * H # receive challenge from random oracle c = uint256_from_str(RO(ser(KX) + ser(KC))) # responses sx = Fp(kx + c * x) sr = Fp(kr + c * r) return (KX, KC, sx, sr)
def dlog_extractor(A, Adv): assert type(A) is Point ## Step 1: run the adversary to generate a proof while recording ## the random bits and oracle queries # TODO: Fill your code in here i = 0 l = {} found = False found2 = False mapping = {} def RO1(s): assert type(s) is str nonlocal mapping if not s in mapping: mapping[s] = os.urandom(32) return mapping[s] def RO2(s): assert type(s) is str nonlocal mapping if not found2: mapping[s] = os.urandom(32) return mapping[s] def rand(x): nonlocal i, l, found if x == 32 and found: return l[i] elif x == 32 and not found: i += 1 r = os.urandom(x) l[i] = r return r else: return os.urandom(x) (K1, s1) = Adv(A, rnd_bytes=rand, RO=RO1) found = True c1 = uint256_from_str(RO1(ser(K1))) # print("c1",c1,"\n","K1",K1) ## Step 2: run the adversary again, replaying the random bits, ## and intercepting the call to the random oracle # TODO: Fill your code in here (5 points) (K2, s2) = Adv(A, rnd_bytes=rand, RO=RO2) found2 = True c2 = uint256_from_str(RO2(ser(K2))) # print("c2",c2,"\n","K2",K2) ## Step 3: Extract a witness from the two proofs and oracle queries # TODO: Fill your code in here (5 points) return Fp(s1 - s2) / Fp(c1 - c2)
def pedersen_vector_verifier(C_arr, prf, rnd_bytes=os.urandom, RO=sha2): (C0, sx, sr) = prf assert type(C0) == Point assert type(sx) == type(sr) == Fp c = Fp(uint256_from_str(RO(ser(C0)))) e = c C_final = C0 for C_elem in C_arr: C_final = C_final + e.n * C_elem e = Fp(e * c) assert C_final == sx.n * G + sr.n * H return True
def OR_prover(A, B, x, rnd_bytes=os.urandom, RO=sha2): assert x * G == A or x * G == B # TODO: Fill your code in here (20 points) ka = uint256_from_str(rnd_bytes(32)) % order kb = uint256_from_str(rnd_bytes(32)) % order KA = ka * G KB = kb * G c = uint256_from_str(RO(ser(KA) + ser(KB))) if x * G != B: ca = c cb = x * order else: ca = x * order cb = c sa = Fp(ka + x * ca) sb = Fp(kb + x * cb) return (KA, KB, sa, sb, ca, cb)
def sender_round1(rnd_bytes=os.urandom): """ Inputs: none Returns: (a, A) A is sent to receiver, a is stored and passed to sender_round3 """ # TODO: Your code goes here a = Fp(uint256_from_str(rnd_bytes(32)) % order) A = a.n * G return a, A
def schnorr_sign(x, m, rnd_bytes=os.urandom, RO=sha2): assert type(x) is bytes assert type(m) is str # TODO: Your code goes here (10 points) k = uint256_from_str(rnd_bytes(32)) % order K = k * G c = uint256_from_str(RO(ser(K) + sha2(m).hex())) x = uint256_from_str(x) s = Fp(k + c * x) return bytes.fromhex(ser(K)) + uint256_to_str(s.n)
def dlog_prover(A, a, rnd_bytes=os.urandom, RO=sha2): assert a * G == A # blinding factor k = uint256_from_str(rnd_bytes(32)) % order # commitment K = k * G # Invoke the random oracle to receive a challenge c = uint256_from_str(RO(ser(K))) # response s = Fp(k + c * 124213421) return (K, s)
def dlog_prover(A, a, k=uint256_from_str(os.urandom(32)) % order, rnd_bytes=os.urandom, RO=sha2): assert a * G == A # commitment K = k * G # Invoke the random oracle to receive a challenge c = uint256_from_str(RO(ser(K))) # response s = Fp(k + c * a) return (K, s)
def receiver_round2(c, A, rnd_bytes=os.urandom, RO=sha2): """ Inputs: c a bit 0 or 1 A the round1 message from the sender Returns: (kR, B) B is sent to the sender, kR is the decryption key, stored and passed to sender_round4 """ assert c in (0, 1) assert type(A) is Point # TODO: Your code goes here b = Fp(uint256_from_str(rnd_bytes(32)) % order) B = b.n * G if c == 0 else A + b.n * G kR = RO(ser(b.n * A)) return kR, B
def Adv(A, rnd_bytes, RO): assert A == a * G while True: # The "picky" prover loops until it is happy # Make a whimsical decision coin = rnd_bytes(1) if ord(coin) < 128: continue k = uint256_from_str(rnd_bytes(32)) % order K = k * G c = uint256_from_str(RO(ser(K))) # I only like challenges that end with 3 zero bits if c & 0b111 != 0: continue # OK I'm satisfied s = Fp(k + c * a) return (K, s)
def dlog_simulator(A, rnd_bytes): """ Returns: - (prf, transcript) - prf, a tuple of the form (K,s), where K is a Point and s is an element of Fp - transcript is an array consisting of elements of the form [...(q,h)...] where each q is a query (a string) and each h is the response (a 32-byte string) """ # TODO: Fill in your code here (10 points) transcript = [] h = rnd_bytes(32) c = uint256_from_str(h) s = uint256_from_str(rnd_bytes(32)) % order K = s * G - c * A q = ser(K) transcript.append((q, h)) return ((K, Fp(s)), transcript)
def HandleAuthPacket(self, pkt): print("Received an authentication request") print("Attributes: ") for attr in pkt.keys(): print("%s: %s" % (attr, pkt[attr])) reply = self.CreateReplyPacket( pkt, **{ "Service-Type": "Framed-User", "Framed-IP-Address": '192.168.0.1', "Framed-IPv6-Prefix": "fc66::1/64" }) if "User-Password" in pkt.keys(): if check_local_user(pkt): reply.code = packet.AccessAccept else: reply.code = packet.AccessReject self.SendReplyPacket(pkt.fd, reply) return if "EAP-Message" in pkt.keys(): try: realmname = pkt["User-Name"][0].split("@")[1] except IndexError: reply.code = packet.AccessReject self.SendReplyPacket(pkt.fd, reply) return if realmname == realmlist[nodeid]: time.sleep(random.uniform(delay_lower, delay_higher)) if random.random() < packet_loss_rate: return if pkt["EAP-Message"][0] == "EAP-Response Identity": k = uint256_from_str(os.urandom(32)) % order reply["EAP-Message"] = [ "EAP-Request ZKPoK", uint256_to_str(k).encode("latin") ] state = os.urandom(32) reply["State"] = state server_state[state] = dict(k=k, count=0) reply.code = packet.AccessChallenge self.SendReplyPacket(pkt.fd, reply) else: state = pkt["State"][0] reply["State"] = state K = server_state[state]["k"] * G s = Fp(uint256_from_str(pkt["EAP-Message"][2])) username = pkt["User-Name"][0] A = Point(curve, Fq(userlist[username][0]), Fq(userlist[username][1])) try: dlog_verifier(A, (K, s)) reply.code = packet.AccessAccept self.SendReplyPacket(pkt.fd, reply) except AssertionError: reply.code = packet.AccessReject self.SendReplyPacket(pkt.fd, reply) else: if pkt["EAP-Message"][0] == "EAP-Response Identity": state = os.urandom(32) reply["State"] = state else: state = pkt["State"][0] reply["State"] = state if state not in server_state: server_state[state] = dict(count=0, success=0, fail=0, state=0) # Proxy to other realms peer_list = [ i for i, val in enumerate(realmlist) if val == realmname ] if server_state[state]["count"] >= len(peer_list): return peer_node = peer_list[server_state[state]["count"]] if pkt["EAP-Message"][0] == "EAP-Response Identity": clt = client.Client( server="www.simonyu.net", authport=9110 + peer_node, secret=b"testing123", dict=dictionary.Dictionary("dictionary"), retries=2, timeout=1) while True: try: peerreply = clt.SendPacket(pkt) break except client.Timeout: server_state[state]["count"] += 1 if server_state[state]["count"] >= len(peer_list): return peer_node = peer_list[server_state[state]["count"]] clt = client.Client( server="www.simonyu.net", authport=9110 + peer_node, secret=b"testing123", dict=dictionary.Dictionary("dictionary"), retries=2, timeout=1) server_state[state]["state"] = peerreply["State"] reply = self.CreateReplyPacket(pkt, **peerreply) reply.code = peerreply.code reply["State"] = state self.SendReplyPacket(pkt.fd, reply) else: clt = client.Client( server="www.simonyu.net", authport=9110 + peer_node, secret=b"testing123", dict=dictionary.Dictionary("dictionary"), retries=2, timeout=1) pkt["State"] = server_state[state]["state"] try: peerreply = clt.SendPacket(pkt) if peerreply.code == packet.AccessAccept: server_state[state]["success"] += 1 else: server_state[state]["fail"] += 1 if server_state[state]["success"] >= server_count: reply = self.CreateReplyPacket(pkt, **peerreply) reply.code = packet.AccessAccept self.SendReplyPacket(pkt.fd, reply) return if server_state[state]["fail"] > 1: reply = self.CreateReplyPacket(pkt, **peerreply) reply.code = packet.AccessReject self.SendReplyPacket(pkt.fd, reply) return except client.Timeout: pass server_state[state]["count"] += 1 peer_node = peer_list[server_state[state]["count"]] clt = client.Client( server="www.simonyu.net", authport=9110 + peer_node, secret=b"testing123", dict=dictionary.Dictionary("dictionary"), retries=2, timeout=1) pkt["EAP-Message"] = ["EAP-Response Identity"] del pkt["State"] while True: try: peerreply = clt.SendPacket(pkt) break except client.Timeout: server_state[state]["count"] += 1 if server_state[state]["count"] >= len(peer_list): return peer_node = peer_list[server_state[state]["count"]] clt = client.Client( server="www.simonyu.net", authport=9110 + peer_node, secret=b"testing123", dict=dictionary.Dictionary("dictionary"), retries=2, timeout=1) server_state[state]["state"] = peerreply["State"] reply = self.CreateReplyPacket(pkt, **peerreply) reply.code = peerreply.code reply["State"] = state self.SendReplyPacket(pkt.fd, reply)