HTTPS握手的过程是什么?

  • Post category:云计算

当客户端想要和服务器建立HTTPS连接时,会进行HTTPS的握手协商,协商完成后才能建立安全的连接。

HTTPS握手过程可以分为以下几步:

  1. 客户端向服务器发送一个含hello消息的数据包,其中包含了客户端支持的SSL/TLS协议版本、加密算法、随机数等信息。
```python
# 示例代码:客户端发送hello消息
import socket
import ssl

context = ssl.create_default_context()
with socket.create_connection(('example.com', 443)) as sock:
    with context.wrap_socket(sock, server_hostname='example.com') as ssock:
        hello_msg = b"hello server"
        ssock.sendall(hello_msg)
  1. 服务器收到客户端发送的hello消息后,会回应一个含hello消息的数据包,其中包含了服务器支持的SSL/TLS协议版本、加密算法、随机数等信息。
```python
# 示例代码:服务器回应hello消息
import socket
import ssl

context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
    sock.bind(('example.com', 443))
    sock.listen()
    with context.wrap_socket(sock, server_side=True) as ssock:
        conn, addr = ssock.accept()
        print(f"Connection from {addr}")
        hello_msg = conn.recv(1024)  # 接收客户端hello消息
        print(f"Received message from client: {hello_msg}")

        # 发送服务器hello消息
        server_hello_msg = b"hello client"
        conn.sendall(server_hello_msg)
  1. 客户端收到服务器发送的hello消息后,会验证服务器的证书。如果证书验证成功,则会生成一个随机数,使用服务器发送的加密算法和密钥,对该随机数进行加密,并将加密后的随机数发送给服务器。
```python
# 示例代码:客户端验证服务器证书并加密随机数
import socket
import ssl

context = ssl.create_default_context()
with socket.create_connection(('example.com', 443)) as sock:
    with context.wrap_socket(sock, server_hostname='example.com') as ssock:
        # 发送hello消息后,验证服务器证书
        hello_msg = b"hello server"
        ssock.sendall(hello_msg)  # 发送hello消息
        ssock.do_handshake()  # 进行握手协商
        cert = ssock.getpeercert()  # 获取服务器端证书信息
        print(f"Received cert: {cert}")

        # 生成并加密随机数
        random_num = b"123456"
        key = ssock.get_cipher_shared_key()
        iv = ssock.get_iv()
        print(f"Cipher key: {key}, iv: {iv}")
        cipher = ssl.Cipher('AES256-SHA256')
        encrypted_random_num = iv + cipher.encrypt(key, random_num)  # 加密随机数
        ssock.sendall(encrypted_random_num)  # 发送加密后的随机数
  1. 服务器接收到客户端发送的加密后的随机数,使用自己的私钥和加密算法进行解密,得到客户端的随机数。同时,服务器也会生成一个随机数,使用客户端发送的加密算法和密钥,将该随机数加密后发送给客户端。
```python
# 示例代码:服务器解密客户端随机数并加密自己的随机数
import socket
import ssl

context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
    sock.bind(('example.com', 443))
    sock.listen()
    with context.wrap_socket(sock, server_side=True) as ssock:
        conn, addr = ssock.accept()
        print(f"Connection from {addr}")
        hello_msg = conn.recv(1024)  # 接收客户端hello消息
        print(f"Received message from client: {hello_msg}")

        # 发送服务器hello消息后,接收客户端加密的随机数
        server_hello_msg = b"hello client"
        conn.sendall(server_hello_msg)  # 发送hello消息
        client_encrypted_random_num = conn.recv(1024)  # 接收客户端加密的随机数
        print(f"Received client encrypted random number: {client_encrypted_random_num}")

        # 解密客户端随机数,并加密服务器随机数
        cipher = ssl.Cipher('AES256-SHA256')
        iv = client_encrypted_random_num[:16]
        key = ssock.get_cipher_shared_key()
        print(f"Cipher key: {key}, iv: {iv}")
        client_random_num = cipher.decrypt(key, client_encrypted_random_num[16:]).decode()
        print(f"Decrypted client random number: {client_random_num}")
        server_random_num = b"654321"
        encrypted_server_random_num = iv + cipher.encrypt(key, server_random_num)  # 加密服务器随机数
        conn.sendall(encrypted_server_random_num)  # 发送加密后的服务器随机数
  1. 客户端接收到服务器发送的加密后的随机数,使用客户端发送的加密算法和密钥进行解密,得到服务器的随机数。
```python
# 示例代码:客户端解密服务器随机数
import socket
import ssl

context = ssl.create_default_context()
with socket.create_connection(('example.com', 443)) as sock:
    with context.wrap_socket(sock, server_hostname='example.com') as ssock:
        # 发送hello消息后,验证服务器证书并加密随机数,接收解密服务器随机数
        hello_msg = b"hello server"
        ssock.sendall(hello_msg)  # 发送hello消息
        ssock.do_handshake()  # 进行握手协商
        cert = ssock.getpeercert()  # 获取服务器端证书信息
        print(f"Received cert: {cert}")

        random_num = b"123456"
        key = ssock.get_cipher_shared_key()
        iv = ssock.get_iv()
        print(f"Cipher key: {key}, iv: {iv}")
        cipher = ssl.Cipher('AES256-SHA256')
        encrypted_random_num = iv + cipher.encrypt(key, random_num)  # 加密随机数
        ssock.sendall(encrypted_random_num)  # 发送加密后的随机数

        # 接收解密服务器随机数
        server_encrypted_random_num = ssock.recv(1024)
        server_iv = server_encrypted_random_num[:16]
        server_random_num = cipher.decrypt(key, server_encrypted_random_num[16:]).decode()
        print(f"Decrypted server random number: {server_random_num}")
  1. 握手协商完成后,客户端和服务器就可以使用协商的加密算法和密钥,对后续的通信进行加密和解密。

HTTPS握手协商的过程中,客户端和服务器需要相互验证对方的身份,并协商出一种加密算法和密钥,用于对后续的通信进行加密和解密。握手协商完成后,双方就可以建立安全的连接,保证通信的安全性和保密性。