OpenSSL 创建私有 CA 三部曲:
使用 OpenSSL 创建私有 CA:1 根证书
使用 OpenSSL 创建私有 CA:2 中间证书
使用 OpenSSL 创建私有 CA:3 用户证书

本文将在前文《使用 OpenSSL 创建私有 CA:1 根证书》的基础上介绍如何为私有 CA 创建中间证书。
说明:本系列文章的演示环境为 Ubuntu 18.04,OpenSSL 的版本为 1.1.0g。

为什么要创建中间证书?

使用 CA 的根证书是可以直接签发用户证书的,那么为什么还还要创建中间证书呢?
大概有两个原因:

  • 安全性
  • 建立中间证书颁发机构(CA)

先说安全性,通过签发中间证书,再用中间证书签发用户证书的方式,可以最大程度的减少更证书的使用频率,甚至可以离线保存根证书。如果发现中间证书被破坏,还可以吊销该中间证书并颁发新的中间证书。
再来说说中间证书颁发机构(CA),一个中间证书颁发机构(CA)是一个实体,它具有根 CA 颁发的中间证书,并且可以代表根 CA 颁发用户证书,从而形成一条被信任的证书链。
这里有必要介绍下证书产业的基本玩法:首先根证书的所有者(大的证书厂商)会和 OS 厂商合作,让 OS 等环境默认信任自己的根证书。然后根证书的所有者会签发中间证书卖给小一些的证书厂商。这些小的证书厂商再用中间证书创建最终证书卖给普通消费者。
举个例子,像我们常用的 Windows 操作系统默认就信任了很多厂商的根证书,比如 VeriSign 的证书,并且这些证书还会随着 Windows 系统的更新而更新:

上图中,VeriSign 是根证书所有者,你安装 windows 操作系统时,VeriSign 的根证书就被安装到信任列表中了。Symantec Class 3 SHA256 Code Signing CA 则是 Symantec 公司从 VeriSign 公司购买的中间证书。GrapeCity inc. 则是 GrapeCity 公司从 Symantec 公司购买的最终证书用来对产品进行签名。当然,有时候根证书厂商比如 VeriSign 等也会直接向最终用户销售证书。

为了模拟中间证书颁发机构(CA),本文将使用前文中创建的根证书创建一个名称为 power 的中间证书。

准备中间 CA 的配置文件

创建文件配置文件 powerca/powerca.cnf,编辑其内容如下:

