def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server or just on the client if self.server or self.client: my_public_key, my_private_key = create_dh_key() my_public_iv, my_private_iv = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key, flag = self.recv() their_public_key = int(their_public_key) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) self.shared_hash = shared_hash.encode("ascii") # Send them our public iv seed self.send(bytes(str(my_public_iv), "ascii")) # Receive their public iv seed their_public_iv, flag = self.recv() their_public_iv = int(their_public_iv) # Obtain our shared iv shared_iv = str(calculate_iv(their_public_iv, my_private_iv)).encode("ascii") print("Shared hash: \"{}\"".format(shared_hash)) print("--------------------------------------") # initialize the cipher self.cipher = AES.new(shared_hash[:32], AES.MODE_CBC, shared_iv[:16])
def test_dh(self): from dh import create_dh_key, calculate_dh_secret for _ in range(5): alice_pub, alice_priv = create_dh_key() bob_pub, bob_priv = create_dh_key() alice_sec = calculate_dh_secret(bob_pub, alice_priv) bob_sec = calculate_dh_secret(alice_pub, bob_priv) self.assertEqual(alice_sec, bob_sec)
def initiate_session(self): # Perform the initial connection handshake # Create our public & private key my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) if self.server: # Create the initialization vector iv = get_random_bytes(AES.block_size) # Send them the initialization vector self.send(iv) elif self.client: # Receive the initialization vector iv = self.recv() # Convert the iv to an integer. We send the iv as a byte array, as that's # how python wants things sent over a connection iv = int.from_bytes(iv, byteorder='big') # Calculate the shared secret self.shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(self.shared_hash.hexdigest())) # Create the counter object for the cipher. Crypto handles the incrementing ctr = Counter.new(128, initial_value=iv) # Create the cipher self.cipher = AES.new(self.shared_hash.digest(), AES.MODE_CTR, counter=ctr)
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server or just on the clientasdsad if self.server or self.client: # Calculate Diffie-Hellman key pair my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret self.shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(self.shared_hash)) self.shared_hash = bytes(self.shared_hash, "ascii") # Used AES instead of XOR for stronger encryption. iv = Random.new().read(AES.block_size) # Define the shared_hash and the cipher # Shared hash to be used as the key is declared as self.SH to make it reusable in other cipher # Used AES Mode of CBC self.SH = self.shared_hash[:16] self.cipher = AES.new(self.SH, AES.MODE_CBC, iv) # Create hmac_secret for HMAC # HMAC secret is taken from the shared key so the secret key is stronger self.hmac_secret = self.shared_hash[17:]
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server or just on the client if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) # key encryption key # AES-256, might change the mode self.cipher = AES.new(shared_hash[:32], AES.MODE_CFB, shared_hash[32:48]) #initialise a counter to prevent replay attacks #use the remaining bytes from the DH handshake so this value is secret self.counter = int(shared_hash[48:]) #the server will generate a random key and send it via and encrypted channel if self.server: f = open("/dev/random", "rU") newkey = f.read(32) newiv = f.read(16) self.send(newkey) self.send(newiv) if self.client: newkey = self.recv() newiv = self.recv() #now build the content encryption cipher self.cipher = AES.new(newkey, AES.MODE_CFB, newiv)
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server or just on the client if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret self.key = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(self.key)) # Create a counter from PyCrypto library. Has 128 bits and uses a randomly generated initial value counter = Counter.new(128) # Creating AES cipher with 16 bit key, counter mode and counter initialised in previous line self.cipher = AES.new(self.key[:16], AES.MODE_CTR, counter=counter) # Changes from XOR to AES self.send_seed = read_hex(self.key[:4]) self.recv_seed = self.send_seed print("Send seed: {}".format(self.send_seed)) print("Recv seed: {}".format(self.recv_seed))
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server or just on the client if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key, key_len=64) print("Shared session key: {}".format(binascii.hexlify(shared_hash))) # The first 256 bit from shared hash is the key of hmac self.hmac = HMAC.new(shared_hash[:32], digestmod=SHA256) # TODO: exchange iv # TODO: use a global bloom filter to avoid iv re-use in a reasonable time period, # and we can add a time stamp after iv to avoid replay if the iv filter is reset # The last 256 bit from shared hash is the key of hmac cipher_key = shared_hash[:-32] # TODO: init cipher with aes-cfb using cipher_key and iv # Default XOR algorithm can only take a key of length 32 self.cipher = XOR.new(shared_hash[:4])
def initiate_session(self): # Perform the initial connection handshake # Create our public & private key my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) if self.server: # Create the initialization vector iv = get_random_bytes(AES.block_size) # Send them the initialization vector self.send(iv) elif self.client: # Receive the initialization vector iv = self.recv() # Convert the iv to an integer. We send the iv as a byte array, as that's # how python wants things sent over a connection iv = int.from_bytes(iv, byteorder='big') # Calculate the shared secret self.shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(self.shared_hash.hexdigest())) # Create the counter object for the cipher. Crypto handles the incrementing ctr = Counter.new(128, initial_value = iv) # Create the cipher self.cipher = AES.new(self.shared_hash.digest(), AES.MODE_CTR, counter=ctr)
def initiate_session(self): ''' Perform the initial connection handshake for agreeing on a shared secret. This can be broken into code run just on the server or just on the client. All the function want to do here is to ensure the data confidentiality. Key: A key used to generate IV. Obtained from shuffled shared hash. ''' if self.server or self.client: # DH crete keys my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret self.shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(self.shared_hash)) key = list(self.shared_hash) random.shuffle(key) # Generate IV iv = bytes(str(key).encode()[:AES.block_size]) # Convert hexstr to byte self.shared_hash = bytes.fromhex(self.shared_hash) # AES encrypt with CFB mode self.cipher = AES.new(self.shared_hash, AES.MODE_CFB, iv) self.hmac = HMAC.new(self.shared_hash, None, SHA256.new())
def initiate_session(self): # Perform the initial connection handshake for # agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server # or just on the client if self.server or self.client: # Create the DH key and store into these two variables # "my_private_key" is a # "my_public_key" is the g_a, # which means g to the power of a mod p my_public_key, my_private_key = create_dh_key() # Send out public key # For client, it sends g_a as "my_public_key" self.send(bytes(str(my_public_key), "ascii")) # For server, receive public key g_a as "their_public_key" their_public_key = int(self.recv()) # The following codes was designed to send g. # However, according to rfc3521, the g should be 2, # instead of a random number # Thus the codes has been abandoned ''' # send client's g if self.client: self.send(bytes(str(my_public_key), "ascii")) self.send(bytes(str(g), "ascii")) their_public_key = int(self.recv()) in the server,re calculate g_a if self.server: their_public_key = int(self.recv()) g = int(self.recv()) #print("g:",g) my_public_key = calculate_g_a(g,my_private_key) self.send(bytes(str(my_public_key), "ascii")) ''' # Obtain hased shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) # The original file use XOR one time padding and # we changed it to aes128, key size 16bytes, mode cfb # Becuase the key size is 16 bytes, we take 16 bytes of # the hashed shared key self.aes_key = shared_hash[:16] # set self.cipher object so that it will enter the "if" # in "send" function self.cipher = AES.new(self.aes_key, AES.MODE_CFB, self.inital_vector)
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret # This can be broken into code run just on the server or just on the clientasdsad if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) # Take first 16 bytes of the (32 byte) hash as the key self.key = shared_hash[:16] print("Shared hash: {}".format(shared_hash.hex()))
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server or just on the client if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash))
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server or just on the client if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) # Set the key to the shared hash (should it always be the first 16?) self.key = shared_hash
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret # This can be broken into code run just on the server or just on the client if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) # Default XOR algorithm can only take a key of length 32 self.cipher = XOR.new(shared_hash[:4])
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret and convert it to bytes. self.shared_hash = bytes.fromhex( calculate_dh_secret(their_public_key, my_private_key)) print("Shared hash (in bytes): {}".format(self.shared_hash)) # Our IV is the first 16 bytes of the shared key which is cryptographically secure iv = self.shared_hash[:16] # Our cipher is AES operating in CFB mode self.cipher = AES.new(self.shared_hash, AES.MODE_CFB, iv)
def initiate_session(self): if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret self.shared_key = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(self.shared_key)) aes_key = self.shared_key[:32] #shortnening the value of aes_key to match the AES mode requirement self.iv = aes_iv() self.cipher = AES.new(aes_key, AES.MODE_CFB, self.iv)
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(str(my_public_key)) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret self.shared_hash = calculate_dh_secret(their_public_key, my_private_key) if self.verbose: print("Shared hash: {}".format(self.shared_hash)) self.shared_hash = bytes.fromhex(self.shared_hash) # AES is used in CFB mode with an IV that is initialised each time send() is called iv = self.shared_hash[:16] # set the initialization vector self.cipher = AES.new(self.shared_hash, AES.MODE_CFB, iv) # create cipher object
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret my_public_key, my_private_key = create_dh_key() # if I'm client. i.e., initialize the connection if self.client: # Simple rename to improve readability client_private_key, client_public_key = my_private_key, my_public_key # Send them our public key along with the IV IV = Random.new().read(AES.block_size) # msg structure: IV+msg clientInfo = b"".join([IV, bytes(str(client_public_key), 'ascii')]) self.send(clientInfo) # Receive their public key server_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(server_public_key, client_private_key) # if I'm server. i.e., accept the connection elif self.server: # Rename server_private_key, server_public_key = my_private_key, my_public_key # only send them our publick key, let them choose the IV self.send(bytes(str(server_public_key), "ascii")) clientInfo = self.recv() IV = clientInfo[:AES.block_size] client_public_key = int(clientInfo[AES.block_size:]) shared_hash = calculate_dh_secret(client_public_key, server_private_key) else: raise AttributeError("You have to be either a server or a client") # After the shared hash is obtained, we do three things: # 1. Derive AES key from it # 2. Generate HMAC with AES key # 3. Generate a PRNG using key as seed # As we are confident that the DH algorithm will protect the shared hash, we believe the key won't be compromised. key = shared_hash[:self.KEY_LENGTH] self.cipher = AES.new(key, AES.MODE_CFB, IV) self.hmac = HMAC.new(bytes(key, 'ascii'), digestmod=SHA256.new()) # we use SHA256 here self.prng = aesg() self.prng.reseed(bytes(key, 'ascii')) print("session initialized")
def initiate_session(self): # The initial connection handshake for agreeing on a shared secret if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) # Sets the variables required for encryption and hashing IV = '\x16'*16 shared_hash = bytes(shared_hash,"ascii") self.cipher = AES.new(shared_hash[:32], AES.MODE_CFB, IV) self.hmac = HMAC.new(shared_hash[:32])
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(str(my_public_key)) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret self.shared_hash = calculate_dh_secret(their_public_key, my_private_key) if self.verbose: print("Shared hash: {}".format(self.shared_hash)) self.shared_hash = bytes.fromhex(self.shared_hash) # Use AES in CFB mode for encryption iv = self.shared_hash[:16] # set the initialization vector self.cipher = AES.new(self.shared_hash, AES.MODE_CFB, iv) # create cipher object
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret # This can be broken into code run just on the server or just on the client if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) # Default XOR algorithm can only take a key of length 32 #self.cipher = XOR.new(shared_hash[:4]) self.cipher = AES.new(shared_hash[:32]) # AES-256 accepts keys of 32 bytes in length
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) # Seed the CSPRNG with our shared secret self.csprng.reseed(shared_hash.encode()) # Generate a 256-bit AES key self.key = self.csprng.pseudo_random_data(SHA256.digest_size) # Set up a SHA256 HMAC with a 256-bit key generated by the CSPRNG self.hmac = HMAC.new(self.csprng.pseudo_random_data(32), None, SHA256.new())
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server or just on the client if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) #Sets the IV and key for the AES session from the hashed DH value iv = shared_hash[:16] key = shared_hash[:32] self.cipher = AES.new(key, AES.MODE_CFB, iv)
def hamc_sha256(strContent): h=hmac.new(skey.encoude(),strContent.encode(),hashlib.sha256) return base64.b64encode(h.digest()) #pass ### TODO: Your code here! # This can be broken into code run just on the server or just on the clientasdsad if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash.hex())) # Default XOR algorithm can only take a key of length 32 self.cipher = XOR.new(shared_hash[:4])
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server or just on the client if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) # Create a 128 bit counter from PyCrypto library. counter = Counter.new(128) # Creating AES cipher with 16 bit key, counter mode and the counter initialised # in previous line self.cipher = AES.new(shared_hash[:16], AES.MODE_CTR, counter = counter)
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server or just on the client if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), ch_enc_code)) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) # save hash in byte format for use as key self.shared_hash = bytes.fromhex(shared_hash) # Set the cipher_available equal to true so that # bot can use cipher with shraed_hash to encrypt and decrypt self.cipher_available = True
def initiate_session(self): if self.server or self.client: ###########Implement key exchange using Diffie-Hellman key exchange when peerto-peer connections are made between bots############## my_public_key, my_private_key = create_dh_key() self.send(bytes(str(my_public_key), "ascii")) # send them our public key their_public_key = int(self.recv()) # receive their public key shared_hash = calculate_dh_secret(their_public_key, my_private_key) # Obtain our shared secret print("shared hash is: {}".format(shared_hash)) self.shared_hash = shared_hash # refer shared hash self.key = self.shared_hash[32:] # last 32 bytes of the shared hash is key print("self.key is: " + str(self.key)) self.iv = self.shared_hash[16:] # last 16 bytes of the shared hash is IV # IV is for Confidentiality of the channe print("self.key initiate_session is: " + str(self.iv)) self.cipher = (self.key, AES.MODE_CBC, self.iv)
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server or just on the clientasdsad if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash, shared_secret = calculate_dh_secret( their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash.hex())) self.mac = HMAC.new(shared_hash[:16]) # Default XOR algorithm can only take a key of length 32 iv = Random.new().read(AES.block_size) self.key = shared_hash[:16] self.cipher = AES.new(shared_hash[:16], AES.MODE_CBC, iv) #record msg and recive timestemp to prevent replay attack self.cache = [int(time.time()), ""]
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret self.verbose = True if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(str(my_public_key)) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret self.shared_hash = calculate_dh_secret(their_public_key, my_private_key) if self.verbose: print(Fore.MAGENTA + "[+] Shared hash: {}".format(self.shared_hash) + Style.RESET_ALL) #Print the shared key self.shared_hash = bytes.fromhex(self.shared_hash) # Use AES in CFB mode for encryption as its more secure than ECB. Also AES is used by the US Government iv = self.shared_hash[:16] # set the initialization vector self.cipher = AES.new(self.shared_hash, AES.MODE_CFB, iv) # create cipher object
def initiate_session(self): if self.server or self.client: my_public_key, my_private_key = create_dh_key() self.send(bytes(str(my_public_key), "ascii")) # Send them our public key their_public_key = int(self.recv()) # Receive their public key shared_hash = calculate_dh_secret(their_public_key, my_private_key) # Obtain our shared secret print("Shared hash: {}".format(shared_hash)) # Prints shared hash on session establishment self.shared_hash = shared_hash # References shared hash self.key = self.shared_hash[32:] # Key is taken from the last 32 bytes of the shared key print("SELF.KEY is: " + str(self.key)) # Prints self key as a string self.iv = self.shared_hash[16:] # IV is taken from the last 16 bytes of the shared key print("SELF.IV in INITIATE_SESSION is: " + str(self.iv)) # Prints IV as string self.cipher = (self.key, AES.MODE_CBC, self.iv)
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server or just on the client if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret self.shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(self.shared_hash)) self.salt = Random.new().read(64) #randomly generate a 64 bit salt print("64 bit salt: " + str(self.salt) + "\n") derivedKey = KDF.PBKDF2(self.shared_hash,self.salt,32) #generate derived key from salt, length should be 32 bits so that when split in 2, it provides a 16 bit key for AES print("32 bit derived key: " + str(derivedKey) + "\n"); cipherKey, HMACkey = derivedKey[:16], derivedKey[16:] #split derived key in half and use each 16 bit half as cipher and hmac key respectively print("16 bit cipher and hmac keys" + str(cipherKey) + ", " + str(HMACkey) + "\n") self.iv = Random.new().read(AES.block_size) #randomly generate initialisation vector the size of the AES block size self.cipher = AES.new(cipherKey, AES.MODE_CBC, self.iv) #generate cipher object with cipher key self.hashMAC = HMAC.new(HMACkey, digestmod = SHA512) #generate HMAC object with HMAC key
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server or just on the clientasdsad if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) self.shared_hash = shared_hash print("Shared hash: {}".format(shared_hash)) #print("Shared hash length: {}".format(len(shared_hash))) #Using HC_256 stream cipher as a PRNG. Using shared_hash as seed of PRNG # to generate the 256-bit key and the 128-bit IV for this communication AES_key = HC_256(shared_hash)[:32] AES_iv = HC_256(shared_hash)[-16:] #Using AES encryption in CBC mode (block cipher) self.cipher = AES.new(AES_key, AES.MODE_CBC, AES_iv)
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret ### TODO: Your code here! # This can be broken into code run just on the server or just on the client if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) # Default XOR algorithm can only take a key of length 32 # Creation of the initialisation vector using XOR algorithm and shared hash found in DH iv = XOR.new(shared_hash[:4]) shared_secret = their_public_key * my_private_key #Cipher creation using AES mode CBC self.cipher = AES.new(shared_secret, AES.MODE_CBC, iv)
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret self.time_of_last_communication = datetime.datetime.now() # Project code here... # This can be broken into code run just on the server or just on the client if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) # Default XOR algorithm can only take a key of length 32 # (4 byte) and thus is very insecure and impractical. Also bits can be changed # easily with stream ciphers. Hence, we've changed to a block cipher (CBC). # We are using AES-256 (key is 32 byte string). self.iv = shared_hash[:16] # from week 04 lecture, block size is 128-bits. Using first 16 bytes of shared_hash. self.key = shared_hash[32:] # from week 04 lecture, key length up to 256-bits. Using last 32 bytes of shared_hash. self.cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret # TODO: Your code here! # This can be broken into code run just on the server or just on the client # To avoid random number generated on the server and the client to coincide(if it happens), we choose different # range of integers if self.server: self.counter = random.randint(0, 10000000) if self.client: self.counter = random.randint(11000000, 50000000) if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret self.shared_hash = calculate_dh_secret(their_public_key, my_private_key) self.keyExhangePerformed = True
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret if self.server or self.client: my_public_key, my_private_key = create_dh_key() # Send them our public key self.send(bytes(str(my_public_key), "ascii")) # Receive their public key their_public_key = int(self.recv()) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) # print("Shared hash: {}".format(shared_hash)) #Create Hmac self.hmac = HMAC.new(shared_hash, digestmod=SHA256) # Uses first 4 bytes of shared hash self.ctr = Counter.new(128, initial_value=int.from_bytes(shared_hash[4:], byteorder='big')) # Using CTR AES to encrypt with incrimenting counter thats the same on both ends self.cipher = AES.new(shared_hash, AES.MODE_CTR, counter=self.ctr)
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret if not self.rsaKey: raise RuntimeError("Rsa key must be initialized") iv_length = AES.block_size dh_key_length = 256 # client is the parent - has private rsaKey if self.client: if not self.rsaKey.has_private(): raise RuntimeError("Client needs the private key") # initialize dh my_public_key, my_private_key = create_dh_key() # Receive the challenge from the child (iv g**a) encrypted_data = self.recv() tmpCipher = PKCS1_OAEP.new(self.rsaKey) decrypted_data = tmpCipher.decrypt(encrypted_data) if len(decrypted_data) < iv_length + 1 + dh_key_length: raise RuntimeError("Expected 'IV g**a'") self.iv = int.from_bytes(decrypted_data[:iv_length], byteorder='big') their_public_key = int.from_bytes(decrypted_data[iv_length + 1:], byteorder='big') # Respond to the challenge by the child (iv g**b signed) msg_to_be_signed = decrypted_data[: iv_length] + b' ' + my_public_key.to_bytes( dh_key_length, byteorder='big') h = SHA.new() h.update(msg_to_be_signed) signer = PKCS1_PSS.new(self.rsaKey) signature = signer.sign(h) # send the signed message self.send(msg_to_be_signed + bytes(' ', "ascii") + signature) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) # server is the child - has public rsaKey if self.server: # Generate the IV self.iv = int.from_bytes(Random.new().read(iv_length), byteorder='big') # dh init my_public_key, my_private_key = create_dh_key() # send the challenge challenge = self.iv.to_bytes( AES.block_size, byteorder='big') + bytes( ' ', "ascii") + my_public_key.to_bytes(dh_key_length, byteorder='big') tmpCipher = PKCS1_OAEP.new(self.rsaKey) encrypted_data = tmpCipher.encrypt(challenge) self.send(encrypted_data) # verify the response response = self.recv() if len(response) < iv_length + 1 + dh_key_length + 2: raise RuntimeError("Expected 'IV g**b signed'") iv = int.from_bytes(response[:iv_length], byteorder='big') if iv != self.iv: raise RuntimeError("IV given was incorrect, challenge failed") # verify the signature msg_to_be_verified = response[:(iv_length + 1 + dh_key_length)] signature = response[(iv_length + 1 + dh_key_length + 1):] h = SHA.new() h.update(msg_to_be_verified) signer = PKCS1_PSS.new(self.rsaKey) if not signer.verify(h, signature): raise RuntimeError("Signature was incorrect, challenge failed") their_public_key = int.from_bytes( response[(iv_length + 1):(dh_key_length + iv_length + 1)], byteorder='big') shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) # set up AES cipher self.cipher = AES.new(shared_hash, AES.MODE_CFB, self.iv.to_bytes(iv_length, byteorder='big')) print("Authentication Successful")
def initiate_session(self): # Perform the initial connection handshake for agreeing on a shared secret if not self.rsaKey: raise RuntimeError("Rsa key must be initialized") iv_length = AES.block_size dh_key_length = 256 # client is the parent - has private rsaKey if self.client: if not self.rsaKey.has_private(): raise RuntimeError("Client needs the private key") # initialize dh my_public_key, my_private_key = create_dh_key() # Receive the challenge from the child (iv g**a) encrypted_data = self.recv() tmpCipher = PKCS1_OAEP.new(self.rsaKey) decrypted_data = tmpCipher.decrypt(encrypted_data) if len(decrypted_data) < iv_length + 1 + dh_key_length: raise RuntimeError("Expected 'IV g**a'") self.iv = int.from_bytes(decrypted_data[:iv_length], byteorder='big') their_public_key = int.from_bytes(decrypted_data[iv_length+1:], byteorder='big') # Respond to the challenge by the child (iv g**b signed) msg_to_be_signed = decrypted_data[:iv_length] + b' ' + my_public_key.to_bytes(dh_key_length, byteorder='big') h = SHA.new() h.update(msg_to_be_signed) signer = PKCS1_PSS.new(self.rsaKey) signature = signer.sign(h) # send the signed message self.send(msg_to_be_signed + bytes(' ',"ascii") + signature) # Obtain our shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) # server is the child - has public rsaKey if self.server: # Generate the IV self.iv = int.from_bytes(Random.new().read(iv_length), byteorder='big') # dh init my_public_key, my_private_key = create_dh_key() # send the challenge challenge = self.iv.to_bytes(AES.block_size, byteorder='big') + bytes(' ', "ascii") + my_public_key.to_bytes(dh_key_length, byteorder='big') tmpCipher = PKCS1_OAEP.new(self.rsaKey) encrypted_data = tmpCipher.encrypt(challenge) self.send(encrypted_data) # verify the response response = self.recv() if len(response) < iv_length + 1 + dh_key_length + 2: raise RuntimeError("Expected 'IV g**b signed'") iv = int.from_bytes(response[:iv_length], byteorder='big') if iv != self.iv: raise RuntimeError("IV given was incorrect, challenge failed") # verify the signature msg_to_be_verified = response[:(iv_length + 1 + dh_key_length)] signature = response[(iv_length + 1 + dh_key_length + 1):] h = SHA.new() h.update(msg_to_be_verified) signer = PKCS1_PSS.new(self.rsaKey) if not signer.verify(h, signature): raise RuntimeError("Signature was incorrect, challenge failed") their_public_key = int.from_bytes(response[(iv_length+1):(dh_key_length + iv_length + 1)], byteorder='big') shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) # set up AES cipher self.cipher = AES.new(shared_hash, AES.MODE_CFB, self.iv.to_bytes(iv_length, byteorder='big')); print("Authentication Successful")
def initiate_session(self): # spawn key material my_public_key, my_private_key = create_dh_key() # set some "magic numbers" - ie. "key material" sizes iv_length = AES.block_size key_length = 256 sig_length = iv_length + key_length # if we are in "client" mode - we receive an encrypted-authentication package from the server. # the "client" has to extract an IV and a public key from the package, and use these materials # to create a "signature", which is appended to a message that is sent to the server. if self.client: # receive package encrypted_data = self.recv() # spawn the auth cipher and decrypt the package data = PKCS1_OAEP.new(self.rsa_key).decrypt(encrypted_data) # grab the iv from the start of the package self.iv = int.from_bytes(data[:iv_length], byteorder='big') # grab the public key from the back of the package their_public_key = int.from_bytes(data[iv_length + 1:], byteorder='big') # make a new message with the IV and OUR OWN public key message = data[:iv_length] + b' ' + my_public_key.to_bytes( key_length, byteorder='big') h = SHA.new() # hash the message h.update(message) # spawn an rsa signature and sign it with the hashed message and append the signature to the message # --> send message to server (send function has encryption) self.send(message + bytes(' ', "ascii") + PKCS1_PSS.new(self.rsa_key).sign(h)) # if we are in "server" mode - we generate our own IV and package it with our public key material. # this message is encrypted and sent to the "client". # the IV's of the returned message and our own can be compared directly to preserve integrity if self.server: # spawn initialization vector self.iv = int.from_bytes(Random.new().read(iv_length), byteorder='big') # concatenate the iv and the server public key message = self.iv.to_bytes(iv_length, byteorder='big') + bytes( ' ', "ascii") + my_public_key.to_bytes(key_length, byteorder='big') # spawn the auth cipher, encrypt the message and send self.send(PKCS1_OAEP.new(self.rsa_key).encrypt(message)) # wait for response response = self.recv() # IV integrity check if int.from_bytes(response[:iv_length], byteorder='big') != self.iv: raise RuntimeError("Poisoned IV") # spawn hash h = SHA.new() # peel off the signature h.update(response[:(sig_length + 1)]) # spawn signer signer = PKCS1_PSS.new(self.rsa_key) # signature integrity check if not signer.verify(h, response[(sig_length + 2):]): raise RuntimeError("...This isn't the master...") # we extract the client's public key their_public_key = int.from_bytes(response[(iv_length + 1):(sig_length + 1)], byteorder='big') # spawn the shared secret shared_hash = calculate_dh_secret(their_public_key, my_private_key) print("Shared hash: {}".format(shared_hash)) # spawn the cipher using gathered keying materials self.cipher = AES.new(shared_hash, AES.MODE_CFB, self.iv.to_bytes(iv_length, byteorder='big')) print("Authentication Successful")