超详细https握手与数字签名讲解

12,108 阅读14分钟

之前看过很多https相关内容,感觉都是有个大概印象。趁着刚阅读《http权威指南》后,发表一下自己的理解。如果我有讲的不对的地方,麻烦大家帮我指点出来,阿里嘎多~

其实我也不知道从哪里开始讲起,咱走一步算一步吧哈哈哈哈哈哈。

总览

大部分困难的编码及解码工作都是在 SSL 库中完成的,所以 Web 客户端和服务器在使用安全 HTTP 时无需过多地修改其协议处理逻辑。在大多数情况下,只需要用 SSL 的输入 / 输出调用取代 TCP 的调用,再增加其他几个调用来配置和管理安全信息就行了。 

对称密钥与非对称密钥

 相比之下,对于对称密钥加密技术,128 位的密钥被认为是非常强大的。实际上, 长密钥对密码安全有着非常重要的影响,美国政府甚至对使用长密钥的加密软件实 施了出口控制,以防止潜在的敌对组织创建出美国国家安全局(National Security Agency,NSA)自己都无法破解的秘密代码。基本上可以理解为,用128位的密钥黑客基本GG了。

对称密钥加密技术的缺点之一就是发送者和接收者在互相对话之前,一定要有一个共享的保密密钥。每对通信实体都需要自己的私有密钥。如果有 N 个节点, 每个节点都要和其他所有 N-1 个节点进行安全对话,总共大概会有 N2 个保密密钥: 这将是一个管理噩梦。非对称加密不仅更安全,而且还减少了服务器端的压力,因为它不用再记住它和每个客户端的秘钥。

RSA 算法就是一个满足了所有这些条件的流行的公开密钥加密系统,它是在 MIT发明的,后来由 RSA 数据安全公司将其商业化。即使有了公共密钥、任意一段明文、用公共密钥对明文编码之后得到的相关密文、RSA 算法自身,甚至 RSA 实现 的源代码,破解代码找到相应的私有密钥的难度仍相当于对一个极大的数进行质因 数分解的困难程度,这种计算被认为是所有计算机科学中最难的问题之一。因此, 如果你发现了一种能够快速地将一个极大的数字分解为质因数的方法,就不仅能够 入侵瑞士银行的账户系统,而且还可以获得图灵奖了。

(还做什么程序员,不如去研究一下RSA穷其一生说不定和毕加索一样永垂不朽了)


但公开密钥加密算法的计算可能会很慢。实际上它混合使用了对称和非对称策略。 比如,比较常见的做法是在两节点间通过便捷的公开密钥加密技术建立起安全通信, 然后再用那条安全的通道产生并发送临时的随机对称密钥,通过更快的对称加密技 术对其余的数据进行加密。-----------没错就是https.

还在混淆数字证书和数字签名吗?

数字证书

数字证书(通常被称作“certs”,有点像 certs 牌薄荷糖)中包含了由某个受信任组织担保的用户或公司的相关信息。 我们每个人都有很多形式的身份证明。有些 ID,比如护照和驾照,都足以在很多场合证明某人的身份。例如,你可以用美国的驾照在新年前夜搭乘前往纽约的航班, 在你到那儿之后,接着用它来证明你的年龄,这样你就能和朋友们一起喝酒了。

受信程度更高的身份证明,比如护照,是由政府在特殊的纸上签发并盖章的。很难 伪造,因此可以承载较高的信任度。有些公司的徽章和智能卡中包含有电子信息, 以强化使用者的身份证明。有些绝密的政府组织甚至会对你的指纹或视网膜毛细血 管模式进行匹配以便确认你的 ID ! 

数字证书主要内容:

数字证书通常还包括对象的公开密钥以及对象和所用签名算法的描述性信 息。任何人都可以创建一个数字证书,但并不是所有人都能够获得受人尊敬的签发 权,从而为证书信息担保,并用其私有密钥签发证书。 


我要强调一点!数字证书通常还包括所用签名算法的描述性信息

为什么我要强调这个玩意儿呢?因为当然这就是在一开始三步握手交换信息时双方验证摘要报文的时候,要用到!!!很多人很懵逼不知道浏览器和服务器怎么验证报文的,因为几乎没有作者详细介绍是如何验证过程的,或许你看了我下面解释的这个过程,甚至自己想实现一把。

报文摘要:用于对发送的报文生成一个非常小的摘要信息。这个摘要信息保证原报文的完整性,即原报文只要有一位被改变,则摘要信息就会不匹配。对报文使用签名函数(SHA-1和MD5,而签名函数来自数字证书!

摘要是“对信息主体的浓缩”。摘要是一种单向函数,主要用于将无限的输入值转 换为有限的浓缩输出值。7常见的摘要函数 MD5,会将任意长度的字节序列转换为 一个 128 位的摘要。有时也将摘要函数称为加密的校验和、单向散列函数或指纹函数。强调单向防止被逆向啊。  这样才能百分百保证信息没有完全被修改。听不懂???没关系,这才是开胃菜。

数字签名:

数字签名来验证证书的完整性。就是在第二步握手的时候,稍后讲解。

用加密系统对报文进行签名(sign),以说明是谁编写的报文,同时证明报文未被篡改过。这种技术被称为数字签名(digital signing),

签名是加了密的校验和:

  • 签名可以证明是作者编写了这条报文。只有作者才会有最机密的私有密钥, 因此,只有作者才能计算出这些校验和。校验和就像来自作者的个人“签名”一样。

  • 签名可以防止报文被篡改。如果有恶意攻击者在报文传输过程中对其进行了修改,校验和就不再匹配了。由于校验和只有作者保密的私有密钥才能产生,所以攻击者无法为篡改了的报文伪造出正确的校验码。

    RSA 加密系统将解码函数 D 作为签名函数使用,是因为 D 已经将私有密钥作为输入使用了。注意, 解码函数只是一个函数,因此,可以将其用于任意的输入。同样,在 RSA 加密系统中,以任意顺序 应用 D 和 E 函数时,两者都会相互抵消。因此 E(D(stuff)) = stuff,就像 D(E(stuff)) = stuff 一样。

  • 此时假定私有密钥没有被人偷走。大多数私有密钥都会在一段时间后过期。还有一些“取消列表”记 录了被偷走或入侵的密钥。

HTTPS方案

通常情况下,非安全 HTTP 的 URL 方案前缀为 http,如下所示:

http://www.joes-hardware.com/index.html

在安全 HTTPS 协议中,URL 的方案前缀为 https,如下所示:

https://cajun-shop.securesites.com/Merchant2/merchant.mv?Store_Code=AGCGS

请求一个客户端(比如 Web 浏览器)对某 Web 资源 执行某事务时,它会去检查 URL 的方案。 

  • 如果 URL 的方案为 http,客户端就会打开一条到服务器端口 80(默认情况下) 的连接,并向其发送老的 HTTP 命令 

  • 如果 URL 的方案为 https,客户端就会打开一条到服务器端口 443(默认情况下) 的连接,然后与服务器“握手”,以二进制格式与服务器交换一些 SSL 安全参数, 附上加密的 HTTP 命令 



现在通常是第三种方案。

SSL握手

在发送已加密的 HTTP 报文之前,客户端和服务器要进行一次 SSL 握手,在这个握手过程中,它们要完成以下工作: 

• 交换协议版本号;
• 选择一个两端都了解的密码;
• 对两端的身份进行认证;
• 生成临时的会话密钥,以便加密信道。 

我们来一个http握手https握手概览。




这是一个概览,有利于下面我们在具体分析的时候,不知道在哪个过程的时候,记得来看图对比。让你对https握手更加清晰。

服务器证书

 通过 HTTPS 建立了一个安全 Web 事务之后,现代的浏览器都会自动获取所连接服务器的数字证书。如果服务器没有证书,安全连接就会失败。服务器证书中包含很多字段,其中包括:

  • Web 站点的名称和主机名;

  • Web 站点的公开密钥;
    • 签名颁发机构的名称;
    • 来自签名颁发机构的签名。

浏览器收到证书时会对签名颁发机构进行检查。如果这个机构是个很有权威的公共签名机构,浏览器可能已经知道其公开密钥了(浏览器会预先安装很多签名颁发机构的证书)。这样,就可以验证签名了。


放大招:具体握手过程

(SSL的加密过程是RSA与AES混合进行的。简单概括一下,就是通过RSA加密方式来交换AES加解密的密钥,然后使用AES加密的方式来传输报文。)

第一步:

有客户端发起的第一次握手,此次握手过程的主要目的是从服务端获取数字签名证书,服务端在发送数字签名证书之前要先确认客户端的SSL版本、加密算法等信息。------第一步用到数字证书

客户端(浏览器)的"证书管理器",有"受信任的根证书颁发机构"列表。客户端会根据这张列表,查看解开数字证书的公钥是否在列表之内。如果数字证书记载的网址,与你正在浏览的网址不一致,就说明这张证书可能被冒用,浏览器会发出警告。

第二步:

完成第一次握手后,接着进行第二次握手。第二次握手是在客户端收到证书后发起的,主要目的是将AES加解密使用的Key (Pre-master secret)发送给服务端。当然这个AES_KEY是使用第一次握手获取的公钥进行加密的。客户端收到这个使用公钥加密后的AES_KEY,使用服务端的私钥进行解密。这样客户端和服务端经过二次握手后都持有了AES加解密的KEY。———第二步进行数字签名验证。

参考下面的图理解啊!!老哥们~(我说的第二步可以看成下图中2和3)


第二步包括数字签名过程,也就是RSA算法验证过程。(这个过程比较艰难,如果一时没法理解,谷歌一下相关知识。或者请留言前提是你已经研究了一小时了还是一知半解


节点 A 将变长报文提取为定长的摘要 节点(把A看成浏览器也就是客户端)

A 对摘要应用了一个“签名”函数,这个签名函数就是数字证书里面约好的。这个函数会将用户的私有密钥作为参数。 因为只有用户B(服务器)才知道私有密钥,所以正确的签名函数会说明签名者就是其所有者。 在图中,由于解码函数 D 中包含了用户(服务器)的私有密钥,所以我们将其作为签名函数使用(RSA 加密系统将解码函数 D 作为签名函数使用,是因为 D 已经将私有密钥作为输入使用了。注意, 解码函数只是一个函数,因此,可以将其用于任意的输入。同样,在 RSA 加密系统中,以任意顺序 应用 D 和 E 函数时,两者都会相互抵消。因此 E(D(stuff)) = stuff,就像 D(E(stuff)) = stuff 一样) 注意:这里请用工程思想去理解,也就是私有密钥作为参数这句话,只有服务器才知道私有密钥。


一旦计算出签名,节点 A 就将其附加在报文的末尾,并将报文和签名都发送给B 在接收端,如果节点 B 需要确定报文确实是节点 A 写的,而且没有被篡改过, 节点 B 就可以对签名进行检查。节点 B 接收经私有密钥扰码的签名,并应用了 使用公开密钥的反函数。如果拆包后的摘要与节点 B 自己的摘要版本不匹配,要 么就是报文在传输过程中被篡改了,要么就是发送端没有节点 A 的私有密钥(也 就是说它不是节点 A)

用大白话说:这个过程就是验证A就是浏览器,用户就是服务器。而不是中间者(或者黑客)。浏览器知道数字证书上的签名函数,对发送的报文生成一个非常小的摘要信息。那么这个信息就是唯一不可改变的信息。服务器收到后用公开密钥(当然应用了私有密钥)得到报文摘要C。然后自己再用同样的签名函数对明文得到报文摘要D。如果C==D,说明验证成功。否则就是有问题的。

当你看到这里说明你已经成功70%了!!!


第三步:

当Client与Server端都持有AES_KEY后,就可以对HTTP报文进行加解密了。这里就不再是RSA了,而是使用对称加密,就算被第三方劫持,第三方也不知道密码。除非其中一个人把密码告诉第三方。这里使用对称加密也是为了提高HTTPS的性能。因为本身HTTPS所消耗的时间也是不可忽视的。我可以看一下掘金的用例:


通过代理以隧道形式传输安全流量

CONNECT 方法请求隧道网关创建一条到达任意目的服务器和端口的 TCP 连接,并 对客户端和服务器之间的后继数据进行盲转发。 

客户端通常会用 Web 代理服务器代表它们来访问 Web 服务器。比 如,很多公司都会在公司网络和公共因特网的安全边界上放置一个代理。代理是防火墙路由器唯一允许进行 HTTP 流量交换的设备,它可能会进行 病毒检测或其他的内容控制工作。但只要客户端开始用服务器的公开密钥对发往服务器的数据进行加密,代理就再也 不能读取 HTTP 首部了!代理不能读取 HTTP 首部,就无法知道应该将请求转向何 处了。

为了使 HTTPS 与代理配合工作,要进行几处修改以告知代理连接到何处。一种常 用的技术就是 HTTPS SSL 隧道协议。使用 HTTPS 隧道协议,客户端首先要告知代 理,它想要连接的安全主机和端口。这是在开始加密之前,以明文形式告知的,所 以代理可以理解这条信息。

 HTTP 通过新的名为 CONNECT 的扩展方法来发送明文形式的端点信息。CONNECT 方 法会告诉代理,打开一条到所期望主机和端口号的连接。这项工作完成之后,直接 在客户端和服务器之间以隧道形式传输数据。CONNECT 方法就是一条单行的文本命 令,它提供了由冒号分隔的安全原始服务器的主机名和端口号。host:port 后面跟 着一个空格和 HTTP 版本字符串,再后面是 CRLF。接下来是零个或多个 HTTP 请 求首部行,后面跟着一个空行。空行之后,如果建立连接的握手过程成功完成,就可以开始传输 SSL 数据了。

It's over。

是不是特别详细咩~欢迎指出不正之处!