加密和解密都是使用的同一个密钥。
非对称加密使用一对“私钥-公钥”,用私钥加密的内容只有对应公钥才能解开,反之亦然。非对称加密有以下特性:
常见的非对称加密有 RSA、ESA、ECC 等。缺点:
所谓信息摘要,其实就是某种HASH算法。将信息明文转化为固定长度的字符。摘要算法有以下特性:
基于以上特性,我们一般使用摘要算法来校验原始内容是否被篡改。常见的摘要算法有 MD5、SHA 等。
SSL证书根据验证级别,分为三种类型:
除了验证级别维度的不同,统一级别的证书,它又根据保护域名的数量需求,SSL 证书又分为:
细说 CA 和证书讲的比较详细。
数字签名就是用摘要算法(MD5、SHA等 )提取出源文件的摘要并用私钥进行加密后的内容。用于验证传输的内容是不是真实服务器发送的数据,发送的数据有没有被篡改过。
数字证书中包含了由某个受信任组织担保的用户或公司的相关信息,是为了解决“客户端”如何验证”服务端“提供的公钥是否是真的的问题。
数字证书里一般会包含公钥、公钥拥有者名称、CA 的数字签名、有效期、授权中心名称、证书序列号等信息。
CA是Certificate Authority的缩写,也叫“证书授权中心”。(专业的解释看“这里”),负责管理和签发证书的第三方机构
数字证书有两个作用:
答案就是数字签名(digital signature)。数字签名可以认为是一个证书的防伪标签,目前使用最广泛的 SHA-RSA 数字签名的制作和验证过程如下:
几点说明:
证书信任链机制
实际上,在HTTPS通信中,Server下发给Client的不仅仅是对端网站的证书,而是一个证书链。这个证书链是从网站证书开始,逐级往上,到根证书。每个证书都被下个证书的私钥签署,每个证书的 Issuer 就是下个证书的 Subject,root CA内置在浏览器中,是被浏览器所信任的。
参考:
大型网站的 HTTPS 实践(一)-- HTTPS 协议和原理
互联网安全之数字签名、数字证书与PKI系统
TLS 协议主要有五部分:应用数据层协议,握手协议,报警协议,加密消息确认协议,心跳协议。TLS 协议本身又是由 record 协议传输的,record 协议的格式如上图最右所示。
记录协议在客户机和服务器握手成功后使用,即客户机和服务器鉴别对方和确定安全信息交换使用的算法后,进入SSL记录协议,记录协议向SSL连接提供两个服务:
(1)保密性:使用握手协议定义的秘密密钥实现
(2)完整性:握手协议定义了MAC,用于保证消息完整性
为高层协议提供数据封装、压缩、加密等基本功能的支持。
它建立在SSL记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。
这一步,客户端主要向服务器提供以下信息:
(1) 支持的协议版本,比如TLS 1.0版。
(2) 一个客户端生成的随机数(Random1),稍后用于生成"对话密钥"(session key)。
(3) 支持的加密套件,比如RSA公钥加密。
(4) 支持的压缩方法。
(5) session ID (支持session的一般会有这个)
TLS 握手阶段需要9次请求,非常耗时。链接重用目前有两种方式
session ID 会话复用
对于已经建立的SSL会话,使用session id为key(session id来自第一次请求的server hello中的session id字段),主密钥为value组成一对键值,保存在本地,服务器和客户端都保存一份。
当第二次握手时,客户端若想使用会话复用,则发起的client hello中session id会置上对应的值,服务器收到这个client hello,解析session id,查找本地是否有该session id,如果有,判断当前的加密套件和上个会话的加密套件是否一致,一致则允许使用会话复用,于是自己的server hello 中session id也置上和client hello中一样的值。然后计算对称秘钥,解析后续的操作。
如果服务器未查到客户端的session id指定的会话(可能是会话已经老化),则会重新握手,session id要么重新计算(和client hello中session id不一样),要么置成0,这两个方式都会告诉客户端这次会话不进行会话复用。
– 来自 TLS/SSL 协议详解 (22)会话复用
Session ticket会话复用
Session id会话复用有2个缺点:
Session ticket的工作流程如下:
客户端发起client hello,拓展中带上空的session ticket TLS,表明自己支持session ticket。
服务器在握手过程中,如果支持session ticket,则发送New session ticket类型的握手报文,其中包含了能够恢复包括主密钥在内的会话信息,当然,最简单的就是只发送master key。为了让中间人不可见,这个session ticket部分会进行编码、加密等操作。
客户端收到这个session ticket,就把当前的master key和这个ticket组成一对键值保存起来。服务器无需保存任何会话信息,客户端也无需知道session ticket具体表示什么。
当客户端尝试会话复用时,会在client hello的拓展中加上session ticket,然后服务器收到session ticket,回去进行解密、解码能相关操作,来恢复会话信息。如果能够恢复会话信息,那么久提取会话信息的主密钥进行后续的操作。
两者的主要区别,就是加密的握手记录谁负责保存的问题。Session ID 是服务端保存握手记录,Session Ticket 是 客户端保存握手记录。
SeverHello包含以下内容:
(1) 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。
(2) 一个服务器生成的随机数(Random2),稍后用于生成"对话密钥"(session key)。
(3) 确认使用的加密方法,比如RSA公钥加密。
(4) session ID
Certificate
服务端将自己的证书下发给客户端,让客户端验证自己的身份,客户端验证通过后取出证书中的公钥。
Server Key Exchange
仅用于(服务器)证书消息没有包含足够的信息来建立预置密钥(pre-master key)的情况。如短暂的DH算法,这里发送服务器使用的DH参数。RSA算法不需要这一步。
Certificate Request
服务端要求客户端上报证书,这一步是可选的,需要双向认证时要用到。
Server Hello Done
Server Hello Done 通知客户端 Server Hello 过程结束。
客户端在接受到服务端发来的SSL证书时,会对证书的真伪进行校验,以浏览器为例说明如下:
(1)首先浏览器读取证书中的证书所有者、有效期等信息进行一一校验
(2)浏览器开始查找操作系统中已内置的受信任的证书发布机构CA,与服务器发来的证书中的颁发者CA比对,用于校验证书是否为合法机构颁发
(3)如果找不到,浏览器就会报错,说明服务器发来的证书是不可信任的。
(4)如果找到,那么浏览器就会从操作系统中取出 颁发者CA 的公钥,然后对服务器发来的证书里面的签名进行解密
(5)浏览器使用相同的hash算法计算出服务器发来的证书的hash值,将这个计算的hash值与证书中签名做对比
(6)对比结果一致,则证明服务器发来的证书合法,没有被冒充
(7)此时浏览器就可以读取证书中的公钥(服务端的公钥),用于后续加密了。
(8)客户端再生成一个随机数 Random3,又称"pre-master key"。有了它以后,客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把"会话密钥"。
至于为什么一定要用三个随机数,来生成"会话密钥",dog250解释得很好,总结来说就是为了增加随机性,不容易被暴力破解。SSL协议不信任每个主机都能生成完全随机的随机数。同时需要注意前两个随机数都是明文传输的,窃听者是可以轻易获取到的,只有最后一个 PreMaster Secret 是加密传输的,只有拥有服务器私钥才能解密,一旦 PreMaster Secret 泄露,那么本次通信就就完全可被破解了。
Client Key Exchange
上面客户端根据服务器传来的公钥生成了 pre-master Key,Client Key Exchange 就是将这个 key 传给服务端,服务端再用自己的私钥解出这个 PreMaster Key 得到客户端生成的 Random3。至此,客户端和服务端都拥有 Random1 + Random2 + Random3,两边再根据同样的算法就可以生成一份秘钥,握手结束后的应用层数据都是使用这个秘钥进行对称加密。
Change Cipher Spec
这一步是客户端通知服务端后面再发送的消息都会使用前面协商出来的秘钥加密了,是一条事件消息。
Change Cipher Spec 有必要么?
Change Cipher Spec 用来通知对端,开始启用协商好的密钥做对称加密,内容只有1个字节。 这个协议是冗余的,在TLS 1.3里面直接被删除了。
Encrypted Handshake Message
这一步对应的是 Client Finish 消息,客户端将前面的握手消息生成摘要再用协商好的秘钥加密,这是客户端发出的第一条加密消息。服务端接收后会用秘钥解密,能解出来说明前面协商出来的秘钥是一致的。
服务器收到客户端的第三个随机数pre-master key之后,计算生成本次会话所用的"会话密钥"。
Change Cipher Spec
这一步是服务端通知客户端后面再发送的消息都会使用加密,也是一条事件消息。
Encrypted Handshake Message
这一步对应的是 Server Finish 消息,服务端也会将握手过程的消息生成摘要再用秘钥加密,这是服务端发出的第一条加密消息。客户端接收后会用秘钥解密,能解出来说明协商的秘钥是一致的。
总结 SSL/TLS协议的基本过程是这样的:
(1) 客户端向服务器端索要并验证公钥。
(2) 双方协商生成"对话密钥"(session key)。(只有双方知道,一共需要三个随机数)
(3) 双方采用"对话密钥"进行加密通信。(不直接用公钥加密,因为公钥加密计算量太大,服务器的公钥和私钥只用于加密和解密对话密钥
(确切的来说是第三个随机数),无其他作用。) 关于随机数的介绍。
在SSL中会使用密钥交换算法交换密钥;使用密钥对数据进行加密;使用散列算法对数据的完整性进行验证,使用数字证书证明自己的身份。
不使用SSL/TLS的HTTP通信,就是不加密的通信。所有信息明文传播,带来了三大风险。
(1) 窃听风险(eavesdropping):通信使用明文,可能会被第三方可以获知通信内容。
(2) 篡改风险(tampering):无法证明报文完整性,第三方可以修改通信内容。
(3) 冒充风险(pretending):不验证通信方的身份,第三方可以冒充他人身份参与通信。
SSL/TLS协议是为了解决这三大风险而设计的,希望达到:
(1) 所有信息都是加密传播,第三方无法窃听。
(2) 具有校验机制,一旦被篡改,通信双方会立刻发现。
(3) 配备身份证书,防止身份被冒充。
golang 部署参考Go和HTTPS
用curl
模拟请求注意几点:
curl
模拟请求的时候,单向认证用-k
选项来跳过客户端对服务端证书的检测,即用curl -k https://localhost:8081
,否则要加上--cacert RootCA.crt
。双向认证时,除了跳过证书检查,还要加上客户端证书、私钥,证书编码需是pem格式。即curl -k --cert Client.pem --key Client.key https://localhost:8081
为什么客户端会通过抓包工具的验证?
抓包工具要成功抓取https的内容,首先需要在本地(客户端)安装抓包工具的根证书,这样,本地就认为抓包工具是合法的了(抓包工具的证书就能通过本地的验证)。
SSL/TLS 握手过程详解
基于OpenSSL自建CA和颁发SSL证书
HTTPS 温故知新(三) —— 直观感受 TLS 握手流程(上)比较详细的介绍
HTTPS 温故知新(四) —— 直观感受 TLS 握手流程(下)