0 数字证书
背景
数字证书是网络安全领域的基石,提供了身份验证和加密通信的能力。数字证书遵循一系列的技术标准,其中最重要的是X.509标准。X.509是国际电信联盟(ITU-T)制定的一套关于公钥证书的标准,广泛应用于互联网和私有网络中。它定义了证书的格式和内容,以及如何使用证书链来建立信任关系。
数字证书基本原理
数字证书是基于公钥基础设施(Public Key Infrastructure,PKI)的一种技术,其基本原理涉及到非对称加密、信任链和数字签名。以下是数字证书的基本原理:
- 非对称加密:
-
- 在非对称加密系统中,每个参与者都有一对密钥:公钥和私钥。
- 公钥可以公开分享,而私钥必须保密。
- 使用公钥加密的数据只能用相应的私钥解密,反之亦然。
- 这种机制允许安全地交换信息,即使是通过不安全的通信渠道。
- 数字签名:
-
- 使用私钥对数据(如证书、文件或消息)进行加密,产生的加密数据称为数字签名。
- 数字签名可以用对应的公钥进行验证,以确保信息是由持有私钥的实体签发,并且没有被篡改。
- 数字签名不仅提供了信息的完整性验证,还提供了发送者的身份验证。
- 证书颁发机构(CA):
-
- CA是一个受信任的第三方机构,负责验证实体的身份并为其颁发数字证书。
- 数字证书包含了证书主题的信息(如个人、组织或设备)、公钥、证书有效期等。
- CA使用自己的私钥对证书进行签名,任何拥有CA公钥的人都可以验证该证书。
- 信任链:
-
- 数字证书通常是链式结构,根CA位于信任链的顶端,由根CA签名的中间CA证书形成信任链条。
- 中间CA可以再签发其他证书,这样就形成了从根CA到最终证书的信任路径。
- 用户信任根CA,并预装其公钥,以此为基础对整个信任链中的证书进行验证。
- 证书验证:
-
- 当需要验证证书时(如在TLS握手过程中),客户端软件(如Web浏览器)会检查证书的签名、有效期、吊销状态等。
- 软件通过信任链逐级向上验证,直到可信的根CA证书。
- 如果证书链的所有证书都通过验证,证书就被认为是有效的。
通过这些基本原理,数字证书为在线通信提供了一个安全的验证机制,使得参与者能够验证彼此的身份,并确保数据在传输过程中的安全性和完整性。
数字证书的文件格式
PEM(Privacy Enhanced Mail):以"-----BEGIN CERTIFICATE-----"和"-----END CERTIFICATE-----"包围的Base64编码的文本格式,是最常见的格式。
DER(Distinguished Encoding Rules):使用ASN.1的DER编码的二进制格式,常用于Java平台。
PFX/P12:包含证书和私钥的加密格式,通常用于Windows平台。
CER/ CRT:通常表示一个未加密的PEM或DER格式证书。
数字证书类型
根据应用场景和用途的不同,数字证书可以分为多种类型,包括:
- SSL/TLS证书:用于网站和服务器的身份验证和数据加密。
- 代码签名证书:用于确认软件的出版者身份和代码未被篡改。
- 邮件签名证书:用于电子邮件的签名和加密。
- 客户端证书:用于身份验证,如VPN或企业网络访问。
数字证书关键字段
数字证书包含多个字段,每个字段都承载着关键的信息
颁发机构(Issuer)
签发证书的CA的信息。
Common Name (CN): 对于SSL/TLS证书,CN通常是证书用于保护的完整域名(例如 www.example.com)。对于个人证书,这可能是个人的名字或身份标识符。
Organization (O): 表示证书持有者所属的公司或组织的官方名称。
Organizational Unit (OU): 表示证书持有者所属的公司或组织内的部门或分支。
Country (C): 表示证书持有者所在国家的两个字母国家代码(例如 US 表示美国)。
State or Province (ST): 表示证书持有者所在的州或省。
Locality (L): 表示证书持有者所在的城市或地区。
主体名称(Subject Name)
证书所有者的身份信息,如组织名称和域名。
指定了证书所有者的身份信息。这个字段是证书的一部分,用于唯一标识证书的主体——也就是证书所属的个人、服务器或组织。
具体字段可以参考Issuer。
有效期(Validity Period)
证书从颁发之日起到其失效为止的时间范围。在这个时间段内,证书被视为有效和可信的。数字证书的有效期设置通常取决于证书颁发机构(Certificate Authority, CA)的策略,以及证书用途的具体需求。证书的有效期可以是一年、两年、三年,甚至更长或更短的时间。
Not Before(生效时间):这是证书开始生效的日期和时间。在此之前,证书不应被接受或信任为有效。
Not After(过期时间):这是证书有效期的终止日期和时间。在此时间之后,证书被视为过期,不再被接受或信任。
序列号(Serial Number)
证书颁发机构(CA)为每个颁发的证书分配的一个唯一编号。这个序列号是证书的必要部分,因为它允许区分来自同一CA的不同证书,即使这些证书的其他属性(如主题或公钥)相同。
序列号的主要特点和用途包括:
唯一性:每个证书的序列号都应该是唯一的,至少在颁发它的CA的范围内。这意味着任何给定CA颁发的任何两个证书都不应该有相同的序列号。
不可预测性:为了安全起见,序列号应该是不可预测的,这样攻击者就不能轻易猜测或伪造证书序列号。
证书吊销:序列号在证书管理中起着关键作用,特别是在证书吊销的过程中。当需要吊销证书时,CA会将该证书的序列号添加到证书吊销列表(CRL)中。客户端软件(如Web浏览器)可以检查CRL以确定证书是否已被吊销。
证书跟踪:序列号还可以用于跟踪和管理证书,例如,在证书生命周期管理系统中。
数字证书的序列号通常是一个正整数,可以是任意长度,但通常遵守一定的编码规则,如ASN.1编码。在实践中,序列号的长度通常不会超过20个八位字节(即160位),这足以确保全局唯一性。
签名算法(Signature Algorithm)
证书的签名是由证书颁发机构(CA)的私钥生成的,它确保了证书的内容没有被篡改,并证实了证书颁发机构对证书中包含的公钥和其他信息的认可。接收方将使用CA的公钥(通常包含在CA的根证书或中间证书中)来验证签名。
"Signature Algorithm"字段通常包含如下信息:
散列算法(Hash Algorithm):用于创建证书内容摘要的算法,例如SHA-256、SHA-384等。散列算法应该是安全的,以确保不能找到两个不同的证书内容,它们生成相同的摘要值(这种情况称为散列冲突)。
签名算法(Signature Algorithm):用于加密散列摘要的算法,例如RSA、ECDSA(椭圆曲线数字签名算法)等。签名算法使用CA的私钥来加密散列摘要。
在实际的数字证书中,"Signature Algorithm"字段可能会显示为类似以下的值:
sha256WithRSAEncryption:表示使用SHA-256散列算法和RSA加密算法。
ecdsa-with-SHA256:表示使用SHA-256散列算法和ECDSA签名算法。
sha1WithRSAEncryption:表示使用SHA-1散列算法和RSA加密算法(SHA-1现在被认为是不安全的,不推荐使用)。
公钥(Public Key)
包含证书主体的公钥信息。公钥是非对称加密系统中的一部分,与私钥配对使用。私钥必须保密,而公钥可以公开。这对密钥用于执行如下操作:
加密数据:公钥可以被任何人用来加密数据,但只有持有对应私钥的实体能够解密这些数据。这常用于确保信息的机密性。
验证数字签名:私钥用于生成数字签名,而公钥则用于验证签名的真实性。这可以证明信息未被篡改,并确认信息是由持有私钥的实体发送的。
在X.509数字证书中,“Public Key”字段的结构如下:
公钥算法:指明用于公钥的非对称加密算法,例如 RSA、DSA 或 ECDSA。
公钥:实际的公钥数据,其格式和长度取决于所用的公钥算法。
例如,如果证书使用RSA公钥,那么“Public Key”字段会包含一个RSA公钥,它由两个主要数值组成:模数(modulus)和公钥指数(public exponent)。模数是两个大素数的乘积,而公钥指数通常是一个预定义的常数,例如65537。
密钥用途(Key Usage)
一个重要的扩展字段,它定义了证书中包含的公钥的允许使用方式。这个字段限制了公钥的功能,以确保它只被用于预期的特定目的。这有助于增加安全性,并且允许实施策略以限制密钥的使用。
"Key Usage"扩展可以包含下列标志(不是所有标志都必须存在):
digitalSignature:允许公钥用于验证数字签名,这通常用于证实发送的数据是未被篡改的,并且是由持有相应私钥的实体签署的。
nonRepudiation:允许公钥用于验证签名,以防止发送方否认之前发送过的信息。这通常用于具有法律或合同意义的场合。
keyEncipherment:允许公钥用于加密会话密钥,这样只有持有对应私钥的接收方才能解密这个会话密钥,并用其解密信息。
dataEncipherment:允许公钥直接用于加密数据,而不是加密会话密钥。
keyAgreement:允许公钥用于协商共享密钥,例如在椭圆曲线加密中的密钥协商。
keyCertSign:允许公钥用于签署其他证书,这意味着证书可以作为证书颁发机构(CA)使用。只有CA证书才应该具有这个用途。
cRLSign:允许公钥用于签署证书吊销列表(CRLs),这些列表包含了被CA撤销的证书序列号。
encipherOnly:仅允许公钥用于加密数据,通常与keyAgreement一起使用。
decipherOnly:仅允许公钥用于解密数据,通常与keyAgreement一起使用。
基本限制(Basic Constraints)
是一个扩展字段,用于指示证书的类型以及证书主体是否有权限签发其他证书。这个扩展是非常重要的,因为它可以用来区分证书颁发机构(CAs)的证书和终端实体(如个人、服务器)的证书。
“Basic Constraints”扩展包含以下几个组成部分:
CA(Certificate Authority)标志:此标志指示证书是否可以用作CA证书。
如果设置为TRUE,证书持有者可以使用它来签发其他证书,这意味着它是一个CA证书。
如果设置为FALSE或该标志不存在,则证书不用于签发其他证书,即它是一个终端实体证书。
pathLenConstraint:此选项仅在CA字段为TRUE时才有意义,它定义了证书链中下级CA证书的最大允许数量。例如,如果设置为0,则表示该CA证书只能用来直接签发终端实体证书,而不能签发其他CA证书。如果没有设置这个限制,则CA可以签发任意数量的下级CA证书。
授权密钥标识符(Authority Key Identifier, AKI)
用来帮助唯一地标识证书颁发机构(CA)的公钥的。AKI扩展对于构建证书链非常有用,因为它提供了一个链接到颁发证书的CA的标识符,这有助于证书验证过程中的证书链验证。
“Authority Key Identifier”扩展通常包含以下信息:
keyIdentifier:这是从CA的公钥中派生的一个唯一标识符。它通常是CA公钥的一个散列值(例如,使用SHA-1算法),这个散列值可以用来快速比较和确认CA证书的公钥。
authorityCertIssuer:这是一个可选字段,包含颁发CA证书的颁发者名称。它是一个指向CA证书颁发者的链接,可以用来在证书链中回溯查找。
authorityCertSerialNumber:这也是一个可选字段,包含颁发CA证书的序列号。与“keyIdentifier”一起,这个字段提供了在证书库中查找CA证书所需的足够信息。
“Authority Key Identifier”扩展对于区分具有相同颁发者名称的不同CA证书特别有用。当CA证书需要更新或替换时,可以通过AKI来确保证书链中每个证书正确指向其特定的颁发证书。
主题密钥标识符(Subject Key Identifier, SKI)
用来唯一标识证书中的公钥的。SKI通常是从公钥本身生成的一个散列值,它为证书链的构建和证书路径的验证提供了一种机制。
这个扩展的主要目的是在有多个证书拥有相同主题名称的情况下,帮助唯一地识别这些证书中的公钥。这在证书的续订和吊销过程中尤其重要,以确保证书链中各个证书正确地链接到其对应的实体。SKI扩展通常包含以下信息:
keyIdentifier:这是证书主体的公钥的散列值,通常使用SHA-1或其他散列算法计算得出。这个散列值作为证书的公钥的唯一标识符。
通过使用SKI,可以在验证证书链时确保每个证书都准确地指向其上游的证书颁发机构(CA)。这有助于简化证书链的处理,提高验证过程的效率。
1 CA证书体系
1.1 CA
CA(Certificate Authority,证书授权)是数字证书认证的权威机构,负责颁发数字证书。是数字签名的技术基础保障,也是网上实体身份的证明,能够证明某一实体的身份及其公钥的合法性,证明该实体与公钥二者之间的匹配关系。简单的说,它是负责管理和签发证书的第三方机构,目的在于让通信双方安全的交换公钥。
1.2 数字证书
证书是数字签名的技术基础保障,也是网上实体身份的证明。它能够证明某一实体的身份及其公钥的合法性,并证明该实体与公钥二者之间的匹配关系。证书是公钥的载体,证书上的公钥与实体身份相绑定。在电子商务系统中,所有实体的证书都是由证书授权中心即CA中心颁发并签名的。有了CA证书,就能够明确对方的身份,用数字证书加密,通过数字签名的电子文件防篡改。
1.3 CA证书
顾名思义,CA证书就是由CA机构颁发的一种数字证书,它包含了证书拥有者的身份信息、公钥、私钥以及CA机构的签名,用于在互联网通讯中验证通信实体的身份和公钥和合法性。
1.4 自签名证书
1.4.1 自签名证书的基本概念
自签名证书是指由用户自己生成和签名的证书,而非有公认的证书颁发机构签名的证书。但自签名证书毕竟是免费且未经过权威机构签名,通常不受浏览器和客户端信任。
1.4.2 带或不带CA的自签名证书
另外在创建自签名证书的时候,用户可以自行选择是否带CA,这是他们的区别:
带CA的证书:
用户不仅生成了自己的证书,还创建了自己的CA,并使用该CA签名证书。也就是说用户建立了独立的CA环境。由于创建了自己的CA环境,这类自签名证书的可信度相对高一点。带CA的自签名证书具有较好的可扩展性,适用于需要多个证书,并且需要统一管理和验证的场景。
不带CA的证书:
用户仅仅创建了一个证书,并没有创建CA。也就是说这是一张独立的证书。由于没有CA机构的认证,可信度相对较低。不带CA的自签名证书适用于单一、简单的应用场景,如个人网站或测试环境。
1.5 SSL/TLS安全协议
1.5.1 SSL
SSL(Secure Socket Layer)安全套接层是Netscape公司率先采用的网络安全协议。它是在传输通信协议(TCP/IP)上实现的一种安全协议,采用公开密钥技术。SSL广泛支持各种类型的网络,同时提供三种基本的安全服务,它们都使用公开密钥技术。目前,SSL拥有1.0,2.0,3.0三个版本,我们目前使用的基本为SSL 3.0
1.5.2 TLS
TLS(Transport Layer Security)安全传输层协议是IETF(Internet Engineering Task Force,Internet工程任务组)以SSL协议为基础制定的一种新的协议,它对SSL 3.0进行了标准化并添加了少量的机制。
目前TLS有1.0-1.3共四个版本,但许多浏览器对1.0和1.1两个版本似乎已经停止支持。
2 OpenSSL
2.1 OpenSSL简介
OpenSSL既是一个项目又是一个软件。作为软件,它是一个功能齐全的工具包,广泛应用于通用加密和安全通信。
OpenSSL包括了三个组件:
- libcrypto:用于实现加密和解密的库
- libssl:用于实现ssl通信协议的安全库
- openssl:多用途命令工具
2.2 OpenSSL命令
2.2.1 计算hash
计算文件hash
Command:
openssl <加密算法> <path>
Eg:
[root@linux1 ~]# openssl md5 /etc/passwd
MD5(/etc/passwd)= a6853410a57f452e867727b2f4bd2c1c
[root@linux1 ~]#
计算密码hash
Command:
openssl passwd [options] <password>
Options:
-in infile 从文件中读取密码
-salt val 使用指定的盐
-stdin 从标准输入读取密码
-6 基于SHA512的密码算法
-5 基于SHA256的密码算法
-1 基于MD5的密码算法
-crypt 标准Unix密码算法(默认选项)
-rand val Load the file(s) into the random number generator
-writerand outfile Write random data to the specified file
-rand val 将文件加载到随机数生成器中
-writer和 outfile 将随机数据写入指定文件
Eg:
[root@linux1 ~]# openssl passwd -6 123456
$6$ztBdEjF.bkuzswqI$jRXCp.L4TbcCLSkTtDDavjFrrHlco2xzOpNLFm51Ej7IWcL4d56m5wKtpFE1vj3mK97Ar6QJDKv85F6kZYRpo0
[root@linux1 ~]# echo 123456 | openssl passwd -6 -stdin
$6$M/I/9sEqeq0vidz8$3lUn6bwmJod4azF6z6GfgKLR5JvoTGhCRZbNxMLD9vbC2YiDmLE6naLx3OV76PcPJsga9sHdtKhw/nwta35Xx/
[root@linux1 ~]# openssl passwd -6 -salt M/I/9sEqeq0vidz8 123456
$6$M/I/9sEqeq0vidz8$3lUn6bwmJod4azF6z6GfgKLR5JvoTGhCRZbNxMLD9vbC2YiDmLE6naLx3OV76PcPJsga9sHdtKhw/nwta35Xx/
[root@linux1 ~]#
这里可以看到openssl passwd -6 123456和echo 123456 | openssl passwd -6 -stdin的返回值不一样,这是应为这条命令在计算hash的时候加入了一个叫做盐(salt)的参数,通过openssl passwd -6 -salt M/I/9sEqeq0vidz8 123456命令可以看出只要salt和passwd相同,计算出的hash是一样的。
2.2.2 生成随机数
Command:
openssl rand [-base64] [-hex] <num>
Eg:
[root@linux1 ~]# openssl rand -hex 3
af847d
[root@linux1 ~]# openssl rand -base64 4
AsTleg==
[root@linux1 ~]#
2.2.3 生成私钥和公钥
生成私钥
Command:
openssl genrsa -out <filename> [options] [私钥位数,默认2048]
Options:
-aes128, -aes192, -aes256, -des, -des3, -idea 使用符合密码复杂性的密码对私钥进行指定的加密
Eg:
[root@linux1 ~]# openssl genrsa -out /etc/ssl/test.key
Generating RSA private key, 2048 bit long modulus (2 primes)
..............................................................................................................................+++++
..........................................+++++
e is 65537 (0x010001)
[root@linux1 ~]# ls /etc/ssl
bak test.key
[root@linux1 ~]#
对私钥解密
如果在生成私钥的时候对私钥进行了加密,可以用下面的命令进行解密
Command:
openssl genrsa -in <filename1> -out <filename2>
Eg:
[root@linux1 ~]# openssl genrsa -aes128 -out test.key
Generating RSA private key, 2048 bit long modulus (2 primes)
.........................+++++
.....................................................................+++++
e is 65537 (0x010001)
Enter pass phrase for test.key:
Verifying - Enter pass phrase for test.key:
[root@linux1 ~]# openssl rsa -in test.key -out test1.key
Enter pass phrase for test.key:
writing RSA key
[root@linux1 ~]#
当然,不解密 也是可以的,就是有时候会麻烦一点,比如:
从私钥中提取公钥
Command:
openssl rsa -in <filename1> -pubout -out <filename2>
Eg:
[root@linux1 ~]# openssl rsa -in test.key -pubout -out test.key.pub
Enter pass phrase for test.key:
writing RSA key
[root@linux1 ~]# openssl rsa -in test1.key -pubout -out test1.key.pub
writing RSA key
[root@linux1 ~]#
2.3 建立私有CA实现证书申请颁发
2.3.1 建立私有CA
建目录和文件
由于没有默认生成CA证书根目录结构,所以我们需根据配置文件自行创建目录结构,然后再根据配置文件的要求,创建存放证书索引的index.txt和存放下一个证书的编号的serial这两个文件
[root@linux2 ~]# mkdir -p /etc/pki/CA/{certs,crl,newcerts,private}
# 如果懒的话 yum -y install openssl-* 或者 yum -y install openssl-perl 也可以
[root@linux2 ~]# cd /etc/pki/CA/
[root@linux2 CA]# touch index.txt
[root@linux2 CA]# echo 01 > serial
[root@linux2 CA]#
创建私钥
[root@linux2 CA]# openssl genrsa -out private/cakey.pem
Generating RSA private key, 2048 bit long modulus (2 primes)
.........................................................................................+++++
.....................+++++
e is 65537 (0x010001)
[root@linux2 CA]#
生成自签名根证书
[root@linux2 CA]# openssl req -new -x509 -key private/cakey.pem -days 3650 -out cacert.pem
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) [XX]:CN # 国家,使用国家的ISO 2代码
State or Province Name (full name) []:Zhejiang # 省
Locality Name (eg, city) [Default City]:Hangzhou # 市
Organization Name (eg, company) [Default Company Ltd]:test # 组织(公司)名
Organizational Unit Name (eg, section) []:test # 组织单位(部门)名
Common Name (eg, your name or your server's hostname) []:test.com #使用该证书的域名
Email Address []: # 邮箱,可以不填
[root@linux2 CA]#
选项说明
req 生成证书请求
-new: 生成新的证书签署请求
-x509: 专用于CA生成自签名证书
-key: 生成请求时的私钥
-days: 证书的有效期
-out: 证书的路径及名称
查看证书信息
openssl x509 -in /etc/pki/CA/cacert.pem -noout -text
需要注意的是,由于这是自签名证书,通常不受浏览器和客户端的信任,所以在使用是记得将其添加到【受信任的根证书颁发机构】之类的地方去
2.3.2 为用户颁发证书
生成给用户的私钥
[root@linux2 CA]# openssl genrsa -out /etc/ssl/test.key
Generating RSA private key, 2048 bit long modulus (2 primes)
...................................+++++
...............................+++++
e is 65537 (0x010001)
[root@linux2 CA]#
生成证书请求文件
[root@linux2 CA]# openssl genrsa -out /etc/ssl/test.key
Generating RSA private key, 2048 bit long modulus (2 primes)
...................................+++++
.......+++++
e is 65537 (0x010001)
[root@linux2 CA]# openssl req -new -key /etc/ssl/test.key -out /etc/ssl/test.csr
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) [XX]:CN
State or Province Name (full name) []:Zhejiang
Locality Name (eg, city) [Default City]:Hangzhou
Organization Name (eg, company) [Default Company Ltd]:test
Organizational Unit Name (eg, section) []:test
Common Name (eg, your name or your server's hostname) []:linux2.test.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[root@linux2 CA]#
签发证书
[root@linux2 CA]# openssl ca -in /etc/ssl/test.csr -out /etc/ssl/test.crt -days 1825Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Aug 6 12:07:20 2024 GMT
Not After : Aug 5 12:07:20 2029 GMT
Subject:
countryName = CN
stateOrProvinceName = Zhejiang
organizationName = test
organizationalUnitName = test
commonName = linux2.test.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
C6:24:43:01:A1:DD:17:ED:1B:F9:A8:B7:2F:4E:4E:6C:26:7A:70:B0
X509v3 Authority Key Identifier:
keyid:75:06:3A:B5:19:6F:93:BE:90:6D:24:88:54:0E:53:27:7E:49:78:35
Certificate is to be certified until Aug 5 12:07:20 2029 GMT (1825 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
[root@linux2 CA]#
签发的证书会同时在/etc/pki/CA/newcerts目录下生成一个副本,编号就是serial这个文件中的数字
同时index.txt文件中也对签发的证书进行了记录
[root@linux2 CA]# diff /etc/pki/CA/newcerts/01.pem /etc/ssl/test.crt
[root@linux2 CA]# cat index.txt
V 290805120720Z 01 unknown /C=CN/ST=Zhejiang/O=test/OU=test/CN=linux2.test.com
[root@linux2 CA]#
2.3.3 吊销证书
查看证书的serial
Command:
openssl x509 -in <filename> -noout -serial -subject
Eg:
[root@linux2 CA]# openssl x509 -in /etc/ssl/test.crt -noout -serial -subject
serial=01
subject=C = CN, ST = Zhejiang, O = test, OU = test, CN = linux2.test.com
[root@linux2 CA]#
查看证书状态
Command:
openssl ca -status <serial>
Eg:
[root@linux2 CA]# openssl ca -status 01
Using configuration from /etc/pki/tls/openssl.cnf
01=Valid (V)
[root@linux2 CA]#
吊销证书
[root@linux2 CA]# openssl ca -revoke /etc/pki/CA/newcerts/01.pem
Using configuration from /etc/pki/tls/openssl.cnf
Revoking Certificate 01.
Data Base Updated
[root@linux2 CA]# cat /etc/pki/CA/index.txt
R 290805120720Z 240806124812Z 01 unknown /C=CN/ST=Zhejiang/O=test/OU=test/CN=linux2.test.com
[root@linux2 CA]#
创建用于存放证书吊销列表编号的文件
[root@linux2 CA]# echo 01 > /etc/pki/CA/crlnumber
[root@linux2 CA]#
更新证书吊销列表
[root@linux2 CA]# openssl ca -gencrl -out /etc/pki/CA/crl.pem
Using configuration from /etc/pki/tls/openssl.cnf
[root@linux2 CA]#
3、openssl 生成证书步骤
下载opens ssl并安装:http://slproweb.com/products/Win32OpenSSL.html 官网地址
一、生成证书标准流程
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
- 生成 私钥(.key)
- 用 私钥 生成 证书请求 (.csr)
- 将证书请求文件(.csr)提交给证书颁发机构(CA),CA会对提交的证书请求中的所有信息生成一个摘要,然后使用CA根证书对应的私钥进行加密,这就是所谓的“签名”操作,完成签名后就会得到真正证书
openssl生成证书
1、生成一个 2048 位的 RSA 私钥
openssl genrsa -out private.key 2048
2、使用私钥来生成新的证书签名请求(.csr)
openssl req -new -key private.key -out private.csr -subj "/C=CN/ST=shanghai/L=shanghai/O=example/OU=it/CN=domain1/CN=domain2"
-new 表示创建一个新的证书请求;
-key 后面跟着的是私钥文件;
-out 后面是输出的CSR文件;
-subj 是请求中的主题信息。你将被要求提供一些信息,如你的国家、省份、城市、组织名称等。这些信息将包含在你的证书中。
/C= 是证书的国家代码。
/ST= 是州或省份名称。
/L= 是城市名称。
/O= 是组织名称。
/OU= 是组织单位名称。
/CN= 是通用名称,通常是域名。
/emailAddress= 是电子邮件地址。
3、有了私钥和证书签名请求后,我们可以选择做3件事:
3.1. 标准CA签发流程
将证书请求(.csr)提交给CA认证机构申请证书(.crt);
CA机构会用他的根证书对应的私钥来签名(由CA机构操作);
3.2. 生成自签名证书
可以看到标准CA签发流程是用CA机构的私钥去签名。而自签名证书是用自己的私钥签署自己的证书请求,生成自签名SSL证书。
注意: 自签名证书不会被浏览器信任,只能用于内部或测试用途。如果你需要一个可被浏览器信任的证书,你需要从受信任的证书颁发机构(CA)获取签名证书 。
openssl x509 -req -in private.csr -out private.crt -signkey private.key -days 365
- openssl x509 -req 表示签名请求,生成证书。
- in private.csr 表示输入的CSR文件名。
- out private.crt 表示输出的CRT文件名。
- signkey private.key 表示用于签名的私钥文件名。
- days 表示证书的有效期。
生成的证书格式默认是 PEM,即 Privacy Enhanced Mail,它是 Base64 编码的 ASCII 码文件,常用于存储证书和密钥。PEM 格式的证书通常以 -BEGIN CERTIFICATE- 开始,以 -END CERTIFICATE- 结束,如图:
3.3 .私有CA签发证书
如果我们把3.2生成自签名证书(ca.crt)和私钥(ca.key)当作私有的CA机构,然后签署其他的证书签名请求,生成私有CA签名的证书,这个过程,可以理解为是私有CA签发证书。
CA签名证书命令:
- ca.key就是3.2的private.key;
- ca.crt就是3.2的private.crt;
- server.csr就是我们需要签名的证书请求
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365
-req 表示要处理的输入文件是一个证书签名请求(CSR)。
-in server.csr 表示要处理的CSR文件名为server.csr。
-CA ca.crt 表示CA的证书文件名为ca.crt。
-CAkey ca.key 表示CA的私钥文件名为ca.key。
-CAcreateserial 表示如果CA的证书和私钥不存在,则创建它们。
-out server.crt 表示生成的服务器证书输出文件名为server.crt。
二、其他命令
1、使用私钥生成对应的公钥
openssl rsa -in private.key -pubout -out public.pub
2、从证书中提取公钥
openssl x509 -pubkey -noout -in private.crt > public_key.pem
4、OpenSSL 生成CA证书和自签名证书
正文
一、安装OpenSSL工具
CentOS/RHEL系统:
yum install openssl openssl-devel
Ubuntu/Debian系统:
sudo apt-update
sudo apt-get install openssl libssl-dev
二、制作证书
证书相关名词解释:
- CA:Certification Authority,翻译为证书机构,负责给各个网站颁发证书。(每个电脑都会内置13个根证书机构的证书,并无条件相信这13个证书机构)
- CSR:Certificate Signing Request,即证书签名请求。用户向ca申请证书的时候,需要提交的信息。一般会包含网站域名、用户邮箱、所在国家地区、组织名称等等信息
- 申请证书,或者签发证书,即ca首先使用特定的摘要算法计算出csr的摘要,再用自己的私钥给摘要进行加密后得到的签名,最后将以上所有信息打包为一个特定格式的文件(也就是证书)
- cert:Certificate,即证书。一个特定格式的文件,里面包含了csr中部分信息、摘要生成算法、tls拓展支持、ca给csr的指纹信息(也翻译为签名)等。
- key:一般指openssl生成的密钥文件,其中包含了公钥和私钥。
- 验证证书合法:指客户端首先从cert中读取该证书的签发ca(这里会涉及到证书链的问题,暂时可简单理解为,所有证书都是根证书机构签发),然后使用该ca的公钥去解密证书的签名(非对称加密,私钥加密,公钥解密),获得摘要信息A;然后使用证书中指定的摘要算法计算证书的摘要B;第三步判摘要A是否和摘要B相等。
- tls单向认证:一般指客户端会验证服务端所提供的证书是否合法(访问https的网页就是用的这个,用的很广泛)。
- tls双向认证:在单项认证基础上,服务端也会验证客户端的证书是否合法(相对少见,目前只有docker daemon开启tls后才会使用)。
2.1、生成CA证书
(1)创建证书索引文件和序列号文件
因后面生成证书时使用到了openssl配置文件/etc/pki/tls/openssl.cnf,所以要提前创建,如果不使用 -config /etc/pki/tls/openssl.cnf
选项,可以不用此步。
touch /etc/pki/CA/index.txt
echo "00" > /etc/pki/CA/serial
(2)生成私钥
openssl genrsa -des3 -out rootCA.key 2048
(3)生成CA证书
openssl req -x509 -sha256 -new -nodes -key rootCA.key -days 3650 -out rootCA.crt -subj "/C=cn/ST=gd/L=sz/O=hw/OU=hc/CN=rootCA" -config /etc/pki/tls/openssl.cnf
C=单位的两字母国家代码
ST=州或省份名称
L=城市或区域名称
O=组织名称
OU=组织单位名称
CN=域名或者名字与姓氏
2.2、生成服务端证书
(1)生成私钥
openssl genrsa -out server.key 2048
(2)生成证书请求(CSR)
openssl req -new -key server.key -out server.csr -subj "/C=cn/ST=gd/L=sz/O=hw/OU=hc/CN=192.168.3.3" -config /etc/pki/tls/openssl.cnf
国家(C)、省份(ST)、组织(O)必需和CA证书里的相同,不然后面签发会报错。
(3)签发证书
方式一(openssl x509命令签发,不使用配置文件/etc/pki/tls/openssl.cnf):
openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -in server.csr -out server.crt -days 3650
openssl x509命令具以下的一些功能,例如输出证书信息,签署证书请求文件、生成自签名证书、转换证书格式等。openssl x509工具不会使用openssl配置文件中的设定,而是完全需要自行设定或者使用该伪命令的默认值,它就像是一个完整的小型的CA工具箱。
方式二(openssl ca命令签发 使用配置文件/etc/pki/tls/openssl.cnf):
openssl ca -cert rootCA.crt -keyfile rootCA.key -in server.csr -out server.crt -days 3650 -config /etc/pki/tls/openssl.cnf
(4)查看证书相关命令
#查看证书信息
openssl x509 -in server.crt -noout -text
#查看证书subject和issuer信息
openssl x509 -in server.crt -noout -subject -issuer
#验证证书状态是否正常
openssl verify -CAfile rootCA.crt user01.crt
2.3、生成客户端证书
(1)生成私钥
openssl genrsa -out client.key 2048
(2)生成证书请求(CSR)
openssl req -new -key client.key -out client.csr -subj "/C=cn/ST=gd/L=sz/O=hw/OU=hc/CN=test" -config /etc/pki/tls/openssl.cnf
(3)签发证书
方式一(openssl x509命令签发,不使用配置文件/etc/pki/tls/openssl.cnf):
openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -in client.csr -out client.crt -days 3650
方式二(openssl ca命令签发 使用配置文件/etc/pki/tls/openssl.cnf):
openssl ca -cert rootCA.crt -keyfile rootCA.key -in client.csr -out client.crt -days 3650 -config /etc/pki/tls/openssl.cnf
2.4、吊销证书
吊销证书需要使用默认的配置文件/etc/pki/tls/openssl.cnf,当然也可以复制一份openssl.cnf文件,自己改一下配置也可。这里使用默认的配置文件/etc/pki/tls/openssl.cnf。
(1)创建crlnumber文件
echo "00" > /etc/pki/CA/crlnumber
(2)生成CRL
openssl ca -gencrl -cert rootCA.crt -keyfile rootCA.key -out rootCA.crl -config /etc/pki/tls/openssl.cnf
(3)吊销证书
openssl ca -cert rootCA.crt -keyfile rootCA.key -revoke user01.crt -config /etc/pki/tls/openssl.cnf
(4)更新CRL
openssl ca -gencrl -cert rootCA.crt -keyfile rootCA.key -out rootCA.crl -config /etc/pki/tls/openssl.cnf
(5)查看CRL信息,可以看到吊销的证书信息
openssl crl -in rootCA.crl -noout -text
参考文档:
Linux系统搭建私有CA证书服务器 - Linux-1874 - 博客园
openssl自签名证书 - jiayou111 - 博客园
openssl 命令 生成与吊销证书示例 生成CA证书 客户端证书 服务器证书 用CA签名客户服务器的CSR证书_openssl 吊销证书-CSDN博客
OpenSSL证书的建立、自签和吊销_自签ssl吊销-CSDN博客
openssl 命令(3): openssl x509命令详解_openssl x509 -req -days-CSDN博客
在Linux下如何根据域名自签发OpenSSL证书与常用证书转换 - 踏歌行666 - 博客园
https://zhuanlan.zhihu.com/p/687335362
5、OpenSSL 创建用户证书实战案例详解!
创建用户证书 User Cert
现在,我们终于来到证书链的最下层,用户证书,也叫实体证书(end-entity certificate)。这就是我们平常最常见到的网站的数字证书了,它是支撑 HTTPS 协议的基础设施之一。
要创建 User Cert,我们需要与它的签发机构,也就是 Intermediate CA 进行交互。
下面是目录框架示意图:
可以看到,我用两个平行(而不是层级)的目录来管理 Intermediate CA 和 User Certs。 并且,我在 user_certs
目录下为不同的 Web Service 所需的证书创建了单独的目录。
操作要点
首先,逻辑和步骤与我们之前用 Root CA 签发 Intermediate CA 证书的过程是一样的。 同样是三个步骤:
- 创建 Private Key + Password file
- 创建 CSR
- CA 对 CSR 签名,签发最终证书
主要的区别在于参数配置不一样,比如每个不同的网站的扩展信息不一样(主要是 subjectAltName,也叫 SAN)。
实战案例
现在假设,我们访问 echo 服务,它同时支持 echo1.example.com
和 echo2.example.com
和泛域名 *.example.com
,还支持 IP 地址访问。
进入 user_certs/echo
目录:
cd user_certs/echo
(1) 创建密码文件和私钥
创建密码文件
openssl rand -base64 32 > private/password.txt
创建私钥(RSA 算法)
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out rsa_echo.key
openssl pkcs8 -topk8 -v2 aes256 -iter 100000 -passout file:private/password.txt \
-in rsa_echo.key -out private/rsa_echo_encrypted.key
shred -u rsa_echo.key
检查私钥
openssl asn1parse -in private/rsa_echo_encrypted.key
(2) 创建 CSR
i) 配置信息
req_csr.cnf
[ req ]
default_bits = 4096
default_keyfile = rsa_encrypted.key
distinguished_name = req_distinguished_name
x509_extensions = v3_intermediate_ca
prompt = no
[ req_distinguished_name ]
C = US
ST = TX
O = echo service
CN = echo service
[x509_v3_ext]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
keyUsage = digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = clientAuth,serverAuth
subjectAltName = @alt_names
[alt_names]
IP.1 = 10.10.0.100
DNS.1 = echo1.example.com
DNS.2 = echo2.example.com
DNS.3 = *.example.com
ii) 创建 CSR
openssl req -new \
-passin file:private/password.txt \
-config req_csr.cnf \
-reqexts x509_v3_ext \
-key private/rsa_echo_encrypted.key \
-out rsa_echo.csr
iii) 检查 CSR
openssl req -text -noout -in rsa_echo.csr
现在有了 .csr
文件,int_ca
就可以对其签发证书了。
切换到 int_ca
目录进行操作
(1) 在 int_ca
中创建必要文件和目录
cd ../../int_ca
mkdir -pv newcerts
touch index.txt
echo -ne "00" > serial
echo -ne "00" > crlnumber
(2) 准备配置信息
使用 int_ca
的私钥为 echo
签发证书之前,我们需要再检查一下 int_ca
的各项配置参数是否符合我们的要求:
ica.cnf
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = .
certs = $dir/certs
crl_dir = $dir/crl
database = $dir/index.txt
new_certs_dir = $dir/newcerts
private_key = $dir/CA/private/rsa_encrypted.key
certificate = $dir/CA/rsa_int_ca.crt
serial = $dir/serial
crlnumber = $dir/crlnumber
default_md = sha256
default_days = 3650
default_crl_days = 30
policy = policy_match
copy_extensions = copy
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = optional
organizationalUnitName = optional
commonName = supplied
由于之前在生成 CSR 时,已写入了 v3_intermediate_ca
字段中的信息。因此,我们在使用 int_ca
给其签发证书的时候,可以直接设置 copy_extensions = copy
,它表示 int_ca
签署时会直接拷贝 CSR 中的扩展信息,不做任何改变。
不过,如果我们需要为即将要签发的证书定制 v3 extension,我们可以在 ica.cnf
中增加一个段落 [v3_ext_echo]
,然后在执行命令时用 -extension
选项来指定这个段落。
[v3_ext_echo]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
keyUsage = digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = clientAuth,serverAuth
subjectAltName = @alt_names
[alt_names]
IP.1 = 10.10.0.100
DNS.1 = echo1.example.com
DNS.2 = echo2.example.com
DNS.3 = *.example.com
推荐用 copy 的方式,省事。
(3)签发证书
openssl ca
和 openssl x509
两个命令都可以用来签发证书,区别在于前面的 ca 命令有数据库对所签发的证书进行记录(比如 serial, crlnumber 等),而后面的 x509 命令则适用于 ad-hoc 证书的签发,不管理数据库,不记录签发了哪些证书,所以只适合需要一次性证书(比如自签名证书)并且不负责任何后续管理的场景。
由于我们这里专注于证书链系统的构建,所以我们一律使用 openssl ca
命令来构建和管理证书。
注意:签发证书是在 int_ca
目录中操作!
执行命令:
openssl ca -days 365 -notext \
-config ica.cnf \
-cert CA/rsa_int_ca.crt \
-keyfile CA/private/rsa_encrypted.key \
-passin file:CA/private/password.txt \
-in ../user_certs/echo/rsa_echo.csr \
-out ../user_certs/echo/rsa_echo.crt
注:用户证书通常在一年以内,甚至更短。
输出结果:
补充:
如果想由 int_ca
指定 v3 extension 而不是 copy,我们可以这么做:
- 创建一个单独的文件(如
v3_ext_echo.cnf
),在里面的段落[ v3_ext_echo ]
中填上相应内容。 - 或者直接在
ica.cnf
中增加一个段落[ v3_ext_echo ]
,填上相应内容。
然后执行下面的命令:
openssl ca -days 365 -notext \
-config <(cat ica.cnf v3_ext_echo.cnf) \
-extensions v3_ext_echo \
-cert CA/rsa_int_ca.crt \
-keyfile CA/private/rsa_encrypted.key \
-passin file:CA/private/password.txt \
-in ../user_certs/echo/rsa_echo.csr \
-out ../user_certs/echo/rsa_echo.crt
新证书会生成在 newcerts/
目录中,默认名字是 serial 编号。比如初始的 serial 是 00,那么签发的第一个证书就是 newcerts/00.pem,serial 文件中会变成 01。
index.txt
中也会增加一条记录,如下:
V 251030162019Z 00 unknown /C=US/ST=TX/O=echo service
(4) 检查证书
进入 user_certs/echo
目录
cd user_certs/echo
openssl x509 -text -noout -in newcerts/00.pem
全文完!
下集预告:使用 echo 证书:用 Nginx 搭建 HTTPS 服务器
6、Windows系统使用OpenSSL生成自签名证书
Nginx服务器添加SSL证书。
要在Windows系统的Nginx Web服务器上使用OpenSSL生成证书,并确保该证书能在局域网内被计算机信任,你可以按照以下详细步骤进行操作:
一、生成证书
下载并安装OpenSSL:
从OpenSSL的官方网站下载适用于Windows的版本。
安装OpenSSL,并配置环境变量。将OpenSSL的安装路径(例如C:\Program Files\OpenSSL-Win64\bin)添加到系统的Path环境变量中。
到这里下载需要的OpenSSLWin32/Win64 OpenSSL Installer for Windows - Shining Light Productions
生成服务器私钥:
打开命令提示符(CMD),切换到你想保存证书的目录。
执行以下命令生成服务器私钥(server.pem和server.key):
openssl genrsa -out server.pem 2048
openssl rsa -in server.pem -out server.key
生成证书签名请求(CSR):
- 执行以下命令生成CSR文件(
server.csr
):
openssl req -new -key server.key -out server.csr -subj "/C=CN/ST=YourState/L=YourCity/O=YourOrganization/OU=YourUnit/CN=YourServerName"
注意将/C=CN/ST=YourState/L=YourCity/O=YourOrganization/OU=YourUnit/CN=YourServerName中的占位符替换为你的实际信息。其中CN(Common Name)必须是你希望证书绑定的域名或IP地址,在局域网中通常是服务器的IP地址或局域网内的域名。
生成自签名SSL证书:
执行以下命令生成自签名SSL证书(server.crt):
openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
生成PFX证书(可选,但Windows常用):
- 如果你希望将证书和私钥打包成一个PFX文件,可以执行以下命令:
openssl pkcs12 -export -in server.crt -inkey server.key -out server.pfx -name server
7、使用 OpenSSL 搭建三级证书体系(RSA)
三级证书体系结构
目录结构
证书虽然在概念上有层级,但是为了方便实际的管理,每级证书使用有独立的目录。
换句话说,虽然各证书在概念上是有层级的,但是物理目录上应该使用平级的结构,而不是层级或树状的结构。
mkdir allcerts
cd allcerts
mkdir -p {CSTrust_RSA_CA, CSTrust_RSA_ICA, CSTrust_RSA_Users}
1. 创建 Root CA(自签名证书)
1.1 创建目录及基础文件
目录结构:
按照上图创建目录与文件
cd CSTrust_RSA_CA
mkdir -p CA/private newcerts crl
touch index.txt
echo -ne "00" > serial
echo -ne '00' > crlnumber
touch req_rootca.cnf
1.2 创建私钥
(1) 创建密码文件
密码是用来保护私钥的,把私钥进行加密防止被别人访问。
openssl rand -base64 32 > CA/private/password.txt
chmod 600 CA/private/password.txt
(2) 创建私钥(RSA)
openssl genpkey -algorithm RSA \
-aes256 -pkeyopt rsa_keygen_bits:4096 \
-pass file:CA/private/password.txt \
-out CA/private/rsa_encrypted.key
(3) 检查
openssl asn1parse -in CA/private/rsa_encrypted.key
(4) 去除密码保护
如果需要去除密码保护,可以使用如下命令:
openssl pkcs8 -in CA/private/rsa_encrypted.key \
-out CA/private/rsa_decrypted.key \
-passin file:CA/private/password.txt
1.3 创建证书(自签名)
我们创建的是最顶层的根证书,因此是自签名证书,自己授权自己被所有人信任。
使用 openssl req -x509
命令,所以我们需要填写配置信息中的 [ req ]
段落。
(1) 配置文件
在 req_rootca.cnf
中填入如下内容:
[ req ]
default_keyfile = rsa_decrypted.key # Default private key filename
prompt = no # Disable prompt
distinguished_name = req_dn
x509_extensions = v3_ca # Extensions for self-signed root CA certificate
[ req_dn ]
C = US
ST = TX
O = Sec Homelab
OU = IT Network
CN = CSTrust Root CA (RSA)
[ v3_ca ]
basicConstraints = critical, CA:true
keyUsage = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
(2) 自签名创建
openssl req -new -x509 -days 7300 -sha256 \
-key CA/private/rsa_encrypted.key \
-config req_rootca.cnf \
-passin file:CA/private/password.txt \
-out CA/rsa_rootca.pem
(3) 目录结构
创建完成后,目录内容如下:
(4) 检查
openssl x509 -noout -text -in CA/rsa_rootca.pem
1.5 根证书导入操作系统
我们需要把 Root CA 证书导入操作系统,被系统信任。
(1) Linux
把根证书复制到系统证书目录(Trusted Directory),然后更新系统记录。
sudo cp CA/rsa_rootca.pem /usr/local/share/ca-certificates/CSTrust_RSA_CA.crt
sudo update-ca-certificates
解释: update-ca-certificates
命令会把扫描 /usr/local/share/ca-certificates/
目录,并把其中所有根证书都安装到 /etc/ssl/certs/
目录中。
(2) MacOS
(i) GUI 导入
打开 Keychain 应用:File → Import Items. 选择 System,然后添加我们上面生成的 Root CA 证书(rsa_rootca.pem
) 添加完成后,我们需要信任该证书。right-click → Get Info → Alway Trust
(ii) 命令行导入
使用 security 命令
sudo security add-trusted-cert -d -r trustRoot -k \
/Library/Keychains/System.keychain rsa_rootca.pem
解释:
- -d: default,表示默认被系统中的所有用户信任。
- -r trustRoot,表示要添加的证书为根证书
- -k keychain,表示添加到 system keychain(可以被所有用户访问)
(3) Windows
2. 创建 Intermediate CA
Intermediate CA 证书也属于 CA,可以向下签发用户证书。下面我们简称 ICA。
制作 ICA 之前,我们先准备目录和相关配置文件。
- ICA 证书由 Root CA 所签发,所以需要创建 CSR 请求文件。
- ICA 作为 User Certs 的签发机构,需要证书管理文件(serial, index.txt 和 crlnubmer)
2.1 创建目录及基础文件
目录结构:
按照上述结构来创建相关目录和文件
cd CSTrust_RSA_ICA
mkdir -pv CA/private newcerts crl
echo -ne "00" > serial
echo -ne '00' > crlnumber
touch req_ica.cnf
步骤简介:
下面是我们创建中间证书的大致步骤:
- (a) 创建 ICA 的 Private Key
- (b) 创建 ICA 的 CSR
- (c) 使用 rootca 对 CSR 签名,从而创建出
rsa_ica.crt
2.2 创建私钥
(1) 创建密码文件
openssl rand -base64 32 > CA/private/password.txt
chmod 600 CA/private/password.txt
(2) 创建私钥(RSA)
openssl genpkey -algorithm RSA \
-aes256 -pkeyopt rsa_keygen_bits:4096 \
-pass file:CA/private/password.txt \
-out CA/private/rsa_encrypted.key
如果想增加 KDF 迭代次数来增加密钥强度,命令如下:
openssl pkcs8 -topk8 -v2 aes256 -iter 100000 \
-passin file:CA/private/password.txt \
-passout file:CA/private/password1.txt \
-in CA/private/rsa_encrypted.key \
-out CA/private/rsa_encrypted_enhanced.key
注:-passin
和 -passout
必须用不同的密码。
(3) 检查私钥
openssl asn1parse -in CA/private/rsa_encrypted.key
(4) 去除密码保护
如果需要去除密码保护,可以使用如下命令:
openssl pkcs8 -in CA/private/rsa_encrypted.key \
-out CA/private/rsa_decrypted.key \
-passin file:CA/private/password.txt
2.3 创建 CSR 请求
(1) CSR 配置文件
ICA 需要向 Root CA 发起 CSR 请求,使用 openssl x509 -req
命令,因此,我们需要填写配置文件中的 [ req ]
段落的信息。
向 req_ica.cnf
中填入如下内容:
[ req ]
default_bits = 4096
default_keyfile = rsa_encrypted.key
distinguished_name = req_distinguished_name
x509_extensions = v3_ica
prompt = no
[ req_distinguished_name ]
C = US
ST = CA
O = ICA-Security-Lab
OU = Internete-Security
CN = CSLab ICA # Common Name
[ v3_ica ]
basicConstraints = critical, CA:TRUE, pathlen:0
keyUsage = critical, keyCertSign, cRLSign, digitalSignature
extendedKeyUsage = serverAuth, clientAuth
subjectKeyIdentifier = hash
# authorityKeyIdentifier = keyid:always,issuer:always
解释:
pathlen 定义了当前证书可以签发多少层下级证书。
- 未 pathlen,则无限制。此时默认为 -1
- pathlen:0 表示只能签发用户证书(User Certificate,也叫 end-entity certificate),不能签发 Intermediate 证书。
- pathlen:1 表示只能签发一层 Intermediate 证书,即当前的 CA 证书与用户证书之间,最多只能有一层中间证书。
- pathlen:2 以此类推,当前证书与用户证书之间,可以有两层中间证书。
- Intermediate 证书的 pathlen 一般设置为 0 或 1,证书链不宜太长。
(2) 创建 CSR 对象 (rsa_ica.csr
)
openssl req -new \
-config req_ica.cnf \
-reqexts v3_ica \
-passin file:CA/private/password.txt \
-key CA/private/rsa_encrypted.key \
-out rsa_ica.csr
也可以用命令行来指定 DN (Distinguished Name) 信息:
openssl req -new -passin file:CA/private/password.txt \
-config req_ica.cnf \
-reqexts v3_ica \
-subj="/C=US/ST=CA/O=ICA-Security-Lab/OU=Internete-Security/CN=CSLab ICA" \
-key CA/private/rsa_encrypted.key \
-out rsa_ica.csr
注意:
- 只有添加了
-reqexts
选项,CSR 中才会写入 v3 extension 信息。
(3) 检查 CSR 对象
openssl req -text -noout -in rsa_ica.csr
检查的主要目的是确认 CSR 中保存了 v3 扩展信息。
2.4 签发 ICA 证书
使用 Root CA 对 rsa_ica.csr
签名,即可生成 ICA 证书。
(1) rootca.cnf
配置信息
使用 openssl ca
命令,因此,我们需要填写 [ ca ]
字段中的配置信息。
回到 CSTrust_RSA_CA/
目录:
cd ../CSTrust_RSA_CA
在 rootca.cnf
中填入如下信息:
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = .
certs = $dir/certs
crl_dir = $dir/crl
database = $dir/index.txt
new_certs_dir = $dir/newcerts
private_key = $dir/CA/private/rsa_encrypted.key
certificate = $dir/certs/rsa_rootca.pem
serial = $dir/serial
crlnumber = $dir/crlnumber
default_md = sha256
default_days = 3650
default_crl_days = 30
policy = policy_ica
copy_extensions = copy
[ policy_ica ]
countryName = match # 必须与 Issuer 相同
stateOrProvinceName = supplied # 不必与 Issuer 相同,但必须提供
organizationName = supplied # 同上
organizationalUnitName = optional # 可有可无
commonName = supplied # 不必与 Issuer 相同,但必须提供
解释:
(i) copy_extensions
由于生成 CSR 时,已写入了 v3_ica
字段中的信息。因此,我们在使用 rootca
给其签发证书的时候,可以直接设置 copy_extensions = copy
,它表示 rootca
签署时会直接拷贝 CSR 中的扩展信息,不做任何改变。
copy_extensions 的可选值是:
- copy
- copyall
- none (默认值,不 copy)
不过,如果 Root CA 想要为签发的证书定制 v3 extension,我们可以把信息保存在一个单独文件中,然后用 -extension
选项来指定。
比如我们在 Root CA 的目录中保存为 CSTrust_RSA_CA/ICA1/csr_ext.cnf
,里面填入如下内容:
[ v3_ica ]
basicConstraints = critical, CA:TRUE, pathlen:0
keyUsage = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
推荐使用 copy 的方式,这样管理起来方便很多。否则,rootca
改变了 v3 extension 的话,事后可能不好管理。
(ii) policy_ica
我们根据需要来调整对 ICA 的 DN(Distinguished Name) 的要求,比如要求国家名称必须相同,州名(或省名)必须提供之类的。如果 CSR 中的 DN 信息与 CA 所要求的 Policy 不匹配,那么在执行 openssl ca
命令签名时就会失败。
(2) 为 ICA 签发证书
openssl ca
和 openssl x509
两个命令都可以用来签发证书,区别在于前面的 ca 命令会使用 ROOT CA 的数据库对所签发的证书进行记录(比如 serial, crlnumber 等);而后面的 x509 命令则适用于 ad-hoc 证书的签发,不管理数据库,不记录签发了哪些证书,所以只适合需要一次性证书(比如自签名证书)并且不负责下级证书管理的场景。
由于我们这里专注于证书链系统的构建,所以我们一律使用 openssl ca
命令来签发和管理证书。
签发证书的动作是在 Root CA 目录(CSTrust_RSA_CA/
)执行的:
openssl ca -days 3650 -notext -batch \
-config rootca.cnf \
-cert CA/rsa_rootca.pem \
-keyfile CA/private/rsa_encrypted.key \
-passin file:CA/private/password.txt \
-in ../CSTrust_RSA_ICA/rsa_ica.csr \
-out ../CSTrust_RSA_ICA/CA/rsa_ica.crt
解释: 这里使用 -batch
选项可以避免交互。如果没有这个选项,命令执行过程中会询问你 "Sign the certificate? [y/n]"
,你必须作答。
(3) 检查证书
(i) 检查 Root CA 目录
Root CA 签发下级证书之后,会在其目录中更新相关文件。
newcerts/
新证书会生成在newcerts/
目录中,默认名字是 serial 编号。比如初始的 serial 是 00,那么签发的第一个证书就是newcerts/00.pem
,serial 文件中内容会由原来的 00 变成 01。
index.txt
中也会增加一条记录,如下:
V 341231220257Z 00 unknown /C=US/ST=CA/O=ICA-Security-Lab/OU=Internete-Security/CN=CSLab ICA
crlnumber
由于还没有撤销过证书,crlnumber 文件中的值依然是 00。
(i) 检查 ICA 证书
接下来,我们要检查证书
openssl x509 -text -noout -in newcerts/00.pem
或者
openssl x509 -text -noout -in ../CSTrust_RSA_CA/ICA/rsa_ica.crt
目录结构
把 ICA
证书导入系统
Intermediate CA 是我们最常使用的根证书,因为所有的用户证书都由它签发。 为了方便使用,建议把该 ICA 证书导入到操作系统的根证书目录中去。
至此,证书链中的 Root CA 和 Intermediate CA 我们就搭建好了。
接下来,我们就可以使用 Intermediate CA 来签发用户证书。
全文完!
8、全面解析!用户证书的使用,用 Nginx 容器搭建 HTTPS 服务器。
简介
前面的系列文章,我们已经创建了用户证书,这篇文章,我们继续用案例的方式来演示如何使用用户证书来搭建 HTTPS 服务。
HTTPS 原理介绍
HTTPS 是一种用于在浏览器和服务器之间传输数据的安全协议,它通过加密确保数据在传输中不被第三方窃取或篡改。 数字证书是由权威机构颁发的(如 DigiCert、Let's Encrypt)的电子文件,它包含了网站的公钥和真实身份信息,用来证明是网站的拥有者。
当用户访问一个 HTTPS 网站时,以下步骤确保了通信的安全:
- 证书验证:用户打开浏览器输入网址时,浏览器会自动请求并接收网站的数字证书。浏览器会检查证书是否由可信的证书颁发机构签发,确保真实性。
- 建立加密连接:在验证了服务器的身份后,浏览器和服务器使用证书中的公钥来加密一段“会话密钥”,并将该密钥用于后续的数据加密。
- 数据加密传输:在整个会话过程中,浏览器和服务器使用这个会话密钥加密数据,确保数据只能被双方解读,保护隐私。
可以看到,数字证书不仅帮助验证网站的身份,还提供了“会话密钥”来加密双方的通信内容,避免被第三者窃听; 它能很好地防止中间人攻击等问题极大地提高用户访问网站时的安全性。这也是我们建立整个证书链的一个重要目的。
重点:
数字证书验证身份过程中,权威机构(CA)的证书是被我们操作系统已经信任的,网站服务在被浏览时所提供的证书是尚未被信任的。我们使用已信任的 CA 证书去校验未信任的 User 证书,当然,前提是它是由已信任的 CA 所签发。
所以第一步,要确保我们之前所创建的 root_ca
的证书已经被导入到访问者的系统证书库中。
Linux
sudo cp rsa_ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
MacOS
实战案例
我在服务器中使用 Nginx 搭建一个简单的 echo 服务来验证用户证书的使用。假设服务器是 Ubuntu 系统,我们用 Nginx 容器来为 echo 搭建 HTTPS 服务。
下面是 Nginx 容器 Volume 挂载的本地目录及文件信息:
登录服务器,
ssh <web-server>
创建一个目录保存 Nginx 相关的信息:
mkdir -pv docker/nginx/etc/conf.d
mkdir -pv docker/nginx/ssl/echo
创建 docker-compose 文件:
docker-compose.yml
services:
echo:
image: nginx:latest
container_name: nginx
restart: always
volumes:
- ./etc/conf.d:/etc/nginx/conf.d
- ./ssl:/etc/nginx/ssl
- ./www/html:/var/www/html
- ./log:/var/log/nginx
ports:
- 80:80
- 443:443
在 Nginx 配置文件目录中新建一个 echo 服务的配置文件
touch etc/conf.d/echo.conf
server {
listen 80;
listen [::]:80;
server_name echo1.example.com echo2.example.com
server_tokens off;
location / {
return 301 https://echo.example.com$request_uri;
}
}
server {
listen 443 default_server ssl http2;
listen [::]:443 ssl http2;
server_name *.example.com;
ssl_certificate_key /etc/nginx/ssl/echo/rsa_echo.pem;
ssl_certificate /etc/nginx/ssl/echo/fullchain.pem;
location / {
}
}
注意第二个 server
配置块中 ssl_certificate
和 ssl_certificate_key
两个字段的配置。
注:
我的三级证书系统是在工作主机(MacOS)上搭建的,这里为了方便演示,我把整个证书目录拷贝到了服务器主机(Ubuntu)上。 在实际场景中,我们通常还是在工作主机上(放在一个安全的位置)保存证书系统,方便管理。
假设当前在服务器的 $HOME 目录中,各目录结构如下:
ssl_certificate_key
字段
cp allcerts/user_certs/echo/rsa_echo.crt docker/nginx/ssl/echo/rsa_echo.pem
- ssl_certificate 字段。
cat allcerts/user_certs/echo/rsa_echo.crt allcerts/int_ca/CA/rsa_int_ca.crt > fullchain.pem
mv fullchain.pem docker/nginx/ssl/echo/fullchain.pem
解释:
ssl_certificate
表示的是网站的数字证书,如果签发该证书的 CA 机构已被系统信任(不管该机构是 Root CA 还是 Intermediate CA),那么 ssl_certificate 填该证书名就可以了。如下:
但是,这里的 rsa_echo.crt
是由 int_ca
签发的,而我们并没有把 int_ca
证书导入到系统证书库中,系统证书库只信任了 root_ca
。所以,这里,我们需要把 rsa_echo.crt
和 rsa_int_ca.crt
两个证书合并,这样,Root CA 才能根据证书链去一一验证这两个证书的合法性。
以此类推,如果中间有多个 Intermediate CA 并且都没有被添加到系统证书库中,那我们应该把这些证书都合并为一个,这样才能得到验证。 如下:
这里,我把合并后的证书起名为 fullchain.pem
是参考了 Let's Encrypt 的命名方式;也有命名方式,比如 Hashicorp Value 中就命名为 bundle.pem
。当然,你也可以根据自己的喜好起名,只要别与原名称造成混淆。
另外,由于我们映射了当前的 ./ssl
的目录到 Nginx 容器中的的 /etc/nginx/ssl
,所以我们直接把文件拷贝到 ./ssl/echo
中即可。
至此,配置完成,启动 Nginx 容器:
docker compose up -d
服务启动没问题之后,我们就可以在浏览器中输入类似 https://echo.example.com
这样的网址打开网页了。
查看网页所使用的证书:
全文完!