自签名证书与Nginx配置Https证书

发布时间 2024-01-03 11:06:53作者: 羊37

0.背景

公私钥、证书体系、Https等基础知识。

这个之前有写过ppt,空了我编辑成文章传上来,再更新这里。

1.密钥及证书角色

区分自签名证书和CA签名证书

自签名:根证书是自己的私钥签名的,意味着它是由相应的私钥持有者(即CA本身)签发的,而不是由另一个CA签发。

1.1 CA

以RSA为例

该环节,模拟自己作为CA,生成ca的私钥和根证书。

1.1.1 私钥生成

openssl genrsa -out ca-private.key 2048

genrsa:生成 RSA 密钥的 OpenSSL 命令。
-out server.key:指定生成的私钥文件名为 server.key。
2048:指定密钥的位数,通常为 2048 位。

1.1.2 根证书生成

openssl req -new -x509 -key ca-private.key -out ca.crt -days 3650

req:执行证书请求和生成证书操作的 OpenSSL 子命令。
-new:创建一个新的证书请求 (CSR)。
-x509:生成自签名的 X.509 证书,而不仅仅是 CSR。
-key server.key:指定用于生成证书的私钥文件。
-out ca.crt:指定生成的自签名根证书文件名为 ca.crt。
-days 3650:指定证书的有效期,这里设置为 3650 天(大约 10 年)。

1.1.3 总结

image-20231215165335565

image-20231215165354376

1.2 用户

1.1.1 私钥生成

openssl genrsa -out user-private.key 2048

1.2.2 生成请求文件CSR

这个玩意有时候也叫p10文件

openssl req -new -key user-private.key -out user.csr

req:执行证书请求操作的 OpenSSL 子命令。
-new:创建一个新的证书请求 (CSR)。
-key server.key:指定用于生成 CSR 的私钥文件。
-out server.csr:指定生成的 CSR 文件名为 server.csr。

制作csr的时候,一般在Common Name处输入我们的域名。

Common Name (e.g. server FQDN or YOUR name) []:example.com

1.2.3 总结

image-20231215174428976

image-20231215165518380

3.CA签发用户证书

1.3.1 签发证书

无非就是私钥给我们的csr文件签名下

openssl x509 -req -days 3650 -in user.csr -CA ca.crt -CAkey ca-private.key -CAcreateserial -out user.crt

x509:执行 X.509 证书操作的 OpenSSL 子命令。
-req:指定输入文件为 CSR。
-days 3650:指定生成的服务器证书的有效期,这里设置为 3650 天(大约 10 年)。
-in server.csr:指定输入的 CSR 文件。
-CA ca.crt:指定用于签名 CSR 的根证书文件。
-CAkey server.key:指定用于签名 CSR 的根证书的私钥文件。
-CAcreateserial:指定在生成证书时创建序列号文件。

1.3.2 总结

经过签发后,我们就有了一个证书文件user.crt

image-20231215174620902

2.Nginx配置(服务端)

https最开始的步骤,就是握手前问服务器要下证书,然后通过本地根证书验证下这个证书靠谱不。

然后,证书验证通过,利用这个可信的“公钥证书”来与服务器构建会话密钥。

所以,作为nginx服务器,配置证书时,我们应该要做这2个事情。

  • 将私钥对应的公钥证书返回给客户端
  • 配置私钥文件,用于解密客户端发送的“公钥证书加密“的数据包。

2.1 配置

2.1.1 linux

        #ssl
        server {
        #SSL 访问端口号为 443
        listen 443 ssl;
        #填写绑定证书的域名
        server_name yang37.cn;
        #证书文件路径
        ssl_certificate /etc/nginx/key/ssl/user.crt;
        #私钥文件路径
        ssl_certificate_key /etc/nginx/key/ssl/user-private.key;
        ssl_session_timeout 5m;
        #请按照以下协议配置
        ssl_protocols TLSv1.2 TLSv1.3;
        #请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
        ssl_prefer_server_ciphers on;

        location / {
           #网站主页路径。此路径仅供参考,具体请您按照实际目录操作。
           #例如,您的网站运行目录在/etc/www下,则填写/etc/www。
            root html;
            index  index.html index.htm;
        }
    }

