前言
https是基于SSL/TLS的http协议,能够保证数据传输的安全性,避免如http报文传输过程中数据被劫持篡改的风险。
本文基于python2的ssl库以及httplib库模拟https客户端以及服务端进行通信。
SSL/TLS认证模式
- 双向认证:客户端与服务端互相认证,两者之间将会交换证书;
- 单向认证:客户端会认证服务器身份,而服务器不会对客户端身份进行验证
SSL/TLS握手过程
Client | Server |
1.Client Hello | |
2.Server Hello 3.Certificate 4.(Server_Key_Exchange) 5.(Certificate_Request) 6.Server_Hello_Done |
|
7.(Certificate) 8.Client_Key_Exchange 9.(Certificate_Verify) 10.Change_Cypher_Spec ----finished---- |
|
11.Change_Cypher_Spec ----finished---- |
1.Client Hello:
(1)支持的协议版本,比如TLS 1.0
(2)支持的加密算法(Cipher Specs)
(3)客户端生成的随机数1(Challenge),稍后用于生成"对话密钥"。
2.Server Hello
(1) 确认使用的协议版本
(2) 服务器生成的随机数2,稍后用于生成"对话密钥"
(3) session id
(4) 确认使用的加密算法
3.Certificate
服务器证书
4.(Server_Key_Exchange)
如果是DH算法,这里发送服务器使用的DH参数。RSA算法不需要这一步。
5.(Certificate_Request)
要求客户端提供证书,包括
(1) 客户端可以提供的证书类型
(2)服务器接受的证书distinguished name列表,可以是root CA或者subordinate CA。如果服务器配置了trust keystore, 这里会列出所有在trust keystore中的证书的distinguished name。
6.Server_Hello_Done
server hello结束
7.(Certificate)
客户端证书
8.Client_Key_Exchange
包含pre-master secret。客户端生成第三个随机数。如果是采用RSA算法,会生成一个48字节随机数,然后用server的公钥加密之后再放入报文中;如果是DH算法,这里发送的就是客户端的DH参数,之后服务器和客户端根据DH算法,各自计算出相同的pre-master secret。
9.(Certificate_Verify)
发送使用客户端证书给到这一步为止收到和发送的所有握手消息签名结果。
10.Change_Cypher_Spec
客户端通知服务器开始使用加密方式发送报文。客户端使用上面的3个随机数client random, server random, pre-master secret, 计算出48字节的master secret, 这个就是对称加密算法的密钥。
finished
客户端发送第一个加密报文。使用HMAC算法计算收到和发送的所有握手消息的摘要,然后通过RFC5246中定义的一个伪函数PRF计算出结果,加密后发送。
11.Change_Cypher_Spec
----finished----
服务器端发送change_cipher_spec和finished消息。到这里握手结束
HTTPS客户端
1 import httplib 2 import ssl 3 import socket 4 5 def start_client(ip_addr): 6 print("启动https客户端......") 7 ssl._create_default_https_context = ssl._create_unverified_context;#重要,忽略证书认证 8 conn = httplib.HTTPSConnection(ip_addr) 9 print(str(conn.host) + str(conn.port)) 10 sock = socket.create_connection((conn.host, conn.port)) 11 conn.sock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_SSLv23)#忽略服务器证书认证 12 print '