美文网首页
HTTPS 原理与小战

HTTPS 原理与小战

作者: Robin92 | 来源:发表于2020-08-28 17:18 被阅读0次

    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 端的数据是正确的,且还可以解密这个数据。那问题就在 如何传递公钥 了。

    这里引入一个第三方。

    我们这样约定:

    • 第三方用一个 签名算法 (Hash 算法)将 Server 的公钥 及 Server 的一些信息签名得到 摘要
    • 第三方用 第三方的私钥 将摘要加密,得到 数字签名
    • 第三方将这个 数字签名摘要签名算法 以及 服务的公钥和信息作为 证书 颁发给服务端

    Server 可以将这个证书出示给别人,来证明自己的身份。比如颁发给 Client 端

    • Client 端用 第三方的公钥 将证书中的 数字签名 解密得到 摘要
    • Client 端用证书中的 签名算法 重新算一下 Server 的公钥和其他信息,得到新的 摘要
    • 此时,将自己生成的 摘要 与证书中包含的对比,如果一致,则证明是 Server 下发的公钥

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

    HTTPS颁发证书和验证证书过程

    HTTPS 四次握手

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

    四次握手

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

    假设中间人拦截到了证书,可以拿到 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...:
                        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:...
             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


    相关文章

      网友评论

          本文标题:HTTPS 原理与小战

          本文链接:https://www.haomeiwen.com/subject/ubdjsktx.html