2.1.2 windows

	#ssl
    server {
        #SSL 访问端口号为 443
        listen 443 ssl;
        #填写绑定证书的域名
        server_name yang37.cn;
        #证书文件路径
        ssl_certificate D:/Software/nginx/nginx-1.22.1/cert/user.crt;
        #私钥文件路径
        ssl_certificate_key D:/Software/nginx/nginx-1.22.1/cert/user-private.key;
        ssl_session_timeout 5m;
        #请按照以下协议配置
        ssl_protocols TLSv1.2 TLSv1.3;
        #请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
        ssl_prefer_server_ciphers on;

        location / {
           #网站主页路径。此路径仅供参考,具体请您按照实际目录操作。
           #例如,您的网站运行目录在/etc/www下,则填写/etc/www。
            root html;
            index  index.html index.htm;
        }
    }

2.2 重载ng

nginx -s reload

2.3 验证

此处使用nginx在win下配置了刚才的证书,本地访问https://127.0.0.1

可以看到已经能够通过https正常访问了。

image-20231215170909651

那么,为啥浏览器提示不安全呢?因为证书是我们自己生成的,可信任根证书里没有我们自己作为CA时的根证书。

当然可以手动操作下,导入就好了,参照3.4、3.5节。

3.扩展

3.1 私钥文件加密

生成私钥时,可以使用对称算法加密私钥,这样私钥就不能直接使用,而是需要输入密码。

# 生成加密的rsa私钥,长度为2048
openssl genrsa -des3 -out server.key 2048

genrsa:生成 RSA 密钥的 OpenSSL 命令。
-des3:使用 DES3 算法加密私钥,需要输入至少四位密码。
-out server.key:指定生成的私钥文件名为 server.key。
2048:指定密钥的位数,通常为 2048 位。

image-20231215151638705

通过此种方式生成出来的私钥,是通过des3加密了的,打开生成的文件可以看到ENCRYPTED标记。

image-20231215152653550

既然加密了,使用的时候肯定需要使用密码操作。如果想要方便,执行下方命令。

openssl rsa -in server.key -out server.key

image-20231215152823157

这样私钥使用时就不再需要输入密码了。

image-20231215152832166

3.2 CSR文件是啥

csr就是公钥带着刚才那堆备注信息而已,可以在这个网站解析csr文件。

CSR查看

image-20231215154655844

公钥和证书的差别就是证书额外多了个CA签发,其实可以推断,CA无非就是拿着自己的私钥给我们这个csr签名下而已。

3.3 签发后咋多出来一个srl文件

多出来了个srl文件,这个就是证书的序列号信息,签发的证书里面可以看到是一样的。

这个序列号当作唯一id就好了,每个证书都不一样。

image-20231215174641129

3.4 关于自签名证书的问题

上面的演示中,可以发现服务端只是导入了用户私钥user-private.key和用户证书user.crt,可以看到服务端根本都没有上传过根证书ca.crt

那么问题来啦:如果服务器没有提供 CA 的根证书,客户端如何验证服务器证书的真实性?

  • 通常客户端并不需要服务器提供 CA 的根证书

    因为根证书应该已经预安装在客户端的操作系统或浏览器中。

    根证书通常是由全球信任的证书颁发机构提供的,这些机构的证书内置在客户端软件中。

    例如:win示例-所需的受信任根证书

    image-20231218103835302

  • 本例中使用的是自签名的根证书

    所以客户端必须事先知道并信任这个根证书才能验证服务器证书(user.crt)的真实性。

    如果客户端没有预先安装这个根证书,它将不能验证服务器证书,从而导致安全警告或拒绝建立连接。

  • 为了让自签名证书工作,必须手动将 CA 的根证书(ca.crt)安装到每个客户端设备上。

    这样,当 SSL 握手发生时,客户端可以使用已安装的根证书来验证服务器证书。

    在实际生产环境中,由于无法要求所有用户都安装自签名的根证书,因此通常会使用具有公信力第三方 CA 签发的证书。

3.5 win导入根证

win + r 打开命令框,输入certmgr.msc进入win证书管理器。

image-20231215171205762

找到受信任的根证书颁发机构,右键选择导入。

image-20231215172347044

找到我们刚才自己的ca根证,执行导入操作。

image-20231215172505419

image-20231215172515377

image-20231215172614083

导入完成后,可以看到我们的根证书。

image-20231215172705804