使用传输层安全协议TLS/SSL实现信息加密传输

一、问题描述:

TCP协议是明文传输的,并不对信息进行加密,很容易被窃听和还原。所以重要信息不适合使用TCP直接传输,需要进行加密传输,具体的实现有很多种,其中一种是安全套接字SSL(传输层安全协议TLS)。本文中我们先使用标准的TCP协议进行通信,然后改用TLS协议进行通信,并对通信过程进行抓包来比较两种协议的不同。

二、实验步骤:
  1. 编写代码实现TCP套接字,模拟服务端和客户端通信。

    服务端代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import socket
    from time import sleep

    MAX_BYTES = 4096

    with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as sock:
    sock.bind(('127.0.0.1',6666))
    sock.listen(1)
    conn,addr = sock.accept()
    data = conn.recv(MAX_BYTES)
    print(data)
    sleep(5)
    conn.sendall(b'received')
    conn.close()

    客户端代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import socket

    MAX_BYTES = 4096

    with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as sock:
    sock.connect(('127.0.0.1',6666))
    sock.sendall(b'hello')
    data = sock.recv(MAX_BYTES)
    print(data)
  1. 使用管理员身份启动wireshark,选择本地回环地址,如图:

  2. 设置抓包规则,只关心TCP协议且端口号为6666的数据,开始抓包,如图:

  3. 运行前面编写的TCP通信服务端和客户端程序,然后切换到wireshark窗口,查看抓到的信息,除了通信双方的握手信息,还有互相发送的明文信息,如图:

  4. 安装Win64OpenSSL,用来生成安全证书,安装后把安装路径以及bin文件夹添加到系统的环境变量Path中(如果不添加Path变量的话需要在安装路径中执行下面的命令),然后打开cmd命令提示符,执行下面的命令生成安全证书:

    生成的文件如下:

  5. 编写代码,使用TLS/SSL实现安全套接字通信。

    服务端代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import socket
    import ssl

    #创建默认上下文
    cxt = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    cxt.load_default_certs(ssl.Purpose.CLIENT_AUTH)
    #加载证书
    cxt.load_cert_chain(certfile='dengjiawei.cer',keyfile='dengjiawei.key')
    server_address = ('127.0.0.1',6666)
    with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as sock:
    #绑定本地地址
    sock.bind(server_address)
    #开始监听
    sock.listen(1)
    #创建安全套接字,接受连接后返回的所有套接字都是安全的
    with cxt.wrap_socket(sock,server_side=True) as ssock:
    while True:
    conn,addr = ssock.accept()
    print(f'本地服务端地址:{ssock.getsockname()}')
    print(f'客户端地址:{addr}')
    print(conn.recv(1024).decode())
    conn.send(b'received')
    conn.close()

    客户端代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import socket
    import ssl

    server_address = ('127.0.0.1',6666)
    #不验证服务器证书
    cxt = ssl._create_unverified_context()

    with socket.socket() as sock:
    with cxt.wrap_socket(sock,server_hostname=server_address[0]) as ssock:
    ssock.connect(server_address)
    print(f'本地地址:{ssock.getsockname()}')
    ssock.send('hello'.encode())
    print(ssock.recv(1024).decode())
    ssock.close()
三、实验结果:

切换到wireshark窗口,重新开始抓包,然后运行上面的安全套接字程序,回到wireshark窗口查看抓到的信息,可以看到,服务端和客户端之间的信息全部被加密了,抓不到明文。