예제 #1
0
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
예제 #2
0
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
예제 #3
0
 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
예제 #4
0
 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
예제 #5
0
 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
예제 #6
0
 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
예제 #7
0
 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
예제 #8
0
 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
예제 #9
0
 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
예제 #10
0
 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
예제 #11
0
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()
예제 #12
0
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
예제 #13
0
파일: set5.py 프로젝트: nemausus/matasano
 def test_modexp(self):
     """Challenge 33"""
     self.assertEqual(1, modexp(45, 0, 37))
     self.assertEqual(8, modexp(45, 1, 37))
예제 #14
0
#     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."