Home Archives Categories Tags

基于OpenSSL自建CA证书、二级CA证书和SSL证书

发布时间: 更新时间: 总字数:4458 阅读时间:9m 作者: 分享
专栏文章
  1. SSL/TLS原理详解
  2. 怎样查看计算机本地安装的证书
  3. 免费HTTPS证书Let's Encrypt安装教程
  4. 多域名(SAN/UCC)生成CSR操作指南
  5. 免费通配符/泛域名SSL证书申请
  6. 基于OpenSSL自建CA证书、二级CA证书和SSL证书(当前)

本文介绍基于OpenSSL自建CA证书、二级CA证书和SSL证书。

基础知识

OpenSSL工具介绍

openssl是一个开源程序的套件、这个套件有三个部分组成:

  • 一是libcryto,这是一个具有通用功能的加密库,里面实现了众多的加密库;
  • 二是libssl,这个是实现ssl机制的,它是用于实现TLS/SSL的功能;
  • 三是openssl,是个多功能命令行工具,它可以实现加密解密,甚至还可以当CA来用,可以让你创建证书、吊销证书。

证书格式介绍

  • .key文件:私钥文件,如ca.key
  • .crt文件:数字证书(Digital Certificate)文件,如ca.crt
  • .bundle.crt文件:最终在NGINX上配置的数字证书文件,通常包含两部分,如:<domain>.crtca.crt
  • .chain.crt文件:证书链文件
  • .srl文件:openssl ca签名过程中产生的Serial Number存放的文件
  • .csr文件:证书签名请求(Certificate Signing Request)文件,如all.xiexianbin.cn.csr

非对称加密算法

非对称加密算法需要两个密钥:

  • 公开密钥(publickey)简称公钥
  • 私有密钥(privatekey)简称私钥
  • 公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密;私钥仅有一把,但公钥可以是多个
  • 私钥加密的内容,所有公钥都能解开
  • 公钥加密的内容,只有私钥才能解开

CA

证书颂发机构(Certificate Authority,缩写:CA)是指一个中心化的,可信任的证书颁发机构

数字证书

数字证书(Digital Certificate),使用CA私钥加密(拥有者信息、公钥信息和拥有者公钥)得到的数据,即是数字证书

PKI

公钥基础设施(Public Key Infrastructure,缩写:PKI),用来实现基于公钥密码体制的密钥和证书的产生、管理、存储、分发和撤销等功能。

X.509

X.509是国际电信联盟针对PKI制定的标准RFCs

一个X.509 v3版本的数字证书包含的结构如下:

  • Version - 必须是v3
  • Serial Number - 每个证书都有唯一的序列号
  • Algorithm ID - 算法ID,与底下的证书签名算法必须一致
  • Issuer - 发行者
  • Validity - 指明有效期
  • Subject - 拥有者的相关信息,如 C=CN, ST=Henan, L=Zhengzhou, ... CN=*.xiexianbin.cn
  • Subject public key info
  • Issuer Unique Identifier (optional)
  • Subject Unique Identifier (optional)
  • Extensions (optional) - 拓展,尤其是Subject Alternative Name的拓展非常关键
    • Subject Key Identifier (optional)
    • Authority Key Identifier (optional)
    • Subject Alternative Name: 重要
      • 通配证书(Wildcard Certificates)指的是像*.xiexianbin.cn一类的证书
    • Basic Constraints (optional)
  • 证书签名算法(Certificate Signature Algorithm)如:SHA-256
  • 证书签名(Certificate Signature)

创建CA

签发一级CA证书

方法一:直接通过命令行签名

生成根密钥

openssl genrsa -out cakey.key 4096

为了安全起见,修改cakey.key私钥文件权限为600400,也可以使用子shell生成( umask 077; openssl genrsa -out cakey.key 4096 ),下面不再重复。

示例:

# openssl genrsa -out cakey.key 4096
Generating RSA private key, 4096 bit long modulus
.......................++
.........................................................................................................................................................................................................................................................................................................................++
e is 65537 (0x10001)

生成根证书

使用req命令生成自签证书:

openssl req -new -x509 -days 14610 -key cakey.key -out cacert.crt
  • 示例
# openssl req -new -x509 -days 14610 -key cakey.key -out cacert.crt
...
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Henan
Locality Name (eg, city) [Default City]:Zhengzhou
Organization Name (eg, company) [Default Company Ltd]:X Technology Co. Ltd.
Organizational Unit Name (eg, section) []:X Root CA Trust
Common Name (eg, your name or your server's hostname) []:X Root CA - R3
Email Address []:me@xiexianbin.cn

查看证书

openssl x509 -in cacert.crt -noout -text

生成SSL密钥

以上都是在CA服务器上做的操作,而且只需进行一次,现在转到nginx服务器上执行:

cd /etc/nginx/ssl
openssl genrsa -out all.xiexianbin.cn.key 2048

这里测试的时候CA中心与要申请证书的服务器是同一个。

生成证书签署请求

# openssl req -new -days 3650 -key all.xiexianbin.cn.key -out all.xiexianbin.cn.csr
...
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:ShangHai
Locality Name (eg, city) [Default City]:ShangHai
Organization Name (eg, company) [Default Company Ltd]:xiexianbin.cn
Organizational Unit Name (eg, section) []:IT
Common Name (eg, your name or your server's hostname) []:*.xiexianbin.cn
Email Address []:

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

同样会提示输入一些内容,其它随便,除了Commone Name一定要是你要授予证书的服务器域名或主机名,challenge password不填。

私有CA签署证书

接下来要把上一步生成的证书请求csr文件,发到CA服务器上,在CA上执行:

openssl ca -in all.xiexianbin.cn.csr -out all.xiexianbin.cn.crt
# 上面的命令生成的证书不能识别,试试下面的命令
openssl x509 -req -days 825 -in all.xiexianbin.cn.csr -CA /etc/pki/CA/cacert.crt -CAkey /etc/pki/CA/private/cakey.key -CAcreateserial -out all.xiexianbin.cn.crt

示例:

创建ext:all.xiexianbin.cn.ext

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment
subjectAltName=@alt_names
extendedKeyUsage=serverAuth
# crlDistributionPoints=URI:https://ca.xiexianbin.cn/crl.pem

[alt_names]
DNS.1 = xiexianbin.cn
DNS.2 = *.xiexianbin.cn
DNS.3 = kb.cx
DNS.4 = *.kb.cx
DNS.4 = localhost
# openssl x509 -req -days 825 -in all.xiexianbin.cn.csr -CA cacert.crt -CAkey cakey.key -CAcreateserial -out all.xiexianbin.cn.crt -extfile all.xiexianbin.cn.ext -sha256
Signature ok
subject=/C=CN/ST=Shanghai/L=Shanghai/O=xiexianbin.cn/OU=IT/CN=*.xiexianbin.cn/emailAddress=me@xiexianbin.cn
Getting CA Private Key

说明:

  • -days 必须少于 825 天,否则报错 NET::ERR_CERT_REVOKED

上面签发过程其实默认使用了-cert cacert.crt -keyfile cakey.key,这两个文件就是前两步生成的位于/etc/pki/CA下的根密钥和根证书。将生成的crt证书发回nginx服务器使用。

到此我们已经拥有了建立ssl安全连接所需要的所有文件,并且服务器的crtkey都位于配置的目录下。

验证生成的SSL证书

校验证书是否被 CA 证书签名:

# openssl verify -CAfile cacert.crt all.xiexianbin.cn.crt
all.xiexianbin.cn.crt: OK

生成bundle.crt

cat all.xiexianbin.cn.crt cacert.crt > all.xiexianbin.cn.bundle.crt

使用SSL证书

nginx配置

在nginx配置文件(可能是/etc/nginx/nginx.conf)的server指令下添加:

    ssl_certificate            /etc/nginx/conf.d/cert/all.xiexianbin.cn.bundle.crt;
    ssl_certificate_key        /etc/nginx/conf.d/cert/all.xiexianbin.cn.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl on;

同时注意 server_name 与证书申请时的 Common Name 要相同,打开443端口。当然关于web服务器加密还有其他配置内容,如只对部分URL加密,对URL重定向实现强制https访问,请参考其他资料。

访问域名问题

浏览器作为客户端去访问https加密的服务器,一般不用去手动做其他设置,如https://www.xiexianbin.cn,这是因为Chrome、FireFox、Safari、IE等浏览器已经内置了大部分常用的CA的根证书,但自建CA的根证书就不再浏览器的信任列表中,访问时会提示红色错误。

如果你要自己做CA,别忘了客户端需要导入CA的证书(CA的证书是自签名的,导入它意味着你“信任”这个CA签署的证书)。而商业CA的一般不用,因为它们已经内置在你的浏览器中了。

方法二:通过配置文件签名

上述方法是通过命令行,过程过于繁琐,可以使用配置文件进行签名

pki目录结构

CentOS上有关ssl证书的目录结构:

/etc/pki/CA/
            newcerts    存放CA签署(颁发)过的数字证书(证书备份目录)
            private     用于存放CA的私钥
            crl         吊销的证书
/etc/pki/tls/
             cert.pem    软链接到certs/ca-bundle.crt
             certs/      该服务器上的证书存放目录,可以房子自己的证书和内置证书
                   ca-bundle.crt    内置信任的证书
             private    证书密钥存放目录
             openssl.cnf    openssl的CA主配置文件

修改CA的一些配置文件

CA要给别人颁发证书,首先自己得有一个作为根证书,我们得在一切工作之前修改好CA的配置文件、序列号、索引等等。

vi /etc/pki/tls/openssl.cnf:

...
[ CA_default ]
dir             = /etc/pki/CA           # Where everything is kept
certs           = $dir/certs            # Where the issued certs are kept
crl_dir         = $dir/crl              # Where the issued crl are kept
database        = $dir/index.txt        # database index file.
#unique_subject = no                    # Set to 'no' to allow creation of
                                        # several ctificates with same subject.
new_certs_dir   = $dir/newcerts         # default place for new certs.
certificate     = $dir/cacert.crt       # The CA certificate
serial          = $dir/serial           # The current serial number
crlnumber       = $dir/crlnumber        # the current crl number
                                        # must be commented out to leave a V1 CRL
crl             = $dir/crl.pem          # The current CRL
private_key     = $dir/private/cakey.key # The private key
RANDFILE        = $dir/private/.rand    # private random number file
...
default_days    = 3650                  # how long to certify for
...
# For the CA policy
[ policy_match ]
countryName             = match
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
...
[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = CN
countryName_min                 = 2
countryName_max                 = 2
stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = Henan
...
[ req_distinguished_name ] 部分主要是颁证时一些默认的值,可以不动

一定要注意[ policy_match ]中的设定的匹配规则,是有可能因为证书使用的工具不一样,导致即使设置了csr中看起来有相同的countryName,stateOrProvinceName等,但在最终生成证书时依然报错:

Using configuration from /usr/lib/ssl/openssl.cnf
Check that the request matches the signature
Signature ok
The stateOrProvinceName field needed to be the same in the
CA certificate (GuangDong) and the request (GuangDong)
touch index.txt serial:

在CA目录下创建两个初始文件:

# touch index.txt serial
# echo 01 > serial

签名:

openssl ca -config /etc/pki/tls/openssl.cnf -out all.xiexianbin.cn.crt -in all.xiexianbin.cn.csr -extfile all.xiexianbin.cn.cnf -batch

签发中级CA证书

生成二级CA密钥

# openssl genrsa -out secondcakey.key 4096
Generating RSA private key, 4096 bit long modulus
......................++
.......................................................................................................................................................................++
e is 65537 (0x10001)

生成二级CA证书签名请求(CSR)

使用req命令生成自签证书:

# openssl req -new -key secondcakey.key -out secondcsr.csr
...
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Henan
Locality Name (eg, city) [Default City]:Zhengzhou
Organization Name (eg, company) [Default Company Ltd]:X Technology Co. Ltd.  ## 务必确保Organization Name与根CA证书相同
Organizational Unit Name (eg, section) []:X Authority
Common Name (eg, your name or your server's hostname) []:X Authority - R3
Email Address []:me@xiexianbin.cn

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

生成二级CA证书

创建ext:secondcert.ext

basicConstraints=CA:true
crlDistributionPoints=URI:https://ca.xiexianbin.cn/crl.pem
# openssl x509 -req -days 7305 -CA cacert.crt -CAkey cakey.key -CAcreateserial -in secondcsr.csr -out secondcacert.crt -extfile secondcert.ext -sha256
Signature ok
subject=/C=CN/ST=Henan/L=Zhengzhou/O=X Technology Co. Ltd./OU=X Root CA Trust/CN=X Authority - R3/emailAddress=me@xiexianbin.cn
Getting CA Private Key

同样会提示输入一些内容,其它随便,除了Commone Name一定要是你要授予证书的服务器域名或主机名,challenge password不填。

验证二级CA证书

# openssl verify -CAfile cacert.crt secondcacert.crt
secondcacert.crt: OK

生成证书链文件

cat secondcacert.crt cacert.crt > secondcacert.chain.crt

使用二级CA证书签名

# openssl x509 -req -days 825 -in all.xiexianbin.cn.csr -CA secondcacert.crt -CAkey secondcakey.key -CAcreateserial -out all.xiexianbin.cn.crt -extfile all.xiexianbin.cn.ext -sha256
Signature ok
subject=/C=CN/ST=Shanghai/L=Shanghai/O=xiexianbin.cn/OU=IT/CN=*.xiexianbin.cn/emailAddress=me@xiexianbin.cn
Getting CA Private Key

验证生成的SSL证书

校验证书是否被 CA 证书签名:

# openssl verify -CAfile secondcacert.chain.crt all.xiexianbin.cn.crt
all.xiexianbin.cn.crt: OK

生成bundle.crt

cat all.xiexianbin.cn.crt secondcacert.crt > all.xiexianbin.cn.bundle.crt

系统信任CA证书

查看证书

openssl s_client -showcerts -servername xiexianbin.cn -connect xiexianbin.cn:443
openssl s_client -showcerts -connect xiexianbin.cn:443

linux访问错误示例

curl工具可以在linux上模拟发送请求,但当它去访问https加密网站时就会提示如下信息:

# curl https://www.xiexianbin.cn/
curl: (60) Peer certificate cannot be authenticated with known CA certificates
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

Redhat/CentOS信任CA证书

  • pem转cert
openssl x509 -in cacert.crt -inform PEM -out cacert.crt
  • 配置
yum install -y ca-certificates
# 将cacert.crt根证书到/etc/pki/ca-trust/source/anchors目录中
update-ca-trust

再次已经可以正常访问。

Mac信任CA证书

打开钥匙串访问,左侧钥匙串选择系统种类选择证书,然后把刚才生成的根证书托入(根证书是cacert.crt)。

双击此证书,在信任设置中,选择始终信任

访问效果:

原理

证书中X509v3 extensionsX509v3 Authority Key Identifier必须与CA keyid一致才能正常验证证书。

openssl x509 -in all.xiexianbin.cn.crt -text -noout
...
        X509v3 extensions:
            X509v3 Authority Key Identifier:
                keyid:A3:AA:4D:FB:39:BC:15:59:68:F6:3A:D0:DE:10:2A:10:4C:F9:8F:6B

            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Key Usage:
                Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment
            X509v3 Subject Alternative Name:
                DNS:xiexianbin.cn, DNS:*.xiexianbin.cn, DNS:kb.cx, DNS:*.kb.cx
...

其他方式自签证书信任方法

证书签发

openssl req -x509 -days 365 -out ./cert/all.xiexianbin.cn.crt -keyout ./cert/all.xiexianbin.cn.key \
    -newkey rsa:2048 -nodes -sha256 \
    -subj "/CN=*.xiexianbin.cn" -extensions EXT -config <( \
    printf "[dn]\nCN=*.xiexianbin.cn\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:*.xiexianbin.cn\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")

该方式生成的证书中X509v3 extensions没有X509v3 Authority Key Identifier信息

openssl x509 -in all.xiexianbin.cn.crt -text -noout
...
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:*.bktest.com
            X509v3 Key Usage:
                Digital Signature
            X509v3 Extended Key Usage:
                TLS Web Server Authentication
...

证书查看

chrome浏览器上,点击左上角的惊叹号区块,再出现的菜单栏中点击证书(无效)

导出导入自签名证书

Windows用户

  1. 证书页面导出操作

点击详细信息 -> 复制到文件(C)... -> 下一步 -> 在证书导出向导选择DER编码二进制X.509(.CER(D)) -> 下一步 -> 确认浏览证书导出位置 -> 下一步 -> 完成

  1. 安装证书

右键上一步导出的证书文件 -> 选择存储位置(推荐本地计算机) -> 下一步后,选择将所有的证书都放入夏磊存储 -> 浏览选择受信任的证书颁发机构 -> 下一步 -> 完成

Mac用户

  • 直接将证书图片拖拉至桌面即可导出证书文件
  • 双击导入并在钥匙串访问设置中信任该证书,或直接使用下列命令行导入
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <导出证书文件夹的路径及文件名>

FAQ

Java信任其他CA证书

  • 准备证书:通过浏览器下载“中级证书颁发机构”的证书,采用如下方法转化为pem格式
  • 转化为pem
openssl x509 -inform der -in Lets-Encrypt-Authority-X3.cer -out Lets-Encrypt-Authority-X3.pem
  • 将证书添加到java
# wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem
keytool -trustcacerts -keystore "<$JAVA_HOME>/lib/security/cacerts" -storepass changeit -noprompt -importcert -alias lets-encrypt-x3-cross-signed -file "/tmp/lets-encrypt-x3-cross-signed.pem"
专栏文章
  1. SSL/TLS原理详解
  2. 怎样查看计算机本地安装的证书
  3. 免费HTTPS证书Let's Encrypt安装教程
  4. 多域名(SAN/UCC)生成CSR操作指南
  5. 免费通配符/泛域名SSL证书申请
  6. 基于OpenSSL自建CA证书、二级CA证书和SSL证书(当前)
最新评论
加载中...