Example #1
0
def main():

    # Server sends base, prime and k

    data = requests.get('http://127.0.0.1:5000/').json()
    prime, base, k = data['prime'], data['base'], data['k']

    # Client and server exchange public keys, but the server sends 0 as its public
    #key.

    email = b'*****@*****.**'.decode()

    #Test a few bad public keys which are all 0 mod prime. These allow us to
    #login without knowing the password
    for bad_public_key in [0, prime, prime**2, 4 * prime]:

        server_response = requests.post('http://127.0.0.1:5000/',
                                        data={
                                            'email': email,
                                            'dhA': bad_public_key
                                        }).json()

        #We only need the salt, not the secret key. Convert to bytes to calculate
        #our bogus hmac
        salt = bso.int_to_bytes(server_response['salt'])

        # Hmac is calculated by the client and sent to the server.
        K = sha256(bso.int_to_bytes(0)).digest()
        bogus_hmac = bso.bytes_to_hex(
            hmac(K, salt, lambda val: sha256(val).digest(), 64, 32))

        print(
            requests.post('http://127.0.0.1:5000/', data={
                'HMAC': bogus_hmac
            }).text)
Example #2
0
    def verify_hmac(self, recv_hmac):
        """
        Final SRP verification. Computes the hmac which depends depends on the
        salt and password but also on a Diffie Hellmen shared key. Equates with
        the hamc submitted by the client
    

        Args:
            recv_hmac (bytes): hmac computed byt he client
        Returns:
            string, int: 'OK', 200 if the verification is successful
                        'Nope', 400 if the verification is unsuccessful
        """

        S = modexp(self.client_public_key * modexp(self.v, self.u, self.prime),
                   self.secret_key, self.prime)

        hmac_key = sha256(bso.int_to_bytes(S)).digest()

        salt_bytes = bso.int_to_bytes(self.salt)

        calc_hmac = hmac(hmac_key, salt_bytes,
                         lambda val: sha256(val).digest(), 64, 32)

        if recv_hmac == calc_hmac:
            return 'OK', 200
        return 'Nope', 400
Example #3
0
    def calculate_hmac(self):
        """Calculates the hmac and returns it. If the password is correct, it
        it should match the hmac calculated byt the server.
        
        returns:
            bytes: hmac depending on password, salt and server and client keys
        
        """
        u = sha256(
            bso.int_to_bytes(self.public_key) +
            bso.int_to_bytes(self.server_public_key)).hexdigest()
        u = int(u, 16)

        #conver salt to bytes for hashing
        salt_bytes = bso.int_to_bytes(self.salt)

        password_exp = sha256(salt_bytes + self.user_password).hexdigest()
        password_exp = int(password_exp, 16)

        #Calculating the key for hmac
        S_base = (self.server_public_key - self.k *
                  modexp(self.base, password_exp, self.prime)) % self.prime
        S_exponent = (self.secret_key + u * password_exp) % self.prime
        S = modexp(S_base, S_exponent, self.prime)

        hmac_key = sha256(bso.int_to_bytes(S)).digest()

        calc_hmac = hmac(hmac_key, salt_bytes,
                         lambda val: sha256(val).digest(), 64, 32)

        return calc_hmac
Example #4
0
def test_hmac(password, salt, u, client_public_key, secret_key, base, real_hmac, prime = NIST_PRIME):
        """
        Takes in all variables used by the server in simple SRP and calculates 
        the hmac. Tests if the calculated hmac matches the true hmac.
        Args: 
            password (bytes): user password
            salt (int): salt used in SRP. Should be random
            u (int): u used in SRP. Should be random
            client_public_key (int): clients public key
            secret_key (int): servers secret key
            base (int): base used in diffie hellman
        returns:
            bool: True if simple srp claculation matches hmac given, false otherwise
        """
        salt = bso.int_to_bytes(salt)
        x = int(sha256(salt + password).hexdigest(), 16)
        v = modexp(base, x, prime)

        S = modexp(client_public_key * modexp(v, u, prime), secret_key, prime)
        
        hmac_key = sha256(bso.int_to_bytes(S)).digest()
        
        calc_hmac = hmac(hmac_key, salt, lambda val:sha256(val).digest(), 64, 32)
        
        if real_hmac == calc_hmac:
            return True
        return False
