def createDatabase(self, count = 100, startFrom=1000):
     """
     Description: creates the database
     """
     
     # only allow 4 digit PINs
     if startFrom + count > 9999:
         startFrom = 1000
     if count > 1000:
         count = 100
         
     # 'privatekeys : where private keys are stored'
     if not os.path.exists('privatekeys'):
         os.makedirs('privatekeys')
     
     # database is again Database.pkl
     serverDB = open('Database.pkl','ab')
     
     for counter in range(startFrom, startFrom + count):
         # generates RSAkey pair, length = 1024 bits
         rsakey = RSAKeyHandling.generateRSAkeypair()
     
         # now we can write the public and private keys to different files
         # for the efficiency in verification and debugging, the values
         # have been chosen as such.
         # One must NOT confuse them as real values as they will be entirely different and generated
         # using a different set of algorithms
         voterID = 'voteid' + str(counter)
         PIN = counter
     
         # generate privatekey file name for voter
         keyfilename = 'privatekeys/' + voterID +'.pem'
     
         rsakey.save_pem(keyfilename, None, empty_callback)        
     
         # public key part of RSA in base64
         publickey_inbase64 = RSAKeyHandling.save_public_rsakey_to_b64string(rsakey)
     
         # sha256 of VoterID || PIN in base64
         hash_of_voterID_PIN = RSAKeyHandling.sha256hash_base64( voterID + str(PIN) )
         
         # create dictionary for a particular userID
         userDict = { 
             hash_of_voterID_PIN : {
                 'pkey' : publickey_inbase64 , 
                 'voted' : 0
                 }
             }
         
         # save dictionary; save userID info in the database
         pickle.dump(userDict, serverDB)
         serverDB.flush()
     
     serverDB.close()
