def SRPSetup(sock, email, password, isClientGood): g = 2 k = 3 N = int( 'ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e340' '4ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f40' '6b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8f' 'd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff', 16) sock.send(email.encode() + b'\n') a = random.randint(0, 10000) if isClientGood: A = dh.modexp(g, a, N) else: # Sending this means that S = 0 server-side, since # A is the base of the modexp computing S, so all the # other parameters get ignored. # The other tweaking proposed, A = N or A = kN, have the # exact same effect, since you compute S = (A ** x) % A # which is equal to 0 no matter what 'x' is. A = 0 message = (str(A) + '\n').encode() sock.send(message) salt = ReadUntilNewline(sock) B = ReadUntilNewline(sock) sha = hashlib.sha256() sha.update(str(A).encode()) sha.update(B) u = int(sha.hexdigest(), 16) sha = hashlib.sha256() sha.update(salt) sha.update(password.encode()) x = int(sha.hexdigest(), 16) if isClientGood: exp = (a + u * x) base = (int(B) - k * dh.modexp(g, x, N)) S = dh.modexp(base, exp, N) else: # If we have been bad, we know the server has computed S = 0, # so we do the same on our side. We could also avoid computing # a bunch of other parameters before (namely, x and u). # At this point the secret is independent of which password # we send to the server, so we can send an empty one and still # be accepted as good users. S = 0 sha = hashlib.sha256() sha.update(str(S).encode()) K = sha.hexdigest() return K, salt
def SRPSetup(clientsocket): g = 2 k = 3 # Use the same large prime we used before. N = int( 'ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e340' '4ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f40' '6b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8f' 'd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff', 16) # Server and client have agreed already on a password. P = b'mybeautifulpassword' # Random salt. salt = random.randint(1, 100000) saltBytes = str(salt).encode() # Hash salt|password and convert the result to an integer, x. We do # this by simply taking the decimal equivalent of the hash. sha = hashlib.sha256() sha.update(saltBytes) sha.update(P) xhash = sha.hexdigest() x = int(xhash, 16) v = dh.modexp(g, x, N) # We don't actually make any use of the email in this exercise, # but in a real implementation we would associate the email with # the expected password, and/or do other verifications. email = ReadUntilNewline(clientsocket) A = ReadUntilNewline(clientsocket) b = random.randint(1, 10000) B = k * v + dh.modexp(g, b, N) clientsocket.send(saltBytes + b'\n') clientsocket.send(str(B).encode() + b'\n') sha = hashlib.sha256() sha.update(A) sha.update(str(B).encode()) u = int(sha.hexdigest(), 16) S = dh.modexp((int(A) * dh.modexp(v, u, N)), b, N) sha = hashlib.sha256() sha.update(str(S).encode()) K = sha.hexdigest() # Returns both K and saltBytes as byte strings. This helps later # since we hash them. return K.encode(), saltBytes
def __init__(self, N, g, k, I, P, ntimes=None, simple=False): SRPEntity.__init__(self, N, g, k, I, P) self.a = random.randint(0, self.N - 1) # private self.ntimes = ntimes self.simple = simple if ntimes == None: self.A = modexp(g, self.a, self.N) # public (normal) else: self.A = self.N * ntimes # evil zero key
def take_logon(self, email, A): self.I = email # I / email is not really used by server self.A = A self.b = random.randint(0, self.N - 1) # private if self.simple: self.B = modexp(self.g, self.b, self.N) self.u = random.randint(0, 2**128 - 1) else: self.B = self.k * self.v + modexp(self.g, self.b, self.N) # public uH = sha256(str(self.A) + str(self.B)).hexdigest() self.u = int('0x' + uH, 16) S = modexp(self.A * modexp(self.v, self.u, self.N), self.b, self.N) # If A is congruent to 0 (mod N), then S = 0!! self.K = sha256(str(S)).hexdigest() if self.simple: return self.salt, self.B, self.u else: return self.salt, self.B
def __init__(self, N, g, k, I, P, simple=False, mitm=False): SRPEntity.__init__(self, N, g, k, I, P) self.salt = random.randint(0, 2 ** 32) xH = sha256(str(self.salt) + P).hexdigest() x = int('0x' + xH, 16) self.v = modexp(g, x, N) self.simple = simple self.mitm = mitm if mitm: self.simple = True
def __init__(self, N, g, k, I, P, simple=False, mitm=False): SRPEntity.__init__(self, N, g, k, I, P) self.salt = random.randint(0, 2**32) xH = sha256(str(self.salt) + P).hexdigest() x = int('0x' + xH, 16) self.v = modexp(g, x, N) self.simple = simple self.mitm = mitm if mitm: self.simple = True
def logon_to(self, robot): if self.simple: [self.salt, self.B, u] = robot.take_logon(self.email, self.A) else: [self.salt, self.B] = robot.take_logon(self.email, self.A) uH = sha256(str(self.A) + str(self.B)).hexdigest() u = int('0x' + uH, 16) xH = sha256(str(self.salt) + self.password).hexdigest() x = int('0x' + xH, 16) if self.simple: S = modexp(self.B, self.a + u * x, self.N) else: S = modexp(self.B - self.k * modexp(self.g, x, self.N), self.a + u * x, self.N) if self.ntimes == None: self.K = sha256(str(S)).hexdigest() else: self.K = sha256(str(0)).hexdigest() mac = hmac.new(self.K, str(self.salt), sha256).hexdigest() response = robot.validate_hash(mac) print "Server says:", response
def DHExchangeClient(serverHost, port): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((serverHost, port)) # Usual parameters as recommended by NIST. pHex = ('ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e340' '4ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f40' '6b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8f' 'd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff') p = int(pHex, 16) g = 2 a = random.randint(0, p - 1) A = dh.modexp(g, a, p) B = 0 # Sends the message in the predefined format. message = 'BEGIN\n%s\n%s\n%s\nEND' % (str(p), str(g), str(A)) sock.send(message.encode()) # Gets a similar message back from the server. See the comments # on dh_server which has a similar loop. exchange = b'' while b'D' not in exchange: exchange += sock.recv(100) exchange = exchange.decode() pieces = exchange.split('\n') B = int(pieces[1]) secret = dh.modexp(B, a, p) print('My secret is', str(secret)) VerifyKey(sock, secret) sock.close()
def DHExchangeServer(clientsocket): A = 0 p = 0 g = 0 exchange = b'' # In this scenario, the DH exchange message has this form: # BEGIN # p # g # A # END # (including newlines). Therefore we keep reading 100 bytes # until we read D. We do not try and read the whole word # because it could fall across a boundary. However this only # works because the D is unique (p, g and A are integers). while b'D' not in exchange: exchange += clientsocket.recv(100) exchange = exchange.decode() pieces = exchange.split('\n') p = int(pieces[1]) g = int(pieces[2]) A = int(pieces[3]) # Computes B and then the secret. b = random.randint(0, g - 1) B = dh.modexp(g, b, p) secret = dh.modexp(A, b, p) # Perform our side of the exchange, sending B to the client # with the same format. messageForClient = 'BEGIN\n%s\nEND' % str(B) clientsocket.send(messageForClient.encode()) return secret
def test_modexp(self): """Challenge 33""" self.assertEqual(1, modexp(45, 0, 37)) self.assertEqual(8, modexp(45, 1, 37))
# chal33.py - Implement Diffie-Hellman # # Copyright (C) 2015 Andrew J. Zimolzak <*****@*****.**>, # and licensed under GNU GPL version 3. Full notice is found in # the file 'LICENSE' in the same directory as this file. from cryptopals import warn from diffie_hellman import get_pubkey_exp, p, g, modexp p1 = 37 g1 = 5 [A, a] = get_pubkey_exp(p1, g1) [B, b] = get_pubkey_exp(p1, g1) s1 = modexp(B, a, p1) s2 = modexp(A, b, p1) print s1, "?=", s2, "(test of little session key equality)" #### [A, a] = get_pubkey_exp(p, g) [B, b] = get_pubkey_exp(p, g) s1_big = modexp(B, a, p) s2_big = modexp(A, b, p) print "Generated two big session keys of", s1_big.bit_length(), \ "and", s2_big.bit_length(), "bits."