HTTPS 原理与小战

Robin92 · · 1476 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

HTTPS 原理与小战

实事求是,不敢写实战,还是改成小战吧。

原理

HTTP + SSL (Secure Socket Layer)

一次浏览器访问,当访问 baidu.com 时浏览器自动添加 schema http:// 和 端口 :80
这个过程它可能会走这样的路线: 操作系统 -> 路由器 -> ISP -> 电信/联通 -> 城市出口 -> 海底光缆 -> ... -> 联通/电信 -> ISP -> 路由器 -> Server,这个过程中的每一个网元都有风险。
这就像本地写了一个浏览器的代理,可以抓到任何访问的请求。

要解决的问题:

  • C/S 之间的访问加密,让中间网元只传输加密的数据,无法解密(所以要传递密钥)
  • 加密需要密钥,传递密钥也应该保密

加密技术

主要有 对称加密算法、非对称加密算法、Hash 算法(摘要算法)。

对称加密算法

常见的有 des、3des(三次 des)、AES、凯撒加密(移位)。(参考百科)

对称加密算法是对称的,即,有对应的解密方法,参数 密钥(相当于盐,掺进数据中)可以影响加密的结果。

非对称加密算法

有两个密钥——公钥和私钥。他们的关系有以下原则:

  • 公钥加密的明文,可以用私钥解密
  • 私钥加密的明文,可以用公钥解密
  • 公钥加密的明文,用公钥不能解密
  • 公钥是由私钥生成,且要保证一对多关系

存在的问题:

  • 上述特点可以实现 单向 的信息保密,由原则第三条,所以持有公钥发出去的数据是保密的,只能由私钥拥有者解开(原则第一条)且私钥拥有者只有一方(原则第四条)。
  • 由问题第一条,可以试想在客户端也拥有自己的私钥/公钥对,将公钥发给服务端,以此来实现 “双向 保密”。但这样是不对的,因为原则第二条,所以非对称加密算法就不能传递数据。
  • 由上述问题第一条、第二条,只用非对称加密算法不能保证数据的保密,但它 单向保密 的用处却很实用,可以用它来协商 密钥,由密钥再去而数据做数据加密进行传输。(所以 TLS 只是建链,数据仍是 http 80 端口传输)。
  • 还有一个问题就是 中间人 问题,中间人相当于代理,对接客户端时用一对公私钥,对接服务端用另一对公私钥,C/S 无法确认对端是谁,所以还是不安全。

问题的解决:

  • 问题第三条中

浏览器中的证书: Internet 属性 - 内容 - 证书
证书从哪里来的: 装上系统就有,公钥是内置在操作系统中的

Hash 算法

Hash 算法可以将数据(入参)映射到一个 固定长度 的值,且一对一映射,无法反向解 Hash 的。

由它,就有了数字签名。就是用 Hash 算法来做数字签名。 Hash算法(公钥) = hash 公钥的签名/摘要。它的作用只是在 证伪,就是说如果发现某一个数据变了,就证明它被篡改了。

如何保证数据传输的保密性

在非对称加密算法中我们介绍了,数据传输中,只要 Server 的公钥能正确到达 Client 端,Client 端就能验证 Server 端的数据是正确的,且还可以解密这个数据。那问题就在 如何传递公钥 了。

这里引入一个第三方。

我们这样约定:

  • Server 端用 第三方的私钥 将自己的 (Server 的)公钥 加密,即得到 密文
  • 同时,Server 端用 Hash 算法将 自己的 (Server 的)公钥 签名一下,即生成 摘要
  • 同时,准备好自己的 签名算法

这样,由以上三者组成 证书,传递给 Client 端
Client 端拿到证书,也就得到了如上三个值:公钥的密文公钥摘要签名算法

  • Client 端用 第三方的公钥 将证书中的 密文 解密得到 Server 的公钥
  • Client 端用 签名算法 来 Hash 一下 公钥(Server 的),得到自己 Hash 生成的 公钥摘要
  • 此时,将自己 Hash 生成的 公钥摘要 与证书中包含的对比,如果一致,则证明是 Server 下发的公钥

