def create_hello(self, conn): server_hello = bytearray(1249 * '\x00', 'hex') server_hello[0] = '\x02' server_hello[1:5] = util.int_to_binary(1244, 4) server_hello[5] = '\x64' server_hello[6] = '\x65' # Generate random bytes for server_random server_random = '' for i in range(7, 39): server_random += chr(random.randint(0, 255)) server_hello[7:39] = util.text_to_binary(server_random) self.server_randoms[conn] = server_random # Get next sessionID server_id = util.int_to_binary(self.max_server_id, 2) self.max_server_id += 1 self.max_server_id %= 65535 server_hello[39:41] = server_id self.session_ids[conn] = server_hello[39:41] server_hello[41:43] = '\x00\x2F' server_hello[43] = '\x01' server_hello[44:1247] = self.cert server_hello[1247:1249] = '\xF0\xF0' print "Sent ServerHello" return server_hello
def create_key_exchange(self): # First generate pre_master pre_master = "" for _ in range(48): pre_master += chr(random.randint(0, 127)) # Encrypt it and get the encrypted length pre_master_encrypt = rsa.encrypt_rsa(rsa.text_to_decimal(pre_master), self.server_pubkey.e, self.server_pubkey.n) key_length = util.get_length_in_bytes(pre_master_encrypt) client_key_exchange = bytearray((1234 + key_length) * '\x00', 'hex') client_key_exchange[0] = '\x03' client_key_exchange[1:5] = util.int_to_binary(1229 + key_length, 4) client_key_exchange[5:7] = self.session_id client_key_exchange[7:1210] = self.cert client_key_exchange[1210:1212] = util.int_to_binary(key_length, 2) client_key_exchange[1212:1212 + key_length] = util.int_to_binary(pre_master_encrypt, key_length) hash_credentials = sha1.sha1(self.userID + self.password) hash_credentials_nonced = sha1.sha1(sha1.digestToString(hash_credentials) + self.server_random) client_key_exchange[1212 + key_length:1232 + key_length] = util.int_to_binary( hash_credentials_nonced, 20) client_key_exchange[1232 + key_length:1234 + key_length] = '\xF0\xF0' # Calculate and store the master_secret self.master_secret = \ sha1.sha1( sha1.digestToString(sha1.sha1(pre_master + sha1.digestToString( sha1.sha1('A' + pre_master + self.client_random + self.server_random)))) + sha1.digestToString(sha1.sha1(pre_master + sha1.digestToString( sha1.sha1('BB' + pre_master + self.client_random + self.server_random)))) + sha1.digestToString(sha1.sha1(pre_master + sha1.digestToString( sha1.sha1('CCC' + pre_master + self.client_random + self.server_random))))) print "Sent ClientKeyExchange" return client_key_exchange
def create_finished(self): client_finished = bytearray(10 * '\x00', 'hex') client_finished[0] = '\x04' client_finished[1:5] = util.int_to_binary(5, 4) client_finished[5:7] = self.session_id client_finished[7] = '\x00' client_finished[8:10] = '\xF0\xF0' print "Sent FinishedClient" return client_finished
def send_payload(self, payload): length = len(payload) if length > 4294967200: return # First 5 bytes not encrypted client_message = bytearray(5 * '\x00', 'hex') client_message[0] = '\x07' # Do encrypt the rest client_message_to_encrypt = bytearray((8 + length) * '\x00', 'hex') client_message_to_encrypt[0:2] = self.session_id client_message_to_encrypt[2:6] = util.int_to_binary(length, 4) client_message_to_encrypt[6:6 + length] = payload client_message_to_encrypt[6 + length:6 + length + 2] = '\xF0\xF0' client_message_encrypted = util.encrypt_message(client_message_to_encrypt, self.master_secret) # Get length of encrypted part, send concatenation of the two parts client_message[1:5] = util.int_to_binary(len(client_message_encrypted), 4) self.connection.send(client_message + client_message_encrypted) print "Sent payload from client"
def create_payload(self, payload, conn): length = len(payload) # Unencrypted length if length > 4294967200: return # First 5 bytes not encrypted server_message = bytearray(5 * '\x00', 'hex') server_message[0] = '\x07' # Do encrypt the rest server_message_to_encrypt = bytearray((8 + length) * '\x00', 'hex') server_message_to_encrypt[0:2] = self.session_ids[conn] server_message_to_encrypt[2:6] = util.int_to_binary(length, 4) server_message_to_encrypt[6:6 + length] = payload server_message_to_encrypt[6 + length:6 + length + 2] = '\xF0\xF0' server_message_encrypted = util.encrypt_message( server_message_to_encrypt, self.master_secrets[conn]) # Get length of encrypted part, send concatenation of the two parts server_message[1:5] = util.int_to_binary(len(server_message_encrypted), 4) print "Sent payload from server" return server_message + server_message_encrypted
def create_hello(self): client_hello = bytearray(43 * '\x00', 'hex') client_hello[0] = '\x01' client_hello[1:5] = util.int_to_binary(38, 4) client_hello[5] = '\x64' client_hello[6] = '\x65' # Generate client_random bytes for i in range(7, 39): self.client_random += chr(random.randint(0, 255)) client_hello[7:39] = util.text_to_binary(self.client_random) client_hello[39:41] = '\x00\x2F' client_hello[41:43] = '\xF0\xF0' print "Sent ClientHello" return client_hello
def send_error_setup(self, conn, error_code): error_message = bytearray(10 * '\x00', 'hex') error_message[0] = '\x06' error_message[1:5] = util.int_to_binary(5, 4) if self.session_id: error_message[5:7] = self.session_id else: error_message[5:7] = '\x00\x00' # session ID not yet generated, can't send it error_message[7] = error_code error_message[8:10] = '\xF0\xF0' print 'Sending error from client:', util.get_error_message(error_message[7]) conn.send(error_message) conn.close() return
def create_finished(self, conn): # First 5 bytes not encrypted server_finished = bytearray(5 * '\x00', 'hex') server_finished[0] = '\x05' # Do encrypt the rest server_finished_to_encrypt = bytearray(5 * '\x00', 'hex') server_finished_to_encrypt[0:2] = self.session_ids[conn] server_finished_to_encrypt[2] = '\x00' server_finished_to_encrypt[3:5] = '\xF0\xF0' server_finished_encrypted_part = util.encrypt_message( server_finished_to_encrypt, self.master_secrets[conn]) # Get length of encrypted part, send concatenation of the two parts server_finished[1:5] = util.int_to_binary( len(server_finished_encrypted_part), 4) server_finished.extend(server_finished_encrypted_part) print "Sent FinishedServer" return server_finished
def send_error_secure(self, conn, error_code): error_message = bytearray(10 * '\x00', 'hex') error_message[0] = '\x06' error_message[1:5] = util.int_to_binary(5, 4) if self.session_ids.get(conn): error_message[5:7] = self.session_ids[conn] else: error_message[ 5: 7] = '\x00\x00' # session ID not yet generated, can't send it error_message[7] = error_code error_message[8:10] = '\xF0\xF0' print 'Sending error from server:', util.get_error_message( error_message[7]), self.secure_error_count[conn] conn.send(error_message) self.secure_error_count[conn] += 1 if self.secure_error_count[conn] >= 10: conn.close() self.is_connected[conn] = False return
def process_key_exchange(self, message, conn): print "Received ClientKeyExchange" if len(message) < 1234: return '\x03' # Validate some bytes message_id = message[0] if not util.is_known_message_id(message_id): return '\x02' if not message[0] == ord('\x03'): return '\x01' if not message[5:7] == self.session_ids[conn]: return '\x04' # Parse and validate certificate client_cert = crypto.load_certificate( crypto.FILETYPE_PEM, util.binary_to_text(message[7:1210])) if client_cert.get_issuer( ).commonName != 'orion' or client_cert.has_expired(): return '\x08' # Extract pubkey from certificate self.client_pubkeys[conn] = Crypto.PublicKey.RSA.importKey( M2Crypto.X509.load_cert_string( message[7:1210]).get_pubkey().as_der()) # Extract and decrypt pre_master length = util.binary_to_int(message[1210:1212]) if len(message) != 1234 + length: return '\x03' pre_master = rsa.long_to_text( rsa.decrypt_rsa(util.binary_to_long(message[1212:1212 + length]), self.private_key.d, self.private_key.n), 48) # Validate login user_id = client_cert.get_subject().commonName if not self.accounts.get(user_id): # Don't know this user at all return '\x09' expected_hash = sha1.sha1( sha1.digestToString(self.accounts[user_id]) + self.server_randoms[conn]) if not message[1212 + length:1232 + length] == util.int_to_binary( expected_hash, 20): return '\x09' self.user_ids[conn] = user_id # Validate some bytes if not (message[1232 + length] == ord('\xF0') and message[1233 + length] == ord('\xF0')): return '\x06' # Now knows enough to calculate master secret server_random = self.server_randoms[conn] client_random = self.client_randoms[conn] master_secret = \ sha1.sha1( sha1.digestToString(sha1.sha1( pre_master + sha1.digestToString(sha1.sha1('A' + pre_master + client_random + server_random)))) + sha1.digestToString(sha1.sha1( pre_master + sha1.digestToString(sha1.sha1('BB' + pre_master + client_random + server_random)))) + sha1.digestToString(sha1.sha1( pre_master + sha1.digestToString(sha1.sha1('CCC' + pre_master + client_random + server_random))))) self.master_secrets[conn] = master_secret return None