Skip to content

HTTPS是如何做到安全的 #1

Description

@Phieo

HTTPS是如何做到安全的

HTTPS对消息进行加密这是毫无疑问的,那是怎么加密的呢?客户端和服务端要对彼此的加密消息能够解密必须要约定好共用的秘钥,那共用的秘钥怎么约定呢?如果是服务器直接返回给客户端或者客户端直接通知给服务器,都有可能被中间人给劫持,显然直接传输秘钥的方式是不对的。HTTPS采用了非对称加密的方式(公开秘钥),即所有客户端都可以获取到公钥,但是私钥只能保存在服务器端。这样就不存在对称秘钥被劫持的问题啦。但随之而来的是是如何保证下发公钥的安全呢?这里就有一个问题:中间人攻击。

中间人攻击:

1.客户端发起ssl握手时中间人就开始劫持用户的请求并向目标服务器发起伪造的ssl握手,在服务器返回公钥时,中间人将服务器返回的公钥保存并自己伪造一对公钥和私钥,把自己伪造的私钥发送给客户端。

2.客户端拿到中间人伪造的公钥钥后开始加密信息,在发送给服务器过程中被中间人劫持并且用私钥解密,然后再通过之前保存的正确的公钥加密信息发送服务器,服务器拿到消息后用私钥解密后再返回用私钥加密过的信息,这时中间人又用之前截获的公钥解密信息。
这样中间人就能获得客户端和服务器之前所有的通信信息。不能保证信息的安全。

那怎么解决中间人攻击呢?聪明的前辈们想出了用数字证书的方式,就是对公钥进行一次数字签名。那么问题来了,数字签名是怎么一回事呢?简单来说,数字签名是公钥解密的逆应用:用私钥加密,用公钥解密。具体过程如下:

生成数字签名:

1.对消息进行哈希计算,得到哈希值即将变长的报文提取为定长的摘要

2.用私钥对哈希值进行加密,生成签名

3.将签名附属在消息后面,一起发送

验证签名:

1.取到消息已经附属在后面的签名

2.用公钥对签名进行解密取到HASH1

3.用同样的哈希算法对消息进行哈希计算,得到HASH2

4.比较HASH1和HASH2,如果相同就证明消息未被篡改以及发消息的人确实是那个持有私钥的人

看完了数字签名的含义回过头来再来看下证书是如何保证公钥的安全可靠的:

产生证书:

1.服务器将公钥A给CA(cert authority)

2.CA用自己的私钥B(上一级证书的私钥)对公钥A进行加密生产数字签名A

3.CA把公钥A、数字签名A、web站点的名称和主机名、签名颁发机构的名称整合在一起生成证书,发回服务器

验证证书:

1.客户端得到证书

2.客户端从操作系统中找到证书的上一层证书并得到公钥B,与上一环节的私钥B是一对

3.公钥B对数字签名A进行解密得到HASH1

4.客户端对公钥A进行HASH计算得到HASH2

5.如果HASH3===HASH4则证明证书有效,从而证书上带有的公钥A也是有效的

如何确保证书的校验的可靠呢?

每一层的证书有效性都是靠上一层的证书进行验证,而根证书是自签名的,就是说根证书是确保自己是有效的,一般根证书都是预先安装在操作系统中的,基本能保证其安全,但是世界上没有绝对的安全。

verify signature

数字证书+非对称加密能保证数据的安全,但是由于非对称加密比较耗费CPU计算,HTTPS在后续传输数据时依旧是用双方约定的协商秘钥进行对称加密。HTTPS的做法是在验证证书的有效性后,客户端用公钥加密计算协商秘钥用的重要参数Pre-master,服务器用私钥解密Pre-master,客户端和服务器用同一套算法以及同样的参数计算出协商秘钥,然后采用协商秘钥对传输的数据进行对称加密。数字证书+非对称加密+协商秘钥加密确保了HTTPS通信的安全与效率。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions