理解HTTPS协议

定义

HTTPS*(也称为 *HTTP over TLSHTTP over SSL ,和 HTTP Secure )是用于在因特网上广泛使用的计算机网络上的安全通信的协议。HTTPS 通过 TLS 或其前身的 SSL 实现超文本传输​​协议(HTTP)的安全传输。

在密码学中,加密(英语:Encryption )是将明文信息改变为难以读取的密文内容,使之不可读。只有拥有解密方法的对象,经由解密过程,才能将密文还原为正常可读的内容。

对称加密 & 非对称加密

在现代加密体制主要有两种方式:

  • 对称加密,即在加密与解密的过程中使用相同的加密密钥 (cryptographic keys) 的算法,比如 DESRC4AES
  • 非对称/公开加密,会使用一对密钥,分别命名为公钥与私钥,两个密钥可以互相加解密。外部可以获取公钥,但私钥一般只有所有者才知道。我们最熟悉的非对称加密应该就是 RSA 吧。

优缺点

对称加密的缺点主要在于密钥必须双方共享,否则无法实现加解密,只要其中一方(主要指客户端)暴露了密钥,加密过程就不安全了,非对称加密克服了这一点,客户端获得的是服务器的公钥,本来就是公开的,被人获取也不影响。虽然非对称加密有这个好处,但是它的加密的效率比对称加密逊色。所以在 HTTPS 中两者都被使用到了。认证过程采用了非对称加密,而实际数据的传输使用了对称加密。

非对称加密的用途

公钥加密 + 私钥解密 用于通信加密
私钥加密 + 公钥解密 用于身份认证

因此服务器用私钥加密的内容,只要持有公钥,都是可以解密的

SSL 握手流程

图片来自wiki - 传输层安全协议,描述的是 SSL 的握手流程。

协商加密算法

  1. 客户端发送 ClientHello 消息,包含支持的协议版本,加密和压缩算法等,一个客户端生成的随机数 RNc
  2. 服务器收到 ClientHello 消息后,发送 ServerHello 确定要采用的协议版本,加密和压缩算法等,同时生成一个随机数 RNs

RNcRNs 将用于参与后面的 生成对称加密密钥 过程

交换证书

关于证书,在此处可理解为一种身份认证的方式,后面说明

  1. 服务器会发送证书(包含自身的公钥)发送给客户端,并要求客户端证书
  2. 客户端会校验服务器发送的证书是否可信,如果不可信,则关闭连接,若可信,继续执行
  3. 客户端会发送证书(包含自身的公钥)到服务器,这在双向认证时要求,一般情况下只要发送随机生成的公钥即可,主要还是要确认服务器是安全可信的。
  4. 服务器检验客户端证书,获得公钥,继续执行
  5. 客户端会将刚才发送的信息进行 hash 并用自己的私钥进行加密/签名,
  6. 服务器接收后会用得到的客户端的公钥先解密并用相同的算法进行 hash 比较结果

最后的两步,我不确定用途,只能揣测是为了证明服务器已经收到了客户端的公钥同时算法都没有问题。

生成对称加密密钥

RFC 2246 - The TLS Protocol Version 1.0 中,有如下的一段话

7.4.7.1. RSA encrypted premaster secret message

Structure of this message:
   struct {
     ProtocolVersion client_version;
     opaque random[46];
   } PreMasterSecret;
   client_version
     The latest (newest) version supported by the client. This is
     used to detect version roll-back attacks. Upon receiving the
     premaster secret, the server should check that this value
     matches the value transmitted by the client in the client
     hello message.
   random
     46 securely-generated random bytes.

因此 pre master key 的结构为 2 字节协议版本,匹配客户端一开始发送 ClientHello 时所提供的信息,46 字节随机数。它的作用是为了与协商加密算法阶段中随机生成的两个数 RNcRNs 组合,最终生成本次会话中用于对称加密的密钥( Master secret )。

Generate a master secret from the premaster secret and exchanged random values.

  1. 客户端生成 pre master key,并通过服务器的公钥加密后发送给服务器
  2. 服务器用自己的私钥解密,双方现在都有 pre master key + RNc + RNs
  3. 客户端与服务器使用相同的算法将 pre master key + RNc + RNs 各自进行计算,生成 Master secret
  4. 客户端通知服务器接下来的通信用 Master secret 做为对称加密的密钥,结束 SSL 握手通信
  5. 服务器收到消息后,同样发送消息到客户端,确认使用 Master secret 为对称加密的密钥,结束 SSL 握手通信。

数字证书

为什么在 HTTPS 会话中要用到数字证书?

我们看到交换证书的过程中服务器发送的证书中包含了它的公钥,试想如果有不怀好意的中间人拦截了请求,与客户端协商了加密的算法,接收 RNc 并发送 RNs ,然后将自己的公钥发送给客户端。客户端不做校验就接收了,那后面的整个过程都是不安全的。所以需要一个凭证让客户端来验证这个公钥是不是属于与其通信的服务器。

数字证书就充当了这个提供凭证的角色

定义

wiki-电子证书中表明了数字证书并非数字身份证,而是身份认证机构盖在数字身份证上的一个章或印(或者说加在数字身份证上的一个签名),这一行为表示身份认证机构已认定这个持证人。

栗子

打开钥匙串,查看一个数字证书

CA

CA (certificate authority) 就是一个提供身份认证的机构,为什么信任 CA*,证书的信任是链式的向上传递。在 *mac 上开发者证书的信任问题最终会走到苹果的根证书上,因为我们信任了这个证书,所以后面苹果服务器( CA )签名的证书我们也会信任。

而对于 12306 网站浏览器之所以会弹出

同样是因为系统不信任 12306 的根证书 SRCA ,所以由它签发的 kyfw.12306.cn 证书也是不受信任的。

csr (Certificate Signing request)

What is a CSR? A CSR or Certificate Signing request is a block of encoded text that is given to a Certificate Authority when applying for an SSL Certificate. It is usually generated on the server where the certificate will be installed and contains information that will be included in the certificate such as the organization name, common name (domain name), locality, and country. It also contains the public key that will be included in the certificate. A private key is usually created at the same time that you create the CSR, making a key pair. A CSR is generally encoded using ASN.1 according to the PKCS #10 specification.

我们通过钥匙串创建的 csr 文件会包含了组织名,域名,国家等信息,同时还包含了公钥。在生成 csr 文件时也生成了对应的私钥,保存在钥匙串中。

总结

我们平时通过钥匙串通过创建 csr 请求文件的行为,实际上是将自身信息和生成的公钥放到其中,发送给苹果服务器后,苹果服务器会使用自己的私钥对其进行签名,生成 cer 文件,我们下载到客户端,客户端发现该证书是可信的,就从钥匙串中找到并与它的私钥一起进行配置。

苹果服务器在这个场景下实际充当了 CA 的角色,若是服务器本身自己做 CA 进行签名也是可以的,这种情况下称为自签名,但是在 HTTPS 的会话中对证书进行校验时一般会失败,客户端需要操作信任该证书。

到这里,大致可以总结出数字证书的产生过程

HTTPS 协议中,客户端的证书验证与上面的场景类似,服务器预先从 CA 那获得数字证书,当客户端要求证书时,将该证书返回给客户端,只要客户端信任 CA , 就可以通过 CA 的公钥解密出服务器发来的证书( CA 用私钥签名服务器的一些信息与公钥),从而得到公钥,同时判定公钥是来自服务器的。

但是这里有一个问题,如果中间人也请求了 CA 生成了对应的证书,客户端依然无法确定公钥是来自服务器的,还有是否有被修改。

参考 也许,这样理解HTTPS更容易 这篇文章可知,要由客户端负责去校验证书是否合法。

具体方式是客户端得到证书后,根据证书的内容(比如说服务器域名)和算法,客户端再生成一遍签名的过程,然后与证书编号进行比较,因为每个证书的编号应该是唯一的,所以中间人不能创建一个和原证书内容不同,然后编号却相同。如果出现了,那也是算法出的问题,不是设计思路有漏洞。因此客户端可以通过这种方式验证当前获得的证书是否符合要求。从而得到属于服务器的公钥,接着再继续 HTTPS 会话。

实践

现在来动手操作,通过 Wireshark 捕获 HTTPS 请求来验证整个流程。
如果直接手动打开 Wireshark 然后尝试捕获 eth0 网卡,可能会报权限不足的方法。简单的方法就是用终端直接 sudo Wireshark 打开

因为网络的信息非常多,需进行过滤

tcp.srcport == 443 or tcp.dstport == 443

我们只关注走 443 端口的 tcp 协议

访问 https://www.baidu.com

出现了 Client Hello , Server Helloinfo 依次到里面看看

[实践]Client Hello

  • 协议版本 tls 1.2 (0x0303) 2 个字节
  • 随机数 RNc : 27ca27…
  • 客户端支持的加密方式 : TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00ff…
  • Extension : server_name 下有 www.baidu.com

[实践]Server Hello

服务器确定了协议版本号,生成了 RNs,确定了加密的方法

[实践]证书交换

服务器将包含自己公钥的数字证书发送给客户端

客户端验证证书通过后,将发送公钥给服务器

[实践]生成对称加密密钥

双方互相通知对方,准备用加密算法对数据加密了,同时结束握手通信

但是好像少了 SSL 中所谈到的生成对称密钥的过程额

Google 搜索后发现在TLS Extended Master Secret, Breaking SSL Proxies提到了

Before extended master secret extension was introduced, parties communicating under TLS protocol (RFC 5246) would compute master secret with the following formula:
master_secret = PRF(pre_master_secret, “master secret”,
 ClientHello.random + ServerHello.random)
 [0..47];

RFC 5246Master secret 确实是使用 pre master secret + ClientHello.random + ServerHello.random 计算生成的,但是在 RFC 7627中描述了一种攻击。

  1. C sends a “ClientHello” to A, and A forwards it to S.
  2. S sends a “ServerHello” to A, and A forwards it to C.
  3. S sends a “Certificate”, containing its certificate chain, to A.
    A replaces it with its own certificate chain and sends it to C.
  4. S sends a “ServerHelloDone” to A, and A forwards it to C.
  5. C sends a “ClientKeyExchange” to A, containing the
    “pre_master_secret”, encrypted with A’s public key. A decrypts
    the “pre_master_secret”, re-encrypts it with S’s public key, and
    sends it on to S.
  6. C sends a “Finished” to A. A computes a “Finished” for its
    connection with S and sends it to S.
  7. S sends a “Finished” to A. A computes a “Finished” for its
    connection with C and sends it to C.

被攻击的主要原因是 Master Secret 只依赖于 ClientHello.random , ServerHello.random ,解决方案是把证书和会话的信息都参与到 Master Secret 的生成过程

扩展类型为0x0017的扩展主密钥向客户端和服务器通知使用以下公式生成主密钥:

master_secret = PRF(pre_master_secret, “extended master secret”,
  session_hash)
  [0..47];

通过总结与实践尝试,我对 HTTPS 协议的认识又深刻了一点

That’s all

参考

理解Block(下) iOS上实现 3D Touch 功能
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×