写在前面
工作中总是会接触到https协议,也知道其使用了ssl,tls协议。但对其细节并不是十分的清楚。所以,就希望通过这篇文章让自己和读者朋友们都能对这方面知识有更清晰的理解。
1:tls/ssl协议的工作原理
1.1:设计的目的
网络是不安全的,因此一些敏感的信息,比如我们的银行账号密码,比如引爆原子弹的账号信息等。当以明文形式在网络上传输时不可避免的会被坏人看到,被坏人修改,等等,所以为了解决这些问题,就需要一种解决这种问题的方案,也就是一种安全相关的协议,也就是本文要分析的tls/ssl了。具体的解决了如下的问题们:
- 身份验证
证明你就是你
。 - 保密性
就算是坏人拿到了数据,也无法知道其具体内容是什么。 - 完整性
坏人拿到数据后,恶意修改了数据,我们能够知道数据已经被恶意篡改了。
1.2:协议组成
主要由两个自协议组成:
record 记录协议:对称加密
handshake 握手协议:验证身份协商密钥协商加密参数
自然,所有设计都是为了满足设计目的。
1.3:需要用到的知识点
为了解决数据加密的问题,需要用到对称加密算法
,而为了传递对称加密算法的密钥,需要用到非对称加密算法
,而为了进行身份验证,需要用到证书
,CA
等内容。所以后续我们就以这些知识点作为切入点来进行分析。
2:知识点们
2.1:对称加密
加密密钥和解密密钥相同的加解密算法。
2.1.1:对称加密的原理
XOR异或运算,其真值表(truth table)表如下:
通过连续两次的异或运算就可以将数据恢复到初始状态,并且异或运算本身是操作系统底层支持的,速度也很快,所以用在对称加密的场景中是非常合适的。连续两次异或过程如下:
数据:1101
密钥:0101
第1次异或运算:1101 XOR 0101 = 1000
第2次异或运算:1000 XOR 0101 = 1101 可以看到恢复到了最初值
2.1.2:填充padding
当通过异或运算对数据进行加密时,要求进行异或运算时的数据和密钥长度相同,因为长度不相同时时无法进行异或运算的,所以就需要通过增加数据长度的方式来满足要求,这个过程就叫做填充padding。比如如下的数据:
数据:11111111 11111111 11111111
密钥:11111111 11111111
数据的第1,2字节可以作为一组来和密钥做异或运算,但是之后数据只剩下1个字节,所以就需要再额外的填充一个字节的数据。
填充的方式目前有两种,第一种是按照位填充,如下:
第二种是按照字节填充。因为按位填充的方式使用的不多,所以重点来看第二种按照字节方式填充。
按照字节填充的一种方式是直接补0,如下:
第二种方式是ANSI X9.23
规范的,前面补0,最后一个字节为补零的个数,如下:
第三种方式是ISO 10126
规范的,前面的字节补随机字符,最后一个字符为补的随机字符的个数,如下:
第四种方式是PKCS7 (RFC5652
,每个字节都是填充的字节的个数,如下:
2.1.3:工作模式
我们已经知道,对称加密的原理是xor异或运算,但是异或运算需要将原有数据分成很多的段来依次进行,那么具体如何进行就是本部分要分析的工作模式了。通过工作模式可以完成对原有数据的异或运算,生成加密数据。
接着来看下都有哪些工作模式。
- ECB模式
直接将数据分成多块,依次加密。如下:
这种加密的方式的缺点是会保留大量原有数据的特征,更容易被破解。
为了解决这个容易被破解的问题,此时我们可以考虑ACB模式。 - ACB模式
这种模式的后一个异或操作需要依赖于前一个数据块异或的结果,如下图:
这种方式的问题是串行化,效率低。 - CTR
分块并行加密,如下:
缺点是无法进行消息的完整性校验。为了解决消息完整性校验,需要用到MAC(message authentication code),要用到hash函数来生成一个定长的hash值。主要过程是将消息和消息的哈希值都传到对端,对端同样对消息做哈希,对比收到的哈希,如果一致则消息完整,否则消息不完整(被篡改或丢失数据),如下图:
结合MAC完成消息完整性的校验,我们就有了最后一种工作模式。 - GCM
GCM=CTR+MAC,如下图:
2.1.4:AES加密算法
TLS1.2,TLS1.3协议中使用的就是AES加密算法来对数据进行加密的,AES主要工作方式如下:
填充算法:PKCS7
分组模式:GCM,分组的长度是固定的16个字节
有了对称加密,数据的安全性就得到了保障,但是密钥要怎么传输到对端呢?这就需要用到非对称加密算法了。接着来看这部分内容。
2.2:非对称加密
非对称加密就是加密和解密的密钥不同,其中一般使用私钥加密,公钥解密,私钥自己保存,公钥对外暴漏。加解密过程参考下图:
非对称加密中最经典的加密算法是rsa算法,公钥私钥产生过程如下:
其实就是进行了一些复杂的数学运算得到一个结果,比如其中的p,q,n等都是计算过程中需要用到的参数。后续我们通过openssl实战密钥生成时也可以来具体的看到这些值。
加密解密过程如下:
相比于对称加密的异或运算,非对称加解密的数学运算更加复杂,所以就加解密速度来讲的话对称机密是更快的,所以,工作中如果没有特殊的需求建议使用对称机密,这样对系统性能的影响更小。
2.2.1:openssl实战rsa
为了验证rsa加密算法,也为了了解其加解密用到的各种参数值,有必要来来通过openssl具体看下。
- 生成私钥
D:\test\ssl>openssl genrsa -out private.pemD:\test\ssl>type private.pem
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD1V1uc4WVV6Dp9
...
sNqRTYuws/DLlhAH4Ess9xw0FyquwoEkukgvsy/T8ndzcnXO7wX9RuaHHHL4t0DR
Mbwq/x1LymV0ZqYWFHtcTSNR
-----END PRIVATE KEY-----
- 通过私钥导出公钥
因为要解密,所以要用到加密时的某些参数值,而这些参数值需要通过私钥获取,所以需要通过私钥导出公钥:
D:\test\ssl>openssl rsa -in private.pem -pubout -out public.pem
writing RSA keyD:\test\ssl>type public.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9VdbnOFlVeg6fXdXjXmX
gCJtxcXU6k98oswyKxcrylZ7enTe/8EGLSaUpHD1psVQRBGUppWvFHdDO2ZzBacS
LCOKpZjUHNwJyxent6e97ZnPQwTMF8OtTq9OjXFirMppoAhpnVFJaF+IyCzYrtPU
bbtnwlf+l25kxce0FXkECg9I3sO0vIzs4Hglh5X+dwsXyLRoQ5zN+o35MYWPqyYQ
Z2hPpejStNZvXUGUPA64SsD39jCNQVlrKo9lnR1CToeZx32cBuAUZhVK6CGV9q6d
KjHzLvupIf6C0SmdUsihPpfKD8H3+WAqbXw7oFKpSd05o/yZOUyU3rifObnxUGEt
mwIDAQAB
-----END PUBLIC KEY-----
- 查看 ASN.1 格式的私钥
D:\test\ssl>openssl asn1parse -i -in private.pem0:d=0 hl=4 l=1214 cons: SEQUENCE4:d=1 hl=2 l= 1 prim: INTEGER :007:d=1 hl=2 l= 13 cons: SEQUENCE9:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption20:d=2 hl=2 l= 0 prim: NULL22:d=1 hl=4 l=1192 prim: OCTET STRING [HEX DUMP]:308204A40201000282010100F5575B9CE16555E83A7D77578D799780226DC5C5D4EA4F7CA2CC322B172BCA567B7A74DEFFC1062D2694A470F5A6C550441194A695AF1477433B667305A7122C238AA598D41CDC09CB17A7B7A7BDED99CF4304CC17C3AD4EA...CEEF05FD46E6871C72F8B740D131BC2AFF1D4BCA657466A616147B5C4D2351
- 查看 ASN.1 格式的公钥
D:\test\ssl>openssl asn1parse -i -in public.pem0:d=0 hl=4 l= 290 cons: SEQUENCE4:d=1 hl=2 l= 13 cons: SEQUENCE6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption17:d=2 hl=2 l= 0 prim: NULL19:d=1 hl=4 l= 271 prim: BIT STRINGD:\test\ssl>openssl asn1parse -i -in public.pem -strparse 190:d=0 hl=4 l= 266 cons: SEQUENCE4:d=1 hl=4 l= 257 prim: INTEGER :F5575B9CE16555E83A7D77578D799780226DC5C5D4EA4F7CA2CC322B172BCA567B7A74DEFFC1062D2694A470F5A6C550441194A695AF1477433B667305A7122C238AA598D41CDC09CB17A7B7A7BDED99CF4304CC17C3AD4EAF4E8D7162ACCA69A008699D5149685F88C82CD8AED3D46DBB67C257FE976E64C5C7B41579040A0F48DEC3B4BC8CECE078258795FE770B17C8B468439CCDFA8DF931858FAB261067684FA5E8D2B4D66F5D41943C0EB84AC0F7F6308D41596B2A8F659D1D424E8799C77D9C06E01466154AE82195F6AE9D2A31F32EFBA921FE82D1299D52C8A13E97CA0FC1F7F9602A6D7C3BA052A949DD39A3FC99394C94DEB89F39B9F150612D9B265:d=1 hl=2 l= 3 prim: INTEGER :010001
第二行就是n的值,第三行就是k的值。
- 使用 RSA 公私钥加解密
加解密的文件:
D:\test\ssl>type hello.txt
数据:11111111 11111111 11111111
密钥:11111111 11111111
加密:
D:\test\ssl>openssl pkeyutl -encrypt -in hello.txt -inkey public.pem -pubin -out hello.enD:\test\ssl>type hello.en
߫�)2��U��=�
因为加密了所以是乱码。
解密:
D:\test\ssl>openssl pkeyutl -decrypt -in hello.en -inkey private.pem -out hello.deD:\test\ssl>cat hello.de
'cat' is not recognized as an internal or external command,
operable program or batch file.D:\test\ssl>type hello.de
数据:11111111 11111111 11111111
密钥:11111111 11111111
不管是对称加密,还是非对称加密,想要应用到我们的网站中,还是需要一套规范来进行定义其具体行为的,即要想落地只有加密本身还是不够的,所以就有了PKI(public key infrastructure),接下来就看下这部分的内容。
2.3:非对称加密的应用PKI
PKI全称是public key infrastructure,即公钥基础设施,规定了为了能够让网站安全运行需要的元素,具体有如下的这些元素:
CA:certificate authority,即数字证书认证机构,负责颁发数字证书(数字签名)
公钥数字证书的组成:CA信息,公钥用户信息,公钥,权威机构签字,证书有效期等
PKI用户:向CA注册的用户,即申请证书的用户希望使用已经注册的公钥的用户(如浏览器)
数字签名,或数字证书的核心是使用私钥加密,只能使用公钥解密,从而就起到了身份认证的作用。需要注意数字证书仅仅用来进行认证,并不会用来加密传输的数据,加密传输数据还需要依赖于对称机密算法。
这部分的知识很难用线性的方式来进行学习,所以我们通过核心知识点的方式来进行学习。
2.3.1:证书申请的流程
假定鲍勃有一个个人网站,想要申请证书,那么流程是这样子的。首先鲍勃需要准备个人以及网站的基础信息,并使用rsa算法生成公钥和私钥,其中私钥自己保存使用,公钥和基础信息需要提交给CA机构,CA机构负责验证基础信息的真实性,验证通过后,CA也会自己生成公钥和私钥,接着使用私钥对数据进行加密,从而生成数字证书。
具体生成数字证书的过程是这样子的:
1:对用户基础信息执行hash函数,获取一个哈希值
2:CA使用自己的私钥对哈希值进行加密
3:将加密结果和用户的公钥组合在一起,生成证书
如下图:
所以在一个数字证书中就包含如下的信息:
1:基础信息
2:网站的公钥
3:CA的公钥
4:证书有效期等
5:CA机构信息
6:使用的哈希函数
如:
那么当浏览器拿到了这个公钥数字证书之后,如何验签呢,过程是这样子的:
1:浏览器从公钥证书中解析出基础数据和CA的签名
2:浏览器对基础数据使用哈希函数对基础数据执行哈希,获取签名结果1
3:浏览器对CA加密的签名结果使用CA的公钥解密,获取签名结果2
4:比较签名结果1和签名结果2,一致则验签成功,否则不成功
图示:
2.3.2:证书信任链
因为证书的需求量是比较庞大的,所以一个CA机构是远远不够的,所以就需要一些子的CA机构,这些子的CA机构来负责制作和办法证书,这样就形成了一种链式的结构,叫做证书信任链,其中最高级的CA机构叫做ROOT CA,上层CA为下层CA背书,结构如下:
查看CSDN:
2.3.3:PKI公钥基础设施包含哪些部分
1:证书订阅人申请证书,如网站持有者
2:登记机构记录和验证证书订阅人的基础信息,我认为可以看作CA的一部分。
3:CA颁发公钥证书
4:web服务器部署公钥证书
5:信赖方如浏览器,或其他https的客户端程序
6:CRL服务器,OCSP服务器存储证书的元信息,如是否有效等
具体过程是这样子的:
1:证书订阅人将基础信息和公钥交给登记机构,登记机构记录和验证信息
2:登记机构验证通过后将信息交给CA,CA颁发证书给证书订阅人
3:证书订阅人将证书部署到web服务器中
4:信赖方访问web服务器,web服务器将证书返回给信赖方
5:信赖方通过CRL服务器,OCSP服务器验证证书的有效性
图示:
2.3.4:证书类型
我们已经知道了,证书订阅人需要将基础信息提交给CA后,CA会对这些基础信息的真实性做出验证,根据验证的方式不同,内容不同,就分出了不同的证书类型,分别是DV证书,domain validated,OV证书,organization validated,EV证书,extended validated证书。级别依次增高,如下图:
如百度就是OV证书: