SSL/TLS协议、使用opensll生成证书、python代码实现安全传输数据、wireshark抓包

一、SSL\TLS协议:

1.协议简介:

SSL/TLS协议是位于应用层和传输层(如TCP)之间的,它和具体的应用层协议无关,也就是说,任何应用层协议都可以使用SSL/TLS来获得安全通信的能力,如HTTP/FTP/SMTP等。

2.基本原理:

为解决以下问题:第三方监视、偷听、截获甚至篡改,更有甚者,正在和我们通信的对方有可能根本就是假冒的,比如钓鱼网站等。
SSL/TLS通过下面三个方面来为互联网通信提供安全保证。

2.1 机密性保证

SSL/TLS对要传输的数据进行加密,这样在互联网上传递的就是加密后的密文,即使被恶意的第三方监听,没有解密密钥,就无法解密密文的意思。这就是SSL/TLS的放偷听机制。

加密分为对称加密和非对称加密。

对称加密(AES/RC4/3DES)的优点是效率高,然而对称加密使用的加密解密秘钥是一样的,这意味着加密方(即发送方)必须把秘钥发送给接收方,显然,在传输秘钥的过程中,如果不加以保护,秘钥就会被泄露。

非对称加密(RSA/ECC)则克服了对称加密需要传输秘钥的弱点,但是非对称加密的效率很低,如果传输的数据量很大,那么使用非对称加密将是十分耗时的。

也就是说,无论是对称加密还是非对称加密,都不能很好地满足数据加密传输的要求,为此,SSL/TLS对这两种方法取长补短,综合应用。SSL/TLS利用非对称加密来交换秘钥信息秘钥信息并不是秘钥,而是生成秘钥时所需要用到的信息),由于秘钥信息的数据量很少,使用非对称加密还是可以接受的。而对于要传输的数据,SSL/TLS则使用对称加密,其秘钥由前面使用非对称加密传输得到的秘钥信息生成。由于秘钥信息是使用非对称加密的,所以其在传输过程中是安全的(恶意的第三方没有私钥无法进行解密)。

2.2 消息完整性保证

由于恶意的第三方能够截获传输中的数据并把数据篡改后再发给接收方,所以SSL/TLS还必须提供一种方法来检测数据是否被篡改过。这也称为SSL/TLS的防篡改机制。具体地说,SSL/TLS使用**MAC(消息验证码)**来实现防篡改,即在发送消息之前,把该消息和一个通信双方共享的秘钥作为一个hash算法(MD5/SHA1)的输入,再把由此求得的摘要值联通消息一起发送给对方

2.3 身份验证

SSL/TLS通过验证身份来确保不会和假冒的对方通信。这也称为SSL/TLS的防假冒机制。SSL/TLS使用由私钥签名的数字证书来实现防假冒。一般来说,服务器需要把它的数字证书传给客户端来验证。

3.SSL\TLS握手:

在开始传输应用程序数据之前,通信的双方必须先进行SSL/TLS握手。在握手的过程,双方交换并协商重要的信息,包括将要使用的SSL/TLS协议版本、加密算法、MAC算法、验证算法,以及用于各种算法的秘钥等。当然,任一方都可以在握手的过程中来验证对方的真伪,一旦验证失败,握手过程将被终止,同时这个SSL/TLS连接也会被终止。具体说,SSL/TLS的握手过程可以分为三个阶段:参数协商、身份验证,以及秘钥交换。

3.1 参数协商

在这个阶段,客户端和服务器确定一个双方都能支持的最高版本的SSL/TLS协议,同时确定它们所使用的算法组合(Cipher Suite)。算法组合是分别用于不同目的的三个算法的组合,包含用于交换秘钥(Key Exchange)和身份验证的算法,用于加密应用程序数据的对称加密算法,以及用于消息验证的MAC算法。在SSL/TLS中,一个算法组合可以用一个字符串来表示,如“TLS_RSA_WHIT_RC4_128_MD5”,这个算法组合表示使用RSA来交换秘钥和验证身份,使用RC4来加密应用程序数据,以及使用MD5来验证消息内容(即防篡改)。另外,在这个阶段中,客户端和服务器会分别产生一个随机数,然后把其传给对方,它们将会在后面的秘钥交换阶段中用到。

3.2 身份验证

如果在参数协商阶段时所确定的算法组合要求进行身份验证(如RSA),则服务器需要提供信息(服务器证书)来让客户端对齐进行身份验证。反过来,服务器也可以要求客户端提供证书,以便服务器也能够验证客户端的身份,不过这并不是必须的。是否需要验证客户端主要是根据应用程序的要求。

3.3 密钥交换

在身份验证通过以后,就可以进入密钥交换阶段。注意,在这个阶段,客户端和服务器并不是直接交换秘钥,而是交换生成秘钥所需要用的信息,这个信息被称为Pre-Master Secret,其实就是一个有客户端产生的随机数。如果在参数协商阶段时所确定的算法组合指明使用RSA来交换秘钥,那么客户端将使用服务器的公钥(包含在服务器的数字证书中)来加密这个Pre-Master Secret,然后再传给服务器,由于只有服务器才有私钥来进行解密,所以Pre-Master Secret的传输是安全的。有了Pre-Master Secret之后,客户端和服务器还需要再计算一个Master Secret,这是因为最终的秘钥都是基于Master Secret而生成的Master Secret本身则是通过对三个随机数进行计算而得到的,除了Pre-Master Secret之外,另外两个随机数则是在参数协商阶段交换的客户端随机数和服务器随机数。

