服务端:web容器 glassfish 部署了一个可以访问的web包
keystore.jks里添加的SSL证书,可参见 https://blog.csdn.net/yetugeng/article/details/81416320
客户端:一台笔记本,安装好wireshark
在服务端keystore.jks内容如下,主要省略了Extensions部分内容
[dev@localhost config]$ keytool -list -v -keystore keystore.jks -storetype jks -storepass changeit
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 2 entries
Alias name: glassfish-instance
Creation date: Dec 24, 2018
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=localhost.localdomain-instance, OU=GlassFish, O=Oracle Corporation, L=Santa Clara, ST=California, C=US
Issuer: CN=localhost.localdomain-instance, OU=GlassFish, O=Oracle Corporation, L=Santa Clara, ST=California, C=US
Serial number: 78ef63eb
Valid from: Mon Dec 24 12:12:29 HKT 2018 until: Thu Dec 21 12:12:29 HKT 2028
Certificate fingerprints:
MD5: 6C:5C:F1:FA:79:65:7F:1B:09:9F:D7:91:5B:63:C9:D5
SHA1: 78:B6:B9:27:9D:31:5B:D6:C1:24:04:A8:AD:F3:46:71:CA:30:C7:72
SHA256: 9F:06:23:E9:30:FB:3E:E5:AC:3A:01:40:12:78:56:72:36:38:62:C2:C2:0F:64:45:12:65:6A:88:2E:4E:2F:54
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
Extensions:
....此处略.....
*******************************************
*******************************************
Alias name: s1as
Creation date: Jul 21, 2019
Entry type: PrivateKeyEntry
Certificate chain length: 3 #表明证书链有三条
Certificate[1]: #第一条证书
Owner: CN=*.axxxxxxxxing.com, OU=PositiveSSL Wildcard, OU=Domain Control Validated
Issuer: CN=Sectigo RSA Domain Validation Secure Server CA, O=Sectigo Limited, L=Salford, ST=Greater Manchester, C=GB
Serial number: 488f8b186f0fc7b5949f566e5cd6a1c2
Valid from: Sat Jul 20 08:00:00 HKT 2019 until: Mon Jul 20 07:59:59 HKT 2020
Certificate fingerprints:
MD5: 25:C0:F6:C3:5A:41:BF:B6:B2:A9:7A:B4:6B:DD:9A:DC
SHA1: 22:7A:AD:A6:2F:5A:A5:C1:C9:E0:C6:B6:35:55:56:14:D1:CC:5F:6E
SHA256: 38:81:F8:0B:FD:9F:97:F2:68:C1:53:7F:32:5F:AB:D3:C6:A0:86:7F:A3:8A:10:CB:98:F1:CD:93:BF:7E:34:09
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
Extensions:
....此处略.....
Certificate[2]: #第三条证书
Owner: CN=Sectigo RSA Domain Validation Secure Server CA, O=Sectigo Limited, L=Salford, ST=Greater Manchester, C=GB
Issuer: CN=USERTrust RSA Certification Authority, O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US
Serial number: 7d5b5126b476ba11db74160bbc530da7
Valid from: Fri Nov 02 08:00:00 HKT 2018 until: Wed Jan 01 07:59:59 HKT 2031
Certificate fingerprints:
MD5: AD:AB:5C:4D:F0:31:FB:92:99:F7:1A:DA:7E:18:F6:13
SHA1: 33:E4:E8:08:07:20:4C:2B:61:82:A3:A1:4B:59:1A:CD:25:B5:F0:DB
SHA256: 7F:A4:FF:68:EC:04:A9:9D:75:28:D5:08:5F:94:90:7F:4D:1D:D1:C5:38:1B:AC:DC:83:2E:D5:C9:60:21:46:76
Signature algorithm name: SHA384withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
Extensions:
....此处略.....
Certificate[3]: #第三条证书
Owner: CN=USERTrust RSA Certification Authority, O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US
Issuer: CN=AddTrust External CA Root, OU=AddTrust External TTP Network, O=AddTrust AB, C=SE
Serial number: 13ea28705bf4eced0c36630980614336
Valid from: Tue May 30 18:48:38 HKT 2000 until: Sat May 30 18:48:38 HKT 2020
Certificate fingerprints:
MD5: DB:78:CB:D1:90:95:27:35:D9:40:BC:80:AC:24:32:C0
SHA1: EA:B0:40:68:9A:0D:80:5B:5D:6F:D6:54:FC:16:8C:FF:00:B7:8B:E3
SHA256: 1A:51:74:98:0A:29:4A:52:8A:11:07:26:D5:85:56:50:26:6C:48:D9:88:3B:EA:69:2B:67:B6:D7:26:DA:98:C5
Signature algorithm name: SHA384withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3
Extensions:
....此处略.....
*******************************************
*******************************************
[dev@localhost config]$
我们重点需要看的是别名为s1as的这部分,其中s1as下包含了3条证书
分别是泛域名*.axxxxxxxxing.com的证书以及上两级的签名授权商的证书。
(1)为了在握手协议解决降级攻击的问题,TLS协议规定:client发送ClientHello消息,server必须回复ServerHello消息,否则就是fatal error,当成连接失败处理。ClientHello和ServerHello消息用于建立client和server之间的安全增强能力,ClientHello和ServerHello消息建立如下属性:
Protocol Version
Session ID
Cipher Suite
Compression Method
(2)另外,产生并交换两个random值 ClientHello.random 和 ServerHello.random
(3)密钥协商使用四条: server的Certificate,ServerKeyExchange,client的Certificate,ClientKeyExchange 。TLS规定以后如果要新增密钥协商方法,可以订制这4条消息的数据格式,并且指定这4条消息的使用方法。密钥协商得出的共享密钥必须足够长,当前定义的密钥协商算法生成的密钥长度必须大于46字节。
(4)原理类似下图(实验步骤中会详细介绍)
握手消息 | 动作描述 | 消息内容 |
---|---|---|
1. Client —> Server Client Hello |
客户端(浏览器)发送一个hello消息给服务端,发起建立SSL会话的请求。并告诉服务端,自己支持哪些加密算法(Cipher Suite List)。除此之外,还需要产生一个随机数(第一个随机数,用于以后生成对称密钥),发送给服务端。 | 1)支持的协议版本,如TLS 1.0版 2)由客户端生成的随机数,用于生成后面的“对称密钥” 3)支持的加密方法,比如RSA公钥加密 4)支持的压缩方法 5)请求的域名 |
2. Server —> Client Server Hello |
服务端的首次响应,会确定加密协议版本,以及加密的算法,也会生成一个随机数(第二个随机数)给客户端。 | 1)协议的版本 2)加密的算法 3)服务端生成的随机数 |
3. Server —> Client Certificate |
还会把自己的证书发送给客户端,让客户端进行校验。服务端证书中的公钥也可被用于加密后面握手过程中生成的对称密钥。 | 1)服务端证书 证书颁发机构的名称 证书本身的数字签名 证书持有者公钥 证书签名用到的Hash算法 |
4. Server —> Client Server Key Exchange |
指定使用哪种密钥协商协议。服务端可以在ServerKeyExchange之后立即发送CertificateRequest消息,要求校验客户端的证书。 | 1)使用哪种密钥协商方式 2)密钥协商时客户端需要的信息 |
5. Server —> Client Server Hello Done |
服务器发送ServerHelloDone消息,告知客户端服务器这边握手相关的消息发送完毕。 | |
6. Client —> Server Client Key Exchange |
消息中包含客户端这边的EC Diffie-Hellman算法相关参数,然后服务器和客户端都可根据接收到的对方参数和自身参数运算出对称密钥。 | 1)密钥协商时服务端需要的信息 |
7. Client —> Server Change Cipher Spec |
ChangeCipherSpec消息,通知服务器此消息以后客户端会以加密方式发送数据。 | 准备好了做加密传输的通知 |
8. Client —> Server Finished |
客户端计算生成对称密钥,然后使用该对称密钥加密之前所有收发握手消息的Hash值,发送给服务器,服务器将相同的会话密钥(使用相同方法生成)解密此消息,校验其中的Hash值。 | |
9. Server —> Client Change Cipher Spec |
ChangeCipherSpec消息,通知客户端此消息以后服务器会以加密方式发送数据。 | 准备好了做加密传输的通知 |
10. Server —> Client Finished |
服务器使用对称密钥加密(生成方式与客户端相同)之前所发送的所有握手消息的hash值,发送给客户端去校验。 | |
11. Application Data | 真正的数据传输(使用对称加密) |
1.访问我自己的网站 http://*.axxxxxxxxing.com:8181/,网站IP为 103.110.152.xxx
2.wireshark抓包,使用 ip.src == 103.110.152.xxx && ssl 规则来过滤包。如图 4-1 :
图 4-1首先我们了解一下建立握手连接的目的:
(1)身份的验证,client与server确认对方是它相连接的,而不是第三方冒充的,通过证书实现;
(2)client与server交换session key,用于连接后数据的传输加密和hash校验。
其次分析简单的SSL握手连接过程(仅Server端交换证书给client):
客户端(浏览器)发送一个hello消息给服务端,发起建立SSL会话的请求。并告诉服务端,自己支持的协议版本和哪些加密算法(Cipher Suite List)。除此之外,还需要产生一个随机数random(第一个随机数,用于以后生成对称密钥),发送给服务端。
如图 5-1中 30号包,
图 5-1-1
表明此包为TLS的第一个包,参见图3-1过程。
显示了本包的类型为 Handshake (22)。
TLS的ContentType有如下一些,详见 https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-5
图 5-1-2协议版本(客户端期望支持的握手协议版本),版本号的编码规则如下
Common Version name |
|
Response Minor version |
SSL 3.0 |
|
00 |
TLS 1.0 |
|
01 |
TLS 1.1 |
|
02 |
TLS 1.2 |
|
03 |
握手类型大概有如下一些,详见https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-7
图 5-1-3安全随机数(MasterSecret生成用到,协议文档里面说是28个字节,但是实际抓包看到是32个字节,这里怀疑是各个协议文档版本不同,还有使用加密套件的不同,导致的差异,具体博主就没有在继续深究了,如果有朋友知道可以留言给我)
图 5-1-4从底部一栏可以看到全部字段 ,5d6dd059b5ad015d25bbba75a4b7913494b31eb34fdbabefa769cd33dc4badd1
4字节:5d6dd059
28字节:b5ad015d25bbba75a4b7913494b31eb34fdbabefa769cd33dc4badd1
5d6dd059 (16进制)-> 1567477849(十进制,时间戳)-> 2019-09-03 10:30:49 (日期格式)
图 5-1-5即客户端将时间戳连同随机字符串放在一起作为一串字符串发送给服务端。
这个值是被服务端设置的,如果这个值为空,表示客户端与服务端没有存活的https会话,需要与服务端进行完整的握手。
如果这个值存在,则表明客户端期望恢复上一次的https会话,这时候客户端与服务端只需要进行快速的握手过程。
加密套件(客户端支持的加密套件列表)
如果前面的sessionid不为空,可以不传这个值,服务端可以从上一次会话中恢复这个值。
可以看到,客户端发送了21种可用密码套件给服务端,然后由服务端挑选自己支持的套件。
每个加密组件(Cipher Suite)都包括了下面5类算法 , 后面会看到本例中服务端使用的是就是 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 这个加密套件:
(1) authentication (认证算法):RSA
(2) encryption (加密算法 ):AEAD_AES_256_GCM
(3) message authentication code (消息认证码算法 简称MAC):SHA384
(4) key exchange (密钥交换算法):ECDHE
(5) key derivation function (密钥衍生算法)
更多密码套件详见官方文档 TLS Cipher Suite Registry
如下图,wireshark中括号里的十六进制值,就对应下图的Value 。
图 5-1-7加密前进行数据压缩
图 5-1-8压缩方式有如下一些,详见 https://www.iana.org/assignments/comp-meth-ids/comp-meth-ids.xhtml
图 5-1-9因为压缩方法被攻击,在TLS1.3协议版本上已经彻底禁止压缩了。(这里有两种攻击方式BREACH、CRIME,有时间博主会来研究)
最后我们来看看扩展,本例中客户端发送了8种扩展。
比如第一个扩展 Extension: server_name (len=23) 中,就包含了我们访问的域名。
图 5-1-10常见扩展类型有50多种,如下图 5-11,更多详见 https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
图 5-1-11
服务端的首次响应,会确定加密协议版本,以及加密的算法,也会生成一个随机数(第二个随机数)给客户端。
图 5-2-1不过这里我们在如 图 5-2-1 中看起来有些不一样,如 36号包 的Info 字段显示的是Server Hello,Certificate,Server Key Exchange,Server Hello Done 四个过程。
但是绿色框中,[4 Reassembled TCP Segments (4949 bytes): #32(1412), #33(1412), #35(1412), #36(713)] 表明 36号包是整合了32,34,35,36 四个包的内容一起显示的。所以才有红色框里的 Multiple Handshake Messages显示 。
且看图中面黄色框里就是详细展示这四个握手阶段的内容。
现在我们进一步展开 Handshake Protocol: Server Hello 部分。
服务端最高支持的握手协议版本,TLS/SSL协议都是向下兼容的。
现在我们将Client Hello 和Server Hello里面randam进行对比
#Client Hello
Random: 5d6dd059b5ad015d25bbba75a4b7913494b31eb34fdbabefa769cd33dc4badd1
Random Bytes: b5ad015d25bbba75a4b7913494b31eb34fdbabefa769cd33dc4badd1
Session ID: 空
5d6dd059 -> 1567477849 -> 2019-09-03 10:30:49
#Server Hello
Random: 5d6dd04ae801b092ff9d891027a4f4d76293a29780e86e83996564dbf87fa520 #这就是上文说的第二个随机数吧
Random Bytes: e801b092ff9d891027a4f4d76293a29780e86e83996564dbf87fa520
Session ID: 5d6dd04a4db6e7a76205eb180fe7e1557961b95c8b8a2eb6fbb7e792f242e68d
5d6dd04a -> 1567477834 -> 2019-09-03 10:30:34
这里多了个Session ID,但是Server Hello中的时间竟然比 Client Hello中的时间更早?这个我还没看懂,忘大神指点。
如果客户端hello有发送session id,服务端从内存中查找,并尝试恢复之前的会话状态。
恢复成功,服务端返回同样的session id。
恢复不成功,服务端此字段返回空。
服务端从客户端hello的cipher suite列表中选择一个加密套件,如果是恢复上一次的会话,则从会话状态中恢复上一次相同的加密套件。
本次测试,服务端选择的密码套件是 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
服务端从客户端hello的compression_methods列表中选择一个压缩方法,如果是恢复上一次的会话,则从会话状态中恢复上一次相同的压缩方法。
这里包含了两个扩展
图 5-2-3注意这里服务端的扩展里面没有包括 session ticket,证明服务端不支持该机制。
服务端把自己的证书发送给客户端,让客户端进行校验。服务端证书中的公钥也可被用于加密后面握手过程中生成的对称密钥。
图 5-3-1如图 5-3-1服务端发送的是一个证书链,可能包含多个证书 ,这里有三个证书:
下面,我们使用 https://www.geocerts.com/ssl-checker 这个网站可以测试web服务证书安装情况,检测结果如下图
图 5-3-2从图 5-3-2 中我们看到,由上往下证书链的关系依次是:
泛域名 *.aixxxxxxxing.com 被 Sectigo RSA Domain Validation Secure Server CA 签发,
Sectigo RSA Domain Validation Secure Server CA 被 USERTrust RSA Certification Authority 签发,
USERTrust RSA Certification Authority 被 AddTrust External CA Root 签发,
AddTrust External CA Root 被自身AddTrust External CA Root签发。
那证书中到底包含了些什么内容呢?
- 证书版本号(Version)
- 证书序列号(Serial Number)
- 签名算法标识符(Signature Algorithm)
签名算法标识用来指定由CA签发证书时所使用的"签名算法"。算法标识符用来指定CA签发证书时所使用的:
1) 公开密钥算法
2) hash算法
example: sha256WithRSAEncryption
须向国际知名标准组织(如ISO)注册- 签发机构名(Issuer)
- 有效期(Validity):指定证书的有效期
- 证书用户名(Subject)
- 证书持有者公开密钥信息(Subject Public Key Info)
证书持有者公开密钥信息域包含两个重要信息:
1) 证书持有者的公开密钥的值
2) 公开密钥使用的算法标识符。此标识符包含公开密钥算法和hash算法。- 扩展项(extension)
- 签发者唯一标识符(Issuer Unique Identifier)
- 证书持有者唯一标识符(Subject Unique Identifier)
- 签名算法(Signature Algorithm)
- 签名值(Issuer's Signature)
我们再回过头来看看本文第二部分的keystore.jks,里面有三个证书分别如下,只是这里只显示除了前三个证书,最后一个根证书自签名的没有存储在keystore.jks文件里。
...
Certificate[1]: #第一条证书
Owner: CN=*.axxxxxxxxing.com, OU=PositiveSSL Wildcard, OU=Domain Control Validated
Issuer: CN=Sectigo RSA Domain Validation Secure Server CA, O=Sectigo Limited, L=Salford, ST=Greater Manchester, C=GB
...
Certificate[2]: #第三条证书
Owner: CN=Sectigo RSA Domain Validation Secure Server CA, O=Sectigo Limited, L=Salford, ST=Greater Manchester, C=GB
Issuer: CN=USERTrust RSA Certification Authority, O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US
...
Certificate[3]: #第三条证书
Owner: CN=USERTrust RSA Certification Authority, O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US
Issuer: CN=AddTrust External CA Root, OU=AddTrust External TTP Network, O=AddTrust AB, C=SE
...
现在,我们再回到wireshark详细地看看第一个证书
图 5-3-4后面两个证书就不多说了,与第一个证书类似。需要详细研究的可以自己抓包来测试。
如何校验服务端证书呢?
图 5-3-5#### 详细解释服务端的证书是怎么生成的?
由于我这个证书是在某宝买的,所以公钥私钥这些信息都是由卖家提供的.
CA怎么验证证书是不是自己颁发的呢?以及做证书内容校验?
浏览器通常也会内置大多数主流权威CA的根证书,如下图
图 5-3-7
如果查找不到对应的可信CA,则判断这个证书是伪造的,不可信的。(浏览器则会提醒该证书不是可信任机构颁发的,并询问是否要继续访问)
CA机构证书
里面的公钥
信息,将网站方证书
中的签名值
(也就是数字签名)做解密,得到网站证书
信息的hash摘要A。网站证书
中的信息,做hash得到摘要B,比对摘要A和摘要B是否一致。如果不一致,说明网站证书
中的信息被修改了。(浏览器则会提醒该证书不是可信任机构颁发的,并询问是否要继续访问)公钥
,用于后面的握手签名。这个步骤是密钥协商的服务端部分,最终的密钥将会用于传输数据对称加密。
服务端需要发送一个Diffie-Hellman算法的公钥,和指定使用哪种椭圆曲线多项式。
我们到Client Key Exchange的时候,再来讲这个密钥协商过程。
这里还有一个签名,校验这个流程的数据是否被篡改。如下图所示,客户端收到Server Key Exchange数据后,可以用上个流程中获得的证书
公钥对签名值解密,获得摘要A。并将这次数据明文做SHA512的hash,获得摘要B,做比对。(这里对协商算法做签名校验,目的可能是防止中间人对协商算法方式做篡改,虽然DH算法不担心公钥在不安全的网络中传输,但是其他算法可能需要考虑被篡改的情况。所以猜测服务端密钥协商时做签名是这个目的,因为服务端这时已经确定是DH算法了,所以客户端协商时就不需要做签名了,DH算法不需要考虑这个安全问题)
服务端发送ServerHelloDone消息表示,已经发送完了密钥协商需要的消息,并且客户端可以开始进行客户端的密钥协商处理了,也就是Client Key Exchange。
收到ServerHelloDone后,客户端需要确认服务器是否提供了合法的证书,并且确认服务器的ServerHello消息里面的参数是否可以接受。
回顾一下图 5-2-1,一个 TLSv1.2 Record Layer: Handshake Protocol: Multiple Handshake Messages下面包含了四个Handshake Protocol,分别是 Server Hello,Certificate,Server Key Exchange,Server Hello Done。
而这里一个包里包含了三个 TLSv1.2 Record Layer,分别是如下图所示
图 5-7-1展开 Client Key Exchange如下图
图 5-7-2服务端密钥协商的公钥以及自己的公钥
EC Diffie-Hellman
密钥协商协议为例,来看看客户端、服务端是怎么协商出相同的密钥的(这里协商出来的是PreMasterSecret,不是最终的对称加密用到的密钥)。展开Change Cipher Spec如下图
图 5-7-3client发送的encrypted handshake message加密数据非常关键,一是能证明握手数据没有被篡改过,二也能证明自己确实是密钥的拥有者(这里是单边验证,只有server有certificate,server发送的Finished能证明自己含有private key,原理是一样的)。client将之前发送的所有握手消息存入handshake message缓存。
图 5-7-4struct {
ProtocolVersion protocol_version; //协议版本
CipherSuite cipher_suite; //加密套件类型
CompressionMethod compression_method; //压缩方法
opaque master_secret[48]; //对称密钥
ClientIdentity client_identity; //客户端ID
uint32 timestamp;//ticket有效期
} StatePlaintext;
本例中,没有出现 Server New Session Ticket
与9. Client Finished的情况一样,使用对称密钥加密,最后做一次验证,确定双方是否都准备好进行数据传输了。
只是这里加密的数据还不是真正的网站内容数据,而是握手过程的数据。
图 5-7-6
参考文章:
https://www.cnblogs.com/20179204gege/p/7858070.html
https://www.cnblogs.com/Anker/p/6082966.html
https://blog.csdn.net/liangyihuai/article/details/53098482
http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html
https://xz.aliyun.com/t/1039
https://blog.helong.info/blog/2015/09/06/tls-protocol-analysis-and-crypto-protocol-design/