def main():
    
    # seeding the PRNG with 1024 random bytes from OS
    # from M2Crypto
    Rand.rand_seed (os.urandom (1024))

    while 1:
        
    #======================================================
        # draw MAIN SCREEN
        mainScreen = MainScreen()
        centerWindow(mainScreen, WINDOW_WIDTH_MS, WINDOW_HEIGHT_MS)
        mainScreen.mainloop()
    
    #======================================================
        ### begin connecting to the srver
        
        # buffer length
        buffer_length = 5000
        
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
        # require a certificate from the server
    
        myhost = 'localhost'
        myport = 4321
    
        try:
            
            # ssl.CERT_NONE : cause we are using a self signed certificate
            ssl_sock = ssl.wrap_socket(s,cert_reqs=ssl.CERT_NONE,ssl_version=ssl.PROTOCOL_TLSv1)
            ssl_sock.connect((myhost, myport))
        
            #print repr(ssl_sock.getpeername())
            #print ssl_sock.cipher()
    
            #begin to receive DH key exchange data from server
            #in order of p,g,g^a
    
            serverDH_p   = base64.b64decode(ssl_sock.read(buffer_length))
            serverDH_g   = base64.b64decode(ssl_sock.read(buffer_length))
            serverDH_pub = base64.b64decode(ssl_sock.read(buffer_length))
            
            myDHobject = DH.set_params(serverDH_p, serverDH_g)
            
            # pick random p and generate g^b in myDhobject.pub
            myDHobject.gen_key()
            
            ssl_sock.sendall(base64.b64encode(myDHobject.pub))
            
            # generate shared AES Key
            sharedAESkey = myDHobject.compute_key(serverDH_pub)
            
            # print 'shared AES Key ', hexlify(sharedAESkey)
    
            # now we have a secure shared 256-bit AES key to send data around
            # it was Diffie Hellman, so even if TLS was borked, hopefully noone knows it
            
        except:
            #ZZZ change to msgbox
            tkMessageBox.showwarning(title = "Connection Error",
                                    message = "Cannot connect to server.")
            ssl_sock.close()
            # mainScreen.destroy()
            # print 'Cannot connect to server', myhost , ':' , myport
            continue
    
        
    #======================================================    
        # draw AUTHENTICATION SCREEN
        authScreen = AuthScreen()
        centerWindow(authScreen, WINDOW_WIDTH_AUTH, WINDOW_HEIGHT_AUTH)
        authScreen.mainloop()
        
        # voterID, privateRSAKey and PIN are valid
        
    #======================================================     
        
        # start validating login
        
        # get the chosen IV in base64
        chosen_IV_inbase64 = ssl_sock.read(buffer_length)
        
        # decode it from base64
        chosen_IV = b64decode(chosen_IV_inbase64)
        
        # print 'got chosen_IV ', hexlify(chosen_IV)
        
        # voterID || PIN 
        voterID_PIN = voterID + voterPIN
        
        # print 'voterID_PIN ', str(voterID_PIN)
        
        # calculate sha256 hash of voterID || PIN in base64
        hash_of_voterID_PIN_inbase64 = RSAKeyHandling.sha256hash_base64(voterID_PIN)
        
        # print 'hash of voterID_PIN in base 64 ', hash_of_voterID_PIN_inbase64
         
        # encrypt it using AES 256
        # key = sharedAESKey
        # IV = chosen_IV
        
        encrypted_AES_hash = RSAKeyHandling.AES_encryptor(sharedAESkey, hash_of_voterID_PIN_inbase64, chosen_IV) 
        
        # convert it into base64
        encrypted_AES_hash_inbase64 = base64.b64encode(encrypted_AES_hash)
        
        # send it to the server
        ssl_sock.sendall(encrypted_AES_hash_inbase64)
        
        # print 'sent to server encrypted_AES_hash_inbase64 ', encrypted_AES_hash_inbase64
        
        # wait for server to return user_exists or user_has_voted
        user_exists_base64 = ssl_sock.read(buffer_length)
        
        # decode it from base64
        user_exists = base64.b64decode(user_exists_base64)
        
        # print hexlify(user_exists)
        
        # decrypt it from AES using sharedAESkey and chosenIV
        user_exists = RSAKeyHandling.AES_decryptor(sharedAESkey, user_exists, chosen_IV)
        
        # print user_exists
        
        if user_exists == 'LOL_NO_WAY':
            # ZZZ change to msgbox
            tkMessageBox.showerror(title = "Not Eligible User",
                                    message = "Sorry, User Not Eligible to Vote")
            
            #print 'Sorry, user not eligible to vote'
            ssl_sock.close()
            continue
            ## ZZZ restart GUI , how ?
        
        # if user is eligible to vote
        
        # load privatekey 
        rsakey = RSA.load_key(privateRSAKey, RSAKeyHandling.empty_callback)
        
        try:
            # user_exists must contain the hash_normal encrypted with public key
            # decrypt it 
            decrypted_hash = rsakey.private_decrypt(user_exists, RSA.pkcs1_padding)
        except:
            # decryption didn't work
            # ZZZ change to msgbox
            tkMessageBox.showerror(title = "Decyption Error",
                                    message = "Sorry, Wrong User Credentials")
            ssl_sock.close()
            continue
            ## ZZZ restart GUI , how ?
            
        if decrypted_hash != hash_of_voterID_PIN_inbase64:
            # ZZZ change to msgbox
            tkMessageBox.showerror(title = "Decryption Error",
                                    message = "Sorry, Wrong User Credentials")
            # print 'Sorry, wrong user credentials'
            ssl_sock.close()
            continue
            # sys.exit()
        
        # now the user is authenticated and we can go on
        # start voting 
        
    #======================================================     
            
        #draw choice screen for president/congress/counsel/
        
        polls = {
            "president" : (1, 3),
            "congress" : (1, 5),
            "counsel" : (2, 4)
        }
        
        votes = {
            "president" : None,
            "congress" : None,
            "counsel" : None
        }
        
        for poll in polls:
            window = Group(poll, polls[poll][0], polls[poll][1]) # def __init__(self, _vf, _ms, _mo, master=None):
            centerWindow(window, WINDOW_WIDTH_MAIN, WINDOW_HEIGHT_MAIN)
            window.mainloop()
            votes[poll] = tuple(userVote) # store user vote
            del userVote[:] # clear user vote
        
        
        # send the votes to server
        # print votes
        
        votes_string = json.dumps(votes)
        
        # convert votes to base64
        votes_string_inbase64 = base64.b64encode(votes_string)
        
        # to load it later
        # votes_n = json.loads(vote_str)
        
        # begin to encrypt votes
        encrypted_votes_string = RSAKeyHandling.AES_encryptor(sharedAESkey, votes_string_inbase64, chosen_IV)
        
        # convert it to base64
        encrypted_votes_string_inbase64 = base64.b64encode(encrypted_votes_string)
        
        # send it to the server
        ssl_sock.sendall(encrypted_votes_string_inbase64)
        
        # wait for the thank you note
        encrypted_thankyou_inbase64 = ssl_sock.read(buffer_length)
        
        # decode it from base64
        encrypted_thankyou = base64.b64decode(encrypted_thankyou_inbase64)
        
        # decrypt it using AES
        decrypted_thankyou = RSAKeyHandling.AES_decryptor(sharedAESkey, encrypted_thankyou, chosen_IV)
        
        print decrypted_thankyou
        
        # draw END SCREEN
        endScreen = EndScreen()
        centerWindow(endScreen, WINDOW_WIDTH_ES, WINDOW_HEIGHT_MS)
        endScreen.mainloop()
        
        # note that closing the SSLSocket will also close the underlying socket
        ssl_sock.close()