最终生成的秘钥一共有4个,分别是:
  • 客户端MAC写入秘钥。客户端使用这个秘钥来计算将要发送的消息的摘要,服务器使用该秘钥来验证客户端发过了的消息,也即实现防篡改。
  • 服务器MAC写入秘钥。服务器使用这个秘钥来计算将要发送的消息的摘要,客户端使用该秘钥来验证服务器发过来的消息。
  • 客户端写入秘钥。客户端使用这个秘钥来加密将要发送的应用程序数据,服务器使用它来对收到的密文进行解密。
  • 服务器写入秘钥。服务器使用这个秘钥来加密将要发送的应用程序数据,客户端使用它来对收到的密文进行解密。
4.握手阶段示意图:

握手阶段分为五个步骤:
step1:客户端发送client hello包,包含给出协议版本号、一个客户端生成的随机数(Client random),以及客户端支持的加密方法。
step2:服务器发送server hello包,包含双方使用的加密方法,并给出数字证书(含有服务器的公钥)、以及一个服务器生成的随机数(Server random)。(服务器身份验证)
step3:客户端确认数字证书有效,然后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给服务器。(这一阶段既包含客户端身份验证,又包括密钥交换)
step4:服务器使用自己的私钥,获取客户端发来的随机数(即Premaster secret)。
step5:服务器根据协商的加密算法,使用前面的三个随机数,生成"对话密钥"(session key),用来加密接下来的整个对话过程。

在这里插入图片描述
握手阶段有三点需要注意。

(1)生成对话密钥一共需要三个随机数。

(2)握手之后的对话使用"对话密钥"加密(对称加密),服务器的公钥和私钥只用于加密和解密"对话密钥"(非对称加密),无其他作用。

(3)服务器公钥放在服务器的数字证书之中。

二、使用openssl生成自签名证书

1.制作CA

在这里插入图片描述
以上包含三个步骤:

  • 生成CA证书私钥 ca.eky
  • 生成CA证书请求文件 ca.csr (这一步可能会出错,退出后重复这一步)
  • 自验证并生成ca.crt (ca证书)
    注意:Common Name是申请证书的域名
    申请数字证书之前,必须先生成证书私钥证书请求文件(CSR,Cerificate Signing Request),CSR是您的公钥证书原始文件,包含了服务器信息和单位信息,需要提交给CA认证中心。
2.签发服务器证书:

在这里插入图片描述
同样包含三个步骤:

  • 生成server证书私钥 server.eky
  • 生成server证书请求文件 server.csr
  • ca验证并生成server.crt (server证书)
    注意:生成server.csr时,Common Name为服务器的域名地址。
3.签发客户端证书:

在这里插入图片描述
依旧包含三个步骤:

  • 生成client证书私钥 client.eky
  • 生成client证书请求文件 client.csr
  • ca验证并生成client.crt (server证书)

注意:我这里客户端服务器都在同一台机器上,采用localhost不同端口通信模拟,所以Common Name任为local host

三、代码实现

1. server端

import socket
import ssl

class server_ssl:
    def build_listen(self):
        # 生成SSL上下文
        context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
        # 加载服务器所用证书和私钥
        context.load_cert_chain('cert1/server.crt', 'cert1/server.key')

        # 监听端口
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock:
            sock.bind(('127.0.0.1',11443))
            sock.listen(5)
            # 将socket打包成SSL socket
            with context.wrap_socket(sock, server_side=True) as ssock:
                while True:
                    # 接收客户端连接
                    client_socket, addr = ssock.accept()
                    # 接收客户端信息
                    msg = client_socket.recv(1024).decode("utf-8")
                    print(f"receive msg from client {addr}:{msg}")
                    # 向客户端发送信息
                    msg = f"yes , you have client_socketect with server.\r\n".encode("utf-8")
                    client_socket.send(msg)
                    client_socket.close()

if __name__ == "__main__":
    server = server_ssl()
    server.build_listen()
2.client端

import socket
import ssl


class client_ssl:
    def send_hello(self,):
        # 生成SSL上下文
        context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
        # 加载信任根证书
        context.load_verify_locations('cert1/ca.crt')

        # 与服务端建立socket连接
        with socket.create_connection(('127.0.0.1', 11443)) as sock:
            # 将socket打包成SSL socket
            # 一定要注意的是这里的server_hostname不是指服务端IP,而是指服务端证书中设置的CN,我这里正好设置成127.0.1而已
            with context.wrap_socket(sock, server_hostname='localhost') as ssock:
                # 向服务端发送信息
                msg = "do i connect with server ?".encode("utf-8")
                ssock.send(msg)
                # 接收服务端返回的信息
                msg = ssock.recv(1024).decode("utf-8")
                print(f"receive msg from server : {msg}")
                ssock.close()

if __name__ == "__main__":
    client = client_ssl()
    client.send_hello()

四、wireshark抓包

握手阶段数据包如下:

在这里插入图片描述
1.client hello server random
2. server hello server certificate client random
3. client certificate pre master secert
4. generate session key
5. data transmation

1.client hello server random

在这里插入图片描述

2. server hello server certificate client random

在这里插入图片描述
在这里插入图片描述

3. client certificate pre master secert

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.generate session key

在这里插入图片描述

5. data transmation

在这里插入图片描述
发送的数据已经被加密。

参考:
https://blog.csdn.net/coderaldrich/article/details/78524017
https://blog.csdn.net/fw0124/article/details/40875629

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值