# OpenSSL root CA configuration file.
# v1
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
# Directory and file locations.
dir = /home/nick/projects/myca/powerca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/db/index
serial = $dir/db/serial
RANDFILE = $dir/private/random
# The root key and root certificate.
private_key = $dir/private/powerca.key.pem
certificate = $dir/certs/powerca.cert.pem
# For certificate revocation lists.
crlnumber = $dir/db/crlnumber
crl = $dir/crl/powerca.crl.pem
crl_extensions = crl_ext
default_crl_days =
# SHA- is deprecated, so use SHA- instead.
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days =
copy_extensions = copy
preserve = no
policy = policy_loose
[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
# Options for the `req` tool (`man req`).
# Optionally, specify some defaults.
prompt = no
input_password =
default_bits =
distinguished_name = req_distinguished_name
string_mask = utf8only
# SHA- is deprecated, so use SHA- instead.
default_md = sha256
# Extension to add when the -x509 option is used.
# make sure use x509_extensions, do not use req_extensions.
x509_extensions = v3_ca
# use the req_extensions not work.
#req_extensions = v3_ca
[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName = CN
stateOrProvinceName = ShaanXi
localityName = Xian
organizationName = NickLi Ltd
organizationalUnitName = NickLi Ltd CA
commonName = NickLi Power CA
emailAddress = ljfpower@.com
[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always
[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning

这个配置文件的内容和 rootca/rootca.cnf 有很多相同之处,下面是一些比较重要的不同之处:

[ CA_default ]
dir = /home/nick/projects/myca/powerca
private_key = $dir/private/powerca.key.pem
certificate = $dir/certs/powerca.cert.pem
crl = $dir/crl/powerca.crl.pem
policy = policy_loose
[ req_distinguished_name ]
commonName = NickLi Power CA

CA_default 中的变化主要是告诉 OpenSSL 相关文件的路径,而中间证书的 commonName 必须不同于根证书。

准备目录和文件

与 rootca 目录相同,我们需要在 powerca 目录下创建如下的目录和文件:

powerca/certs/
powerca/db/
powerca/private/
powerca/crl/
powerca/csr/
powerca/newcerts/ powerca/db/index
powerca/db/serial
powerca/db/crlnumber

其中的 powerca/private 目录需同样要 700 的权限,我们使用下面的脚本来创建这些目录和文件:

#!/bin/bash

# create dir certs db private crl csr newcerts under powerca dir.
if [ ! -d powerca/certs ]; then
mkdir -p powerca/certs
fi if [ ! -d powerca/db ]; then
mkdir -p powerca/db
touch powerca/db/index
openssl rand -hex > powerca/db/serial
echo > powerca/db/crlnumber
fi if [ ! -d powerca/private ]; then
mkdir -p powerca/private
chmod powerca/private
fi if [ ! -d powerca/crl ]; then
mkdir -p powerca/crl
fi if [ ! -d powerca/newcerts ]; then
mkdir -p powerca/newcerts
fi if [ ! -d powerca/csr ]; then
mkdir -p powerca/csr
fi

把上面的代码保存到 myca/powerhelper.sh 文件中,然后 cd 到 myca 目录下执行:

$ ./powerhelper.sh

此时当前目录为 myca,powerca 下的子目录和文件都已经创建成功。

创建中间证书的秘钥

进入 powerca 目录:

$ cd powerca 

执行下面的命令重建私钥:

$ openssl genrsa -aes256 -out powerca/private/powerca.key.pem 

这里笔者设置的密码为:123456,记住这个密码,后面还会用到。然后为了确保安全,把秘钥的权限设置为 400:

$ chmod  private/powerca.key.pem

此时当前目录为 myca/powerca。

创建 Certificate Signing Requests(csr)

要创建中间证书,需要使用带有 v3_intermediate_ca 扩展名的根 CA 来签署中间 CSR,其中 v3_intermediate_ca 扩展的配置信息就在 powerca/powerca.cnf 中:

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

现在直接创建 csr 就行了:

$ openssl req -new \
-config powerca.cnf \
-sha256 \
-key private/powerca.key.pem \
-out csr/powerca.csr.pem

下面的命令可以检查生成的 csr:

$ openssl req -text -noout -in csr/powerca.csr.pem

注意,csr 中包含了 CA 的基本信息,和公钥信息。

创建中间证书

下面是整个过程中最为关键的地方!通过 Root CA 的信息和用户的 csr 为用户生成证书。
创建中间证书需要用到 rootca/rootca.cnf 中的配置信息,所以先进入 myca 目录:

# 从 powerca 目录回到 myca 目录
$ cd ..
$ openssl ca -config rootca/rootca.cnf \
-extensions v3_intermediate_ca \
-days -notext -md sha256 \
-in powerca/csr/powerca.csr.pem \
-out powerca/certs/powerca.cert.pem

在交互式的提示中输入私钥的密码 123456,并同意其它的确认提示,就完成了根证书的生成操作:

rootca/db/index 文件是 OpenSSL CA 工具存储证书的数据库,请不要手动修改这个文件(除非你清楚的知道自己在干什么)。此时它应该包含了根证书和中间证书的信息:

证书生成后我们把它的权限修改为 444:

$ chmod  powerca/certs/powerca.cert.pem

验证中间证书

通过下面的命令验证中间证书:

$ openssl x509 -noout -text -in powerca/certs/powerca.cert.pem

在中间证书中,Subject 的 Common Name 为 "NickLi Power CA",而 Issuer 的 Common Name 为 "NickLi Root CA"。
还可以通过下面的命令来检查中间证书的状态:

$ openssl verify -CAfile rootca/certs/rootca.cert.pem powerca/certs/powerca.cert.pem

创建证书链文件

当 web 浏览器等应用程序试图验证中间 CA 颁发的证书时,它还必须根据根证书验证中间证书。这就需要构建完整的证书信任链供应用程序验证。所谓的证书链,简单的说就是把根证书和中间证书按照顺序放置在同一个证书文件中。重点是:中间证书在上面,根证书在下面。比如为我们的中间证书创建证书链:

$ cat powerca/certs/powerca.cert.pem \
rootca/certs/rootca.cert.pem > powerca/certs/powerca-chain.cert.pem
$ chmod powerca/certs/powerca-chain.cert.pem

注意:在局域网环境中,我们一般会把生成的这个证书链安装到用户的机器上。

pem 格式的证书、证书链文件适用的场景比较多,但是在 windows 系统中一般使用 p12 格式,所以我们还需要创建一个 p12 格式的证书链:

$ openssl pkcs12 -export \
-name "powerca chain" \
-inkey powerca/private/powerca.key.pem \
-in powerca/certs/powerca.cert.pem \
-certfile powerca/certs/powerca-chain.cert.pem \
-out powerca/certs/powerca-chain.cert.p12

这个过程中需要输入私钥 powerca/private/powerca.key.pem 的密码(这里是 123456),并且为新证书设置的密码。

总结

现在我们已经有了私有 CA 的根证书并且生成了中间证书和证书链,在接下来的《使用 OpenSSL 创建私有 CA:3 用户证书》一文中我们将详细的介绍如何使用中间证书创建用户证书,以及如何把证书部署到 web 站点和客户端。

参考:
OpenSSL Certificate Authority
《openssl-cookbook》

使用 OpenSSL 创建私有 CA:2 中间证书的更多相关文章

  1. 使用 OpenSSL 创建私有 CA:1 根证书

    OpenSSL 创建私有 CA 三部曲:使用 OpenSSL 创建私有 CA:1 根证书使用 OpenSSL 创建私有 CA:2 中间证书使用 OpenSSL 创建私有 CA:3 用户证书 OpenS ...

  2. 使用 OpenSSL 创建私有 CA:3 用户证书

    OpenSSL 创建私有 CA 三部曲:使用 OpenSSL 创建私有 CA:1 根证书使用 OpenSSL 创建私有 CA:2 中间证书使用 OpenSSL 创建私有 CA:3 用户证书 在前文&l ...

  3. 创建私有CA并签发证书

    一.创建私有CA 1.创建所需要的文件 2.创建私有密钥 3.CA自签证书 -new: 生成新证书签署请求:               -x509: 专用于CA生成自签证书:不自签的时候不要加该选项 ...

  4. OpenSSL创建私有CA

    1.编辑/etc/pki/tls/openssl.cnf [ CA_default ] dir             = /etc/pki/CA           # 工作目录certs      ...

  5. 如何通过Openssl实现私有CA,并为HTTP服务提供TLS/SLL安全机制

    原文链接:http://guodayong.blog.51cto.com/263451/1181059 Openssl是SSL的开源实现(可以免费下载应用程序),是一种安全机密程序,主要用于提高远程登 ...

  6. 自签名证书和私有CA签名的证书的区别 创建自签名证书 创建私有CA 证书类型 证书扩展名【转】

    自签名的证书无法被吊销,CA签名的证书可以被吊销 能不能吊销证书的区别在于,如果你的私钥被黑客获取,如果证书不能被吊销,则黑客可以伪装成你与用户进行通信   如果你的规划需要创建多个证书,那么使用私有 ...

  7. linux基础之加密解密、PKI及SSL、创建私有CA

    加密解密基础 1. 对称加密: 加密和解密使用同一个密钥 常见的加密算法有:DES.3DES.AES.Blowfish.Twofish.IDEA.RC6.CAST5 特性: 1. 加密.解密使用同一个 ...

  8. 创建私有CA, 加密解密基础, PKI, SSL

    发现了一篇图文并茂的超棒的  加密解密, CA, PKI, SSL 的基础文章, 链接如下:https://blog.csdn.net/lifetragedy/article/details/5223 ...

  9. Linux操作系统安全-局域网私有CA(Certificate Authority)证书服务器实战篇

    Linux操作系统安全-局域网私有CA(Certificate Authority)证书服务器实战篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.试验架构说明 node101 ...

随机推荐

  1. SQL Server OPTION (OPTIMIZE FOR UNKNOWN) 测试总结

      关于SQL Server的查询提示OPTION (OPTIMIZE FOR UNKNOWN) ,它是解决参数嗅探的方法之一. 而且对应的SQL语句会缓存,不用每次都重编译.关键在于它的执行计划的准 ...

  2. Dapp已来,如何把握区块链创富模式变化的趋势

    区块链技术持续升温,Dapp迅速成为焦点,未来区块链市场上新的蓝海.这么说当然不是空想出来的,而是从区块链市场的发展趋势中推断而来.区块链市场由最初的挖矿炒币到如今尝试投入行业应用,随着技术和应用模式 ...

  3. Lua保留指定小数位数

    默认会四舍五入 比如:%0.2f 会四舍五入后,保留小数点后2位 print(string.format("%.1f",0.26)) ---会输出0.3,而不是0.2 Lua保留一 ...

  4. 【2018.08.13 C与C++基础】网络通信:阻塞与非阻塞socket的基本概念及简单实现

    一.前言 最近在做Matalb/Simulink与C/C++的混合编程,主要是完成TCP.UDP.SerialPort等常见通信方式的中间件设计,为Simulink模型提供数据采集及解析模块. 问题在 ...

  5. 你可能不知道的printf

    前言 printf可能是我们在学习C语言的过程中最早接触的库函数了.其基本使用想必我们都已经非常清楚了.但是下面的这些情况你是否已经清楚地知道了呢? 示例程序 我们来看一个示例程序,看看你能否对下面的 ...

  6. C3P0连接池温习1

    一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...

  7. Django Form和ModelForm组件

    Form介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否 ...

  8. 【PS技巧】如何校正倾斜的图片

    1.打开PS,直接拖拽图片. 2.点击[滤镜==>扭曲==>镜头校正],出现校正对话框. 3.点击拉直工具,从右向左滑一条直线. 参考文档: 在Photoshop中如何校正倾斜的图片?

  9. n阶方阵的最值问题和对角线的和问题

    如题! package 矩阵2; public class JuZheng { public static void main(String args[]) { int array[][] = { { ...

  10. 【FJWC 2019】 森林

    [FJWC 2019] 森林 样例输入 0 5 1 0 0 2 样例输出 1 2 3 3 我们发现,答案就是直径加上直径上某个点出发,不经过其他直径上的点的最长链.这里的直径可以是任意一条直径. 首先 ...