Handshake ( Server Hello )

Do I need to send a ( Server Hello ) as a response to the handshake ( Client Hello ) received, but I couldn’t find out why it doesn’t work? If I can help, below is an example:

import socket
import ssl

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Bind the socket to port 443
sock.bind(("localhost", 443))

# Listen for connections
sock.listen(1)

# Accept a connection
conn, addr = sock.accept()

# Create a SSL/TLS context
ctx = ssl.SSLContext()

# Load the server's certificate
ctx.load_cert_chain("server.crt")

# Create a SSL/TLS wrapper around the socket
ssl_sock = ctx.wrap_socket(conn)

# Receive the "ClientHello" message
client_hello = ssl_sock.recv(16384)

# Select the highest version of SSL/TLS common between the client and the server
ssl_version = client_hello[0:2]

# Select a set of encryption algorithms and security parameters supported by both the client and the server
ciphers = ssl.get_ciphers()

# Send the "ServerHello" message to the client
ssl_sock.sendall(b"ServerHello\n" + ssl_version + b"\n" + ciphers + b"\n")

# Receive the "ClientKeyExchange" message from the client
client_key_exchange = ssl_sock.recv(16384)

# Generate a shared secret
shared_secret = ssl.generate_shared_secret(client_key_exchange)

# Encrypt the data stream
ssl_sock.write(shared_secret)

# Receive data from the client
data = ssl_sock.read()

# Decrypt the data
decrypted_data = ssl.decrypt_data(data, shared_secret)

# Print the decrypted data
print(decrypted_data)

# Close the socket
ssl_sock.close()

The TLS exchange is handled by the ssl socket, your code will not see the TLS messages.
If you want to configure the exchange then you set stuff up in the ctx.

See the docs for how to do this ssl — TLS/SSL wrapper for socket objects — Python 3.11.3 documentation
like the ssl_version arg of wrap_socket().

I made some modifications to the above code and the handshake ( server hello ) works but the secure connection is not being established ( the certificate was signed and the private key is correct ), below is the refactored code :

import socket
import multiprocessing
import ssl


def connect_tls(conex_tcp):

    # Create a SSL/TLS context
    ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
        # Load the server's certificate and private key
    ctx.load_cert_chain(certfile="/etc/ssl/certs/kosmics.tech.crt", keyfile="/etc/ssl/private/private.key")
    # Create a SSL/TLS wrapper around the socket
    socket_tls = ctx.wrap_socket(conex_tcp, server_side=True)
    # Close the Connection TLS
    conex_tcp.close()

    # Receive the "ClientHello" message
    client_hello = socket_tls.recv(16384)
    # Select the highest version of SSL/TLS common between the client and the server
    version = client_hello[:2]
    # Select a set of encryption algorithms and security parameters supported by both the client and the server
    cipher_suites = socket_tls.cipher()

    # Send the "Server Hello" message to the client
    socket_tls.sendall(b"Server Hello\n" + version + b"\n" + cipher_suites + b"\n")

    # Receive the "ClientKeyExchange" message from the client
    client_key_exchange = socket_tls.recv(16384)

    # Generate a shared secret
    shared_secret = socket_tls.shared_ciphers()
    
    # Encrypt the data stream
    socket_tls.write(shared_secret)
    
    # Receive data from the client
    data = socket_tls.read()

    # Decrypt the data
    decrypted_data = socket_tls.decrypt(data)

    # Close the Socket TLS
    socket_tls.close()
    
def connect_tcp():

    # Create a socket and bind it to port 443
    socket_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # Define o endereço e a porta em que o servidor vai ouvir
    address_https = ('', 443)
    # Liga o socket ao endereço e porta
    socket_tcp.bind(address_https)
    # Ouça conexões de clientes
    socket_tcp.listen()
        
    while True:

        # Aceite uma conexão do cliente
        conex_tcp, client_addr = socket_tcp.accept()
        # Cria processos para lidar com requisição simultaneo
        process = multiprocessing.Process(target=connect_tls, args=(conex_tcp,))
        process.start()

if __name__ == '__main__':

    connect_tcp()

This does not get the TLS client hello.
That is done by the code that wraps the socket.

You have the protocol stack of:

TCP
TLS
Application data

After the call to wrap_socket all you can read and write is “Application data”.
Your reads and writes will be the HTTP data not anything TLS related.

To do TLS Negotiation you must setup the ctx object BEFORE you call wrap_socket.

Given you are using port 443 I assume that you are trying to implement a
web server for HTTPS. For example I would expect something like
`GET / HTTP/1.1\r\n’ to be in client_hello with your code.

Since your reply is not valid HTTP I would expect a web browser or HTTPS aware app to just error out and close the connection.