生成自签名根证书

环境

  • mac 10.13.6, LibreSSL 2.2.7

前言

对于数字签名、证书、CA、Https的相关概念一直都很混乱.参考了相关资料后,并记录.

  • 公钥、私钥

    用于对数据进行加密、解密.

  • 摘要(digest)、数字签名(signature)

    摘要,是对数据进行hash运算后的数据; 数字签名(signature),使用公(私)钥对摘要进行加密后的数据.

  • CA(Certificate Authority)证书中心、数字证书(Digest Certificate)

    CA(证书中心)用自己的私钥,对用户公钥、用户个人信息进行加密,生成数字证书(Digest Certificate).

  • SSL握手过程

    • 客户端向服务器发请求,请求证书

    • 服务器把证书发给客户端

    • 客户端一般会有大部分CA的公钥,客户端收到证书后,检查该颁发者是否是客户端认可的CA,如果是,就用该CA的公钥解密数字签名,然后再计算

      证书中的”公钥和证书信息“的hash值,比较两者,如果相同,那就说明该证书没有被人篡改过,而且是该CA机构颁发的。当然,还会进行其它验证,
      如证书的common name与http request header中的host(不包括端口)是否相同,等等,如果有哪项检查不通过,会有告警,如果所有检查通过,
      那进入下一步。

    • 客户端生成对称密钥,用证书中的公钥加密,发给服务器

    • 服务器收到对称密钥后保存,给客户端一个应答。

    • 客户端接收响应,这样就完成了SSL连接,后面的通信用对称密钥加密数据传输。

      因为非对称加密相对对称加密来说比较耗时,所以正式的数据传输是用对称加密算法。非对称加密只是用于建立SSL时对称密钥的安全传输。我们可以设置

HTTPS长连接,这样建立好SSL+HTTP连接后,可以用这个连接发多次HTTPS请求,而不用每次请求都建立连接。

生成证书

详细信息参考req

1
2
3
4
5
6
7
8
9
10
11
12
13
# 生成一个RSA私钥,1024是加密强度,一般是1024或2048 
$ openssl genrsa -out private.key 2048

# 生成一个证书请求
$ openssl req -new -key private.key -out cert_req.csr

# 自己签发证书,如果要权威CA签发的话,要把cert_req.csr发给CA
$ openssl x509 -req -days 3650 -in cert_req.csr -signkey private.key -out server_cert.crt
只需要两处填写就行,其他都不填.
...
Common Name (eg, fully qualified host name) []:这里填域名
...
A challenge password []:密码
  • 使用自签名脚本
1
2
3
4
5
6
7
$ ./gencrt.sh 
输入域名和密码即可,这里输入域名gitlab.example.com,则生成以下4个文件
gitlab.example.com.crt:自签名的证书
gitlab.example.com.csr:证书的请求
gitlab.example.com.key:不带口令的Key
gitlab.example.com.origin.key:带口令的Key
只要使用.crt和com.key即可.

Nginx使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 启动nginx
$ docker run --name mynginx -p 8080:80 -d nginx
# 拷贝nginx的配置文件到本地,并重命名文件夹为conf
$ docker cp mynginx:/etc/nginx /opt/nginx
$ mv /opt/nginx/nginx /opt/nginx/conf/certs下
# 删除容器
$ docker rm -f mynginx
# 拷贝密钥到/opt/nginx/conf/certs下
$ cp gitlab.example.com.crt gitlab.example.com.key /opt/nginx/conf/certs
# 设置证书.在配置文件最后添加内容.
$ vim /opt/nginx/conf/conf.d/default.conf
server {
listen 443 ssl;
server_name localhost;

ssl on;
ssl_certificate /etc/nginx/certs/gitlab.example.com.crt;
ssl_certificate_key /etc/nginx/certs/gitlab.example.com.key;

ssl_session_timeout 5m;

ssl_ciphers HIGH:!aNULL:!MD5;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
# 启动
$ docker run --name mynginx -v /opt/nginx/conf:/etc/nginx -p 8080:80 -p 8081:443 -d nginx
# 浏览器验证即可.

参考

附录

自签名脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
$ vim gencrt.sh
#!/bin/sh
# create self-signed server certificate:
read -p "Enter your domain [www.example.com]: " DOMAIN

echo "Create server key..."

openssl genrsa -des3 -out $DOMAIN.key 2048

echo "Create server certificate signing request..."

SUBJECT="/C=US/ST=Mars/L=iTranswarp/O=iTranswarp/OU=iTranswarp/CN=$DOMAIN"

openssl req -new -subj $SUBJECT -key $DOMAIN.key -out $DOMAIN.csr

echo "Remove password..."

mv $DOMAIN.key $DOMAIN.origin.key
openssl rsa -in $DOMAIN.origin.key -out $DOMAIN.key

echo "Sign SSL certificate..."

openssl x509 -req -days 3650 -in $DOMAIN.csr -signkey $DOMAIN.key -out $DOMAIN.crt

echo "TODO:"
echo "Copy $DOMAIN.crt to /etc/nginx/ssl/$DOMAIN.crt"
echo "Copy $DOMAIN.key to /etc/nginx/ssl/$DOMAIN.key"
echo "Add configuration in nginx:"
echo "server {"
echo " ..."
echo " listen 443 ssl;"
echo " ssl_certificate /etc/nginx/ssl/$DOMAIN.crt;"
echo " ssl_certificate_key /etc/nginx/ssl/$DOMAIN.key;"
echo "}"
坚持原创技术分享,您的支持将鼓励我继续创作!
Fork me on GitHub