Example #5
0
def diffiehellman_mitm_sim(prime, base):
    """This function simulates an exchange between two parties, first using 
    Diffie Hillmann to exchange secret keys and then AES CBC to exchange 
    messages. However, the function uses yield functionality to simulate a man
    in the middle attack.
    """
    alice = {}

    #Alice generates their public key an sends to 'bob'
    alice['dh'] = DiffieHellman(prime,
                                base,
                                secret_key=secrets.randbelow(prime))
    alice_pub = alice['dh'].gen_public_key()

    (prime, base, key_for_bob) = yield (prime, base, alice_pub)

    #bob recieves 'alice's' public key, generates their own public key and
    #the shared key. Sends their public key ot 'alice'
    bob = {
        'dh': DiffieHellman(prime, base, secret_key=secrets.randbelow(prime))
    }
    bob_pup = bob['dh'].gen_public_key()
    bob['dh'].gen_shared_key(key_for_bob)

    key_for_alice = yield bob_pup

    ### Alice recieves Bob's public key, generates the shared key and encrypts
    ### message for bob

    alice['dh'].gen_shared_key(key_for_alice)

    alice['sha1'] = SHA1(bso.int_to_bytes(alice['dh'].shared_key))
    alice['cipher'] = AES_CBC(alice['sha1'].digest()[:16],
                              secrets.token_bytes(16))
    alice_ciphertext = alice['cipher'].encrypt(b'Message to Bob')
    alice_ciphertext += alice['cipher'].IV

    ciphertext_for_bob = yield alice_ciphertext

    #Bob recieves the ciphertext, decrypts it and send a reply.

    bob['sha1'] = SHA1(bso.int_to_bytes(bob['dh'].shared_key))
    bob['cipher'] = AES_CBC(bob['sha1'].digest()[:16], secrets.token_bytes(16))
    bob_ciphertext = bob['cipher'].encrypt(b'Message to Alice')
    bob_ciphertext += bob['cipher'].IV

    ciphertext_for_alice = yield bob_ciphertext

    ### Finally alice decrypts bobs reply

    alice['cipher'].decrypt(ciphertext_for_alice[:-16],
                            ciphertext_for_alice[-16:])
Example #6
0
def simulate_communication_with_dh_key(prime, base):
    """ Simulates a communication between two parties who first exhanges key via
    diffiehillman and encrypt messages using aes_cbc. Returns two messages, one
    encrypted by each party
    """

    alice = {}


    alice['dh'] = DiffieHellman(prime, base, secret_key=secrets.randbelow(prime))
    alice_pub = alice['dh'].gen_public_key() 

    #bob recieves alice's public key, generates their own public key and
    #the shared key. Sends their public key ot alice
    bob = {'dh':DiffieHellman(prime, base, secret_key=secrets.randbelow(prime))}
    bob_pub = bob['dh'].gen_public_key()
    bob['dh'].gen_shared_key(alice_pub)

    ### Alice recieves Bob's public key, generates the shared key and encrypts
    ### message for bob

    alice['dh'].gen_shared_key(bob_pub)
    alice['message'] = b'Message to Bob'   

    alice['sha1'] = SHA1(bso.int_to_bytes(alice['dh'].shared_key))
    alice['cipher'] = AES_CBC(alice['sha1'].digest()[:16], secrets.token_bytes(16))
    alice_ciphertext = alice['cipher'].encrypt(alice['message'])
    alice_ciphertext += alice['cipher'].IV

    #Bob encrypts his own ciphertext.

    bob['message'] = b'Message to Alice'

    bob['sha1'] = SHA1(bso.int_to_bytes(bob['dh'].shared_key))
    bob['cipher'] = AES_CBC(bob['sha1'].digest()[:16], secrets.token_bytes(16))
    bob_ciphertext = bob['cipher'].encrypt(bob['message'])
    bob_ciphertext += bob['cipher'].IV


    ### Check decryption works

    assert(bso.remove_padding_pkcs7(alice['cipher'].decrypt(bob_ciphertext[:-16], bob_ciphertext[-16:])) == bob['message'])

    
    assert(bso.remove_padding_pkcs7(bob['cipher'].decrypt(alice_ciphertext[:-16], alice_ciphertext[-16:])) == alice['message'])

    ## return ciphertexts for the man in the middle to decrypt

    return alice_ciphertext, bob_ciphertext
Example #7
0
    def decrypt(self, ciphertext):

        ciphertext_hash = sha256(bso.int_to_bytes(ciphertext)).digest()

        if ciphertext_hash in self.decrypted_ciphertexts_hashes:
            raise Exception('I have already decrypted this message!')

        self.decrypted_ciphertexts_hashes.append(ciphertext_hash)

        return rsa.RSAServer.decrypt(self, ciphertext)
Example #8
0
def main():

    prime = 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff
    
    for base in [1, prime, prime - 1]:
        messages = simulate_communication_with_dh_key(prime, base)
        if base == prime:
            secret_key = 0
        else:
            secret_key = 1
            
        aes_key = SHA1(bso.int_to_bytes(secret_key)).digest()[:16]
        malcolm = AES_CBC(aes_key, b'0'*16)

        assert bso.remove_padding_pkcs7(malcolm.decrypt(messages[0][:-16], messages[0][-16:])) == b'Message to Bob'


        assert bso.remove_padding_pkcs7(malcolm.decrypt(messages[1][:-16], messages[1][-16:])) == b'Message to Alice'
Example #9
0
    def _password_computation(self, user_password):
        """Computes a hash of the users password for storing and later computations

        Args: 
            user_password (bytes): users password

        Returns:
            hashed version of the password which is used in SRP
        """

        #Salt needs to be converted to bytes for use in the hash
        salt_bytes = bso.int_to_bytes(self.salt)

        #password is padded with salt (a random int) and hased to be used as
        #an exponent. This same calculation is also done by the client.

        password_exponent = sha256(salt_bytes + user_password).hexdigest()
        password_exponent = int(password_exponent, 16)

        return modexp(self.base, password_exponent, self.prime)
Example #10
0
def main():
    """Simulate a man in the middle attack on Diffie Hellman key exchange"""

    prime = 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff
    base = 2

    connection = diffiehellman_mitm_sim(prime, base)

    # intercept alices public key
    prime, base, _ = next(connection)

    # send prime instead of alices public key to bob. Recieve Bobs public key,
    # which we forget as it is not needs. The shared kill will be 0.

    connection.send((prime, base, prime))

    #Send prime as bob's public key to alice. We have ensured that the shared
    #hared secret key is 0. Recieve Alice's ciphertext for bob
    ciphertext_a2b = connection.send(prime)

    # decrypt
    malcolm = AES_CBC(SHA1(bso.int_to_bytes(0)).digest()[:16], b'0' * 16)
    messages = []
    messages.append(
        bso.remove_padding_pkcs7(
            malcolm.decrypt(ciphertext_a2b[:-16], ciphertext_a2b[-16:])))

    #Send the ciphertext to bob. Recieve his response
    ciphertext_b2a = connection.send(ciphertext_a2b)

    messages.append(
        bso.remove_padding_pkcs7(
            malcolm.decrypt(ciphertext_b2a[:-16], ciphertext_b2a[-16:])))

    assert messages[0] == b'Message to Bob'
    assert messages[1] == b'Message to Alice'

    return