def generate_voters(count=100,startfrom=1000):
    
    # only allow 4 digit PINs
    if startfrom+count > 9999:
        startfrom = 1000
    if count > 100:
        count = 100
    
    
    'privatekeys : where private keys are stores'
    if not os.path.exists('privatekeys'):
        os.makedirs('privatekeys')
        
    # 'publickeys : where the server DB will be saved'
    # if not os.path.exists('publickeys'):
    #    os.makedirs('publickeys')
    
    
    serverDB = open('Database.pkl','ab')
        
    # start generating count RSA keypairs
            
    for counter in range(startfrom,startfrom+count):
        
        # generates RSAkey pair, length = 1024 bits
        rsakey = RSAKeyHandling.generateRSAkeypair()
        
        # now we can write the public and private keys to different files
        voterID = 'voters' + str(counter)
        PIN = counter
        
        # generate privatekey file name for voter
        keyfilename = 'privatekeys/' + voterID +'.pem'
        
        rsakey.save_pem(keyfilename, None, empty_callback)        
        
        # public key part of RSA in base64
        publickey_inbase64 = RSAKeyHandling.save_public_rsakey_to_b64string(rsakey)
        
        # sha256 of VoterID || PIN in base64
        hash_of_voterID_PIN = RSAKeyHandling.sha256hash_base64( voterID + str(PIN) )
        
        # final string to write to DB in a line 
        # public key in base 64 SPACE hash of voterID||PIN SPACE 0 (0 because he has not voted yet)
        # final_db_record = publickey_inbase64 + ' ' + hash_of_voterID_PIN + ' '+'0\n'
        
        # print final_db_record
        # serverDB.write(final_db_record)
        
        userdict = { 
                    hash_of_voterID_PIN : {
                                           'pkey' : publickey_inbase64 , 
                                           'voted' : 0
                                           }
                    }
        
        pickle.dump(userdict, serverDB)
        serverDB.flush()
        
    serverDB.close()
        
    return 1
 def run(self):
     
     server_start = Server.Server()
     server_start.touchResultsFile()
     
     
     auditlogname = './AuditLog.pkl'
     if (os.path.exists(auditlogname)):
         os.remove(auditlogname)
         
     counterplname = './CounterPL.txt'
     if (os.path.exists(counterplname)):
         os.remove(counterplname)
     
     
     
     # try:
     #     os.remove(auditlogname)
     # except OSError:
     #     pass
     
     # try:
     #     os.remove(counterplname)
     # except OSError:
     #     pass
     
     
     
     # read it from config file later
     number_of_users = 100
     
     print 'server thread started'
     # change buffer length here in bits
     buffer_length = 5000
     
     # seeding the PRNG with 1024 random bytes from OS
     M2Crypto.Rand.rand_seed (os.urandom (1024))
     
     # host address
     # myhost = 'localhost'
     myhost = '' # all interfaces
     
     # port , which is hopefully not used 
     myport = 4321
     
     # number of concurrent connections to the server, will drop after that
     number_of_concurrent_connections = 3
         
     # binding a socket
     bindsocket = socket.socket()
     bindsocket.bind((myhost, myport))
     
     # start listening 
     bindsocket.listen(number_of_concurrent_connections)
     print 'listening'
     
     # read the pickle database
     databaseobject = Database.Database()
                 
     serverDB = databaseobject.readAllDataFromDatabase(number_of_users)
         
     # now we have the database loaded in voting_database
     
     while True:
         #ZZZ remover it later
         print 'inside while'
         
         # connection part
         mysocket, fromaddr = bindsocket.accept()
         
         # wrap SSL around the socket
         connstream = ssl.wrap_socket(mysocket,
                                  server_side=True,
                                  certfile="servercert",             # server certification file
                                  keyfile="serverkey",               # server private key file
                                  ssl_version=ssl.PROTOCOL_TLSv1)    # using TLS
         
         # deal_with_client(connstream)
         print 'Client connected from address ' + str(fromaddr)
         
         # beginning DH key exchange
         
         # print 'beginning DH Key exchange'
         
         # 256 = length
         # 2 = generator, which is usally 2 or 5
         # empty_callback : to avoid writing garbage to screen
         serverDH = DH.gen_params(256, 2, RSAKeyHandling.empty_callback)
         
         # generate the random number a, now g^a will be in serverDH.pub
         serverDH.gen_key()
         
         # now we need to send serverDH.p , serverDH.g and serverDH.pub
         # first they need to be converted to base64 and then sent
         
         connstream.sendall(base64.b64encode(serverDH.p))    # p
         connstream.sendall(base64.b64encode(serverDH.g))    # g
         connstream.sendall(base64.b64encode(serverDH.pub))  # g^a
         
         # now wait for the g^b from client to computer sharedAESkey
         clientDH_pub = base64.b64decode(connstream.read(buffer_length))
         
         # compute sharedAESkey
         sharedAESkey = serverDH.compute_key(clientDH_pub)
         
         # print 'shared AES Key ', hexlify(sharedAESkey)
         
         # now we have a 256 bit shared AES key to encrypt data with
         # now we can send voterID and check for correction in order to authenticate the voter
         # or send votes 
         
         
         # generate 16 byte chosen_IV
         chosen_IV = Rand.rand_bytes(16)
         
         # encode it to base64 (to avoid 00 bytes)
         chosen_IV_inbase64 = base64.b64encode(chosen_IV)
         
         # send it to client
         connstream.sendall(chosen_IV_inbase64)
         
         # print 'Sent chosen IV ' , hexlify(chosen_IV)
         
         # wait for the AES_encrypted sha hash of voterID || PIN in base64
         hash_inbase64 = connstream.read(buffer_length)
         
         # print 'received encrypted_hash_inbase64 ', hash_inbase64
         
         # decode it from base64
         encrypted_hash = base64.b64decode(hash_inbase64)
         
         # decrypt it from AES
         # key = sharedAESkey
         # iv = chosen_IV
         hash_normal = RSAKeyHandling.AES_decryptor(sharedAESkey, encrypted_hash, chosen_IV)
         
         # print 'hash_normal ', hash_normal
         
         # now we have the normal hash and can look up user data
         
         ####ZZZ  do a print (which user connected)
         
         print hash_normal
         
         if hash_normal in serverDB:
             
             print 'user in DB'
             
             # look it up from DB
             user_public_key_inbase64 = serverDB[hash_normal]['pkey']
         
             # we dont need to convert it from base64. our code does that
             # load the public rsa key into an rsakey for encryption
             rsakey = RSAKeyHandling.load_public_rsakey_from_b64string(user_public_key_inbase64)
                 
             # check if he has voted
             has_voted = serverDB[hash_normal]['voted']
                 
             # we dont want to immediately reject after we see that he has voted, to avoid timing attacks 
             # so we add the public key too anyway
         
             # if he has voted 
             # send VOTED
             if (has_voted == 1):
                 # print 'user has voted'
                 
                 # send LOL_NO_WAY
                 
                 # encrypt it using AES, sharedAESkey and chosen_IV
                 encrypted_msg = RSAKeyHandling.AES_encryptor(sharedAESkey, 'LOL_NO_WAY', chosen_IV)
                 
                 # convert it to base64
                 encrypted_msg_inbase64 = base64.b64encode(encrypted_msg)
                 # send it to the server
                 connstream.sendall(encrypted_msg_inbase64)
                 
                 # break the connection
                 # BYE BYE 
                 connstream.shutdown(socket.SHUT_RDWR)
                 connstream.close()
                 continue
             else: # user has not voted and can vote
                 # otherwise (if the user has not voted)
                 # encrypt the hash_normal with public key using RSA
         
                 # padding = PKCS1
                 encrypted_hash_normal = rsakey.public_encrypt(hash_normal, RSA.pkcs1_padding)   
                 
                 # encrypt it with AES
                 encrypted_hash_normal = RSAKeyHandling.AES_encryptor(sharedAESkey, encrypted_hash_normal, chosen_IV)
                 
                 # encode it to base64 to send
                 encrypted_hash_normal_inbase64 = base64.b64encode(encrypted_hash_normal)
                 
                 # send it 
                 connstream.sendall(encrypted_hash_normal_inbase64)
                 
                 # print 'sent public encrypted'
                 
         else: # if he is not in DB
             
             # send LOL_NO_WAY
                 
             # encrypt it using AES, sharedAESkey and chosen_IV
             encrypted_msg = RSAKeyHandling.AES_encryptor(sharedAESkey, 'LOL_NO_WAY', chosen_IV)
                 
             # convert it to base64
             encrypted_msg_inbase64 = base64.b64encode(encrypted_msg)
             # send it to the server
             connstream.sendall(encrypted_msg_inbase64)
                 
             # break the connection
             # BYE BYE 
             connstream.shutdown(socket.SHUT_RDWR)
             connstream.close()
             continue
             
         
         # now we need to wait for votes to be sent
         
         # read votes sent to server
         encrypted_votes_inbase64 = connstream.read(buffer_length)
         
         # decode it from base64
         encrypted_votes = base64.b64decode(encrypted_votes_inbase64)
         
         # decrypt it using AES, we will get a base64 encoding of a json string of the dictionary
         try:
             decrypted_votes_inbase64_json = RSAKeyHandling.AES_decryptor(sharedAESkey, encrypted_votes, chosen_IV)
         except:
             # bad votes received
             connstream.shutdown(socket.SHUT_RDWR)
             connstream.close()
             continue
         
         
         # decode it from base64
         decrypted_votes_json = base64.b64decode(decrypted_votes_inbase64_json)
         
         # de-json it
         decrypted_votes = json.loads(decrypted_votes_json)
         
         # note in the vote log, we don't want people to vote many times, THIS IS NOT IRAN or maybe it is ? :D
         serverDB[hash_normal]['voted'] = 1
         
         # making server object to use the utility functions
         myserver = Server.Server()
         
         auditDict = {
                      hash_normal:{
                                   'president': decrypted_votes['president'],
                                   'congress' : decrypted_votes['congress'],
                                   'counsel' : decrypted_votes['counsel']
                                  }
                      }
         
         
         # add votes to the DB
         myserver.addToAuditLogFile(auditDict)
         myserver.addToResultsFile(decrypted_votes)
         
         # Make vote confirmation message
         thankyou_msg = 'Votes OK'
         
         # Encrypt it
         encrypted_thanks = RSAKeyHandling.AES_encryptor(sharedAESkey, thankyou_msg, chosen_IV)
         
         # convert it to base64
         encrypted_thanks_inbase64 = base64.b64encode(encrypted_thanks)
         
         # send it to the client
         connstream.sendall(encrypted_thanks_inbase64)
         
         #finally:
         connstream.shutdown(socket.SHUT_RDWR)
         connstream.close()