那问题就是要确保第三方可信,这个第三方就是 CA,CA 已经保证自己持有私钥,而公钥下发给 Client。客户端的 CA 的公钥 是内置的(注意,不是 Server 的公钥)。

HTTPS 四次握手

浏览器访问 HTTPS -> 访问 Server 443 端口 -> 建立握手(应用层的四次握手)-> 收到数据后开始 HTTP 通信(80 端口)

四次握手

  • C->S Hello,我支持 xxx 对称加密算法
  • S->C Hello, 好的,我支持 xxx,给你证书 (这个证书是 Server 之前从 CA 申请下来存在 Server 端的,证书中包含自己的公钥、Server 摘要/签名、加密算法,另外还有有效期等)
  • C->S 好的,证书没问题,我看到 公钥 了,给你个随机数,我们之后用这个 密钥 这就是协商加解密
  • S->C OK,收到
  • C<->S 通过 密钥 做对称加密,开始通信

假设中间人拦截到了证书,可以拿到 Server 的公钥,还拦截到了密钥,但这样也无济于事,因为只有私钥可以解密看到密钥。
这其中:1. CA 的私钥是保密的;2. 证书中有签名服务器的名称,且正规 CA 机构保证了它的唯一性(法律问题),所以客户端知道对端是谁;3. 操作系统内置正规的 CA 机构,可以去验证证书。

HTTPS 绝对安全吗

问题一:当首次输入 jd.com 进行访问时,会进行多次 redirect, 第一次是 http://www.jd.com(默认访问 http), 第二次是到 https://www.jd.com(服务器主动 redirect)。如果黑客直接写一个假的 www.jd.com 的钓鱼网站,便可以实现拦截。

实战

OpenSSL 生成证书及自签名

OpenSSL 中用到的名词:

  • Key,私钥
  • CSR,Certificate Signing Request,证书签名请求文件的文件后缀。这个文件相当于用私钥生成的公钥,这个公钥需要被签名。
  • CRT,证书

生成服务器私钥

中间会让你输入一个密码(或者说盐值),用于生成私钥

$ openssl genrsa -des3 -out server.key
Generating RSA private key, 2048 bit long modulus (2 primes)
......................................................................+++++
...........+++++
e is 65537 (0x010001)
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key:

生成待签名证书

中间要求输入私钥的密码,以及签名信息。

$ openssl req -new -key ./server.key -out pub.csr
Enter pass phrase for ./server.key: # 输入私钥的密码
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
----- # 根据提示输入服务信息
Country Name (2 letter code) [AU]: # 签署人信息
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []: # 这里一般天请求人的服务器域名
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

查看待签名证书

查看待签名证书中的内容

$ openssl req -text -in pub.csr -noout
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:b9:ee:ff:01:25:7d:49:2f:37:ea:fe:fb:77:e2:
                    79:db:47:b2:da:33:83:06:25:ed:e2:1e:e9:c0:74:
                    fc:b6:f9:50:b7:88:b8:5b:43:44:f0:1d:a7:f4:25:
                    79:ca:28:f8:29:2e:c7:b8:a3:11:7f:e4:8d:7a:f5:
                    21:60:8b:11:a9:42:ec:1d:96:89:a8:5b:40:f0:1a:
                    a9:7d:f3:80:b6:53:4a:26:cd:6d:cd:8c:9f:3c:08:
                    89:5c:89:03:52:ab:8c:0a:d8:e9:46:17:28:3c:e8:
                    be:30:2b:7d:d5:5c:72:7f:07:be:18:e4:98:a3:86:
                    97:d5:54:87:a5:b7:6a:7a:cf:c3:74:46:a3:2a:dc:
                    15:3e:04:61:f4:b6:f7:7d:df:d8:49:86:1c:e2:ff:
                    4e:aa:2d:72:2a:4c:9d:de:b9:4a:2f:5a:da:5e:7a:
                    90:c3:80:c6:d6:e8:b7:f8:ef:e5:c7:03:80:8d:91:
                    8a:84:ef:af:cd:0b:6e:a4:9c:17:4b:2e:43:44:04:
                    56:fd:20:2a:77:27:ab:95:1d:b4:b4:f7:54:de:c5:
                    2a:56:9d:a3:f5:fc:65:e4:46:7a:1f:1c:93:8a:9c:
                    14:33:33:05:31:54:60:47:ee:8f:13:d8:fa:b1:2c:
                    b2:ca:7c:c7:db:d2:2e:82:e8:3d:f5:87:26:96:08:
                    08:65
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: sha256WithRSAEncryption
         25:d9:ff:94:f0:8a:93:73:d5:18:73:9d:8f:71:80:ed:9e:38:
         fb:ad:d5:e1:54:8c:73:76:b4:0b:4d:21:67:ee:c9:e6:ef:73:
         88:cf:42:74:36:b4:bb:7c:4a:bb:41:7a:75:71:8a:6d:68:14:
         47:f9:41:8e:83:19:f8:f7:bf:9b:9e:7a:af:4f:db:3e:dc:b5:
         ef:8a:6a:a1:17:49:50:7b:53:73:54:42:e9:13:ee:7c:87:c0:
         7e:1c:42:2a:70:7f:74:5b:b1:a3:e0:29:a7:82:86:17:38:d3:
         9b:74:9d:b1:b2:e2:b1:c8:54:b6:21:a6:28:ce:5e:5e:0b:b0:
         11:0f:02:16:81:e3:1a:23:a7:8e:eb:54:59:6c:e5:80:d5:72:
         4e:32:94:64:38:ce:17:07:6f:81:c3:88:00:37:14:36:c4:a3:
         ea:73:51:d0:eb:92:31:72:45:4c:a8:22:9a:5c:ea:c5:26:6d:
         f5:ce:e5:e1:7e:e2:e9:51:84:1e:02:8c:f7:ee:05:f5:d0:8b:
         85:67:23:8d:e3:8f:0d:94:b9:d0:76:51:8c:45:98:c2:f7:06:
         89:fc:0b:2c:44:79:cb:a8:60:06:c4:64:8b:04:24:de:c9:eb:
         03:aa:dc:57:a1:3b:dd:11:8e:65:5a:fd:97:a5:d3:3e:94:ac:
         8e:df:32:87

由于签名请求需要 CA 来做,所以我们要搞一个 CA,这就是自建 CA

自建 CA

  • 先生成一个 CA 的私钥
openssl genrsa -out ca.key
  • 生成一个签名请求
openssl req -new -key ca.key -out ca.csr
  • 生成 CA 根证书

x509 是个协议,传入私钥以及签名请求。此时就生成了 CA 的根证书。

$ openssl x509 -days 365 -req -in ca.csr -extensions v3_ca -signkey ca.key -out ca.crt
Signature ok
subject=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
Getting Private key

这里是自建 CA,上节之前是生成的服务器的私钥和签名请求。有了 CA 之后,下面可以继续对服务器进行签名。

windows 上查看根证书
可以在开始菜单右键“运行”菜单中输入 certmgr.msc 参考

安装根证书
双击根证书,安装到 受信任的根证书颁发机构。(安装后的效果:浏览器不会再拦截此 https 请求的访问,但在浏览器 url 上会显示红色 不安全 三个字)

对服务器签名请求进行签名

  • pub.csr 是 服务端的待签名文件
  • ca.key 是 CA 的私钥
  • ca.crt 是 CA 的证书
  • 签名后的服务器的签名文件是 server.crt
$ openssl x509 -days 365 -req -in ./pub.csr -extensions v3_req -CAkey ca.key -CA ca.crt -CAcreateserial -out server.crt
Signature ok
subject=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
Getting CA Private Key

Nginx 配置 Https

最简单的配置

server {
    listen 443 ssl;
    server_name xx.com;
    ssl_certificate /path/to/server.crt;
    ssl_certificate_key /path/to/server.key;
}

重启服务: service openresty restart


参考


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:Robin92

查看原文:HTTPS 原理与小战

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1476 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传