#!/usr/bin/env python3.4 
import socket
from Crypto.Cipher import AES
import hashlib
import base64

"""
Network Security Hacking Challenges 2014

Challenge: Enter your name into our database.
If you prefer to stay pseudonymous, you may instead enter your "tag".
Please use the same name/tag throughout the semester.

Rules:
1) Be fair! Do not DOS our systems.
2) Please try to enter your name/tag only once


Database at
$ nc netsec.net.in.tum.de 30004
"""
# WARNING:
# This is just a sample client.
# use at your own risk!




def main():
    #create socket and connect to server1, sending the user credentials
    HOST = '131.159.15.68' #netsec.net.in.tum.de
    PORT1 = 20004            
    PORT2 = 20104            
    s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    #Uncomment the following lines if you want to use IPv6 (not necessary)
    #s1 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
    #s2 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
    #HOST = '2001:4ca0:2001:18:216:3eff:fef0:3933'

    #our protocol is linebased, so each message you send should end with \n, otherwise it may result in errors!

    s1.connect((HOST, PORT1))
    s1f=s1.makefile("rw") #use a file abstraction for the sockets
    #first step of diffie hellman (compare slides)
    data = s1f.readline()
    print("from s1 to s2: "+data)
    #forward received data to Server 2
    s2.connect((HOST, PORT2))
    s2f=s2.makefile("rw") #use a file abstraction for the sockets
    s2f.write(data)    
    s2f.flush()
    #receive answer (second step of DH)
    data = s2f.readline()
    print("from s2 to s1: "+data)
    #forward received data to Server 1
    s1f.write(data)
    s1f.flush()
    #now Server 1 sends a encrypted password,tag combinaton which will be entered into the database if the password is correct
    #used algorithm for encrytption is AES-CBC
    #since AES-CBC requeires a block size of 16bytes, we use padding before encryption and remove the padding after decryption.
    #As padding algorithm we use simple zero padding (http://en.wikipedia.org/wiki/Padding_%28cryptography%29#Zero_padding)
    #example padding: "HelloWorld"->"HelloWorld000000" length 10 byte, so 6 byte missing --> add "0"*6 to string 
    #if the stringlength already is a multiple of 16 byte, we don't add anything  
    #we used thy pycrypto library for this purpose(https://pypi.python.org/pypi/pycrypto)
    #doku: https://www.dlitz.net/software/pycrypto/api/current/
    #as key for AES we used aes_key=hashlib.sha256(key.encode()).digest(), where key is the resulting DH key from the previous exchange as string
    #our iv is chosen randomly (16 byte) an is sent with the ciphertext.
    #format is "b64(iv),b64(ciphertext)", where b64 means the values iv and ciphertext are base64 encoded.
    #since AES returns a byte object and we work with strings in our communication protocol, we use base64 encoding on that object before sending it and decode it again on the receiverside.(same for the iv)

    data = s1f.readline()
    print("from s1 to s2: "+data) 
    
    #todo: change the tag to your own tag



    #forward received data to Server 2
    s2f.write(data)
    s2f.flush()

    #receive answer
    data = s2f.readline()
    print("Final response from s2: "+data)
    
    s1f.close()
    s2f.close()
    s1.close()
    s2.close()

main()

