[TOC]

0x00 前言简述

描述:OpenSSL是一个开源项目,它是安全套接字层密码库(Secrue socket layer)和传输层安全(transport layer security,TLS)协议的实现,囊括主要的密码算法、常用的密钥证书封装管理功能及SSL协议(SSL/TLS工具集),并提供丰富的应用程序供测试或其它目的使用。

OpenSSL在这一领域已经成为事实上的标准,并且拥有比较长的历史,在OpenSSL被曝出现严重安全漏洞后,发现多数通过SSL协议加密的网站使用名为OpenSSL的开源软件包。由于这是互联网应用最广泛的安全传输方法,被网银、在线支付、电商网站、门户网站、电子邮件等重要网站广泛使用,所以该漏洞影响范围广大

现在几乎所有的服务器软件和很多客户端软件都在使用OpenSSL,其中基于命令行的工具是进行密钥、证书管理以及测试最常用到的软件了。

在很多情况下,我们需要在公司局域网内的网站中启用 HTTPS,比如测试环境或者是公司内网中的管理系统(现在主流的浏览器都把 HTTP 站点标记为不安全)。此时通过 OpenSSL 创建私有 CA 并颁发证书就是很好的选择了。

等待学习:
https://www.cnblogs.com/xdyixia/p/11673785.html
https://www.cnblogs.com/sparkdev/p/10369313.html



0x01 算法实现

1.对称加密算法
OpenSSL一共提供了8种对称加密算法,其中7种是分组加密算法,仅有的一种流加密算法是RC4(已经证明不安全)。
这7种分组加密算法分别是 AES、DES、Blowfish、CAST、IDEA、RC2、RC5,

四种常用的分组密码加密模式(上面七种):

  • 电子密码本模式(ECB)
  • 加密分组链接模式(CBC)
  • 加密反馈模式(CFB)
  • 输出反馈模式(OFB)

注意:

  • AES使用的加密反馈模式(CFB)和输出反馈模式(OFB)分组长度是128位,其它算法使用的则是64位。
  • DES算法里面不仅仅是常用的DES算法,还支持三个密钥和两个密钥3DES算法。

对称加密应用例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#用DES3算法的CBC模式加密文件plaintext.txt,加密结果输出到文件ciphertext.bin
openssl enc -des3 -salt -in plaintext.txt -out ciphertext.bin
#用DES3算法的CBC模式解密文件ciphertext.bin,提供的口令为trousers,输出到文件plaintext.doc
openssl enc -des-ede3-cbc -d -in ciphertext.bin -out plaintext.doc -pass pass:trousers


#用DES3算法的OFB模式解密文件ciphertext.bin,提供的口令为trousers,输出到文件plaintext.doc
openssl enc -des-ede3-ofb -d -in ciphertext.bin -out plaintext.doc -pass pass:trousers

#用Blowfish的CFB模式加密plaintext.doc,口令从环境变量PASSWORD中取,输出到文件ciphertext.bin。
openssl bf-cfb -salt -in plaintext.doc -out ciphertext.bin -pass pass:123456

#用RC5算法的CBC模式加密文件plaintext.doc,输出到文件ciphertext.bin,salt、key和初始化向量(iv)在命令行指定
#貌似已经更名或者不用RC5 给文件ciphertext.bin用base64编码,输出到文件base64.txt。
openssl rc5 -in plaintext.doc -out ciphertext.bin -S C62CB1D49F158ADC -iv E9EDACA1BD7090C6 -K 89D4B1678D604FAA3DBFFD030A314B29

#给文件ciphertext.bin用base64编码(类似于base64 filenames),输出到文件base64.txt。
openssl base64 -in ciphertext.bin -out base64.txt

WeiyiGeek.

WeiyiGeek.

注意事项:

  • 因为模式不同,该命令不能对以上的文件进行解密。


2.非对称加密算法
描述:OpenSSL一共实现了4种非对称加密算法,包括DH算法、RSA算法、DSA算法和椭圆曲线算法(EC)

  • DH算法一般用户密钥交换
  • RSA算法既可以用于密钥交换(如SSH密匙登录),也可以用于数字签名,当然如果你能够忍受其缓慢的速度,那么也可以用于数据加密
  • DSA算法则一般只用于数字签名

非对称加密应用例子应用例子

1
2
3
4
5
6
#DDiffie-Hellman应用例子
#1.使用生成因子2和随机的1024-bit的素数产生D0ffie-Hellman参数,输出保存到文件dhparam.pem
openssl dhparam -out dhparam.pem -2 1024

#2.从dhparam.pem中读取Diffie-Hell参数,以C代码的形式,输出到stdout
openssl dhparam -in dhparam.pem -noout -C

WeiyiGeek.

WeiyiGeek.


1
2
3
4
5
6
7
8
9
10
11
12
#DSA应用例子:
1.生成1024位DSA参数集,并输出到文件dsaparam.pem
openssl dsaparam -out dsaparam.pem 1024

2.使用参数文件dsaparam.pem生成DSA私钥匙,采用3DES加密后输出到文件dsaprivatekey.pem (需要输入密码 test
openssl gendsa -out dsaprivatekey.pem -des3 dsaparam.pem

3.使用私钥匙dsaprivatekey.pem生成公钥匙,输出到dsapublickey.pem (必修输入上面的密码)
openssl dsa -in dsaprivatekey.pem -pubout -out dsapublickey.pem

4.从dsaprivatekey.pem中读取私钥匙,解密并输入新口令进行加密,然后写回文件dsaprivatekey.pem(输入原有的密码和现在最新的密码)
openssl dsa -in dsaprivatekey.pem -out dsaprivatekey.pem -des3
WeiyiGeek.12

WeiyiGeek.12

WeiyiGeek.34

WeiyiGeek.34


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#RSA应用例子:
1.产生1024位RSA私匙,用3DES加密它,口令为trousers,输出到文件rsaprivatekey.pem
openssl genrsa -out rsaprivatekey.pem -passout pass:trousers -des3 1024

2.从文件rsaprivatekey.pem读取私匙,用口令trousers解密,生成的公钥匙输出到文件rsapublickey.pem
openssl rsa -in rsaprivatekey.pem -passin pass:trousers -pubout -out rsapublickey.pem

#3.使用公钥匙rsapublickey.pem加密文件plain.txt,输出到文件cipher.txt
openssl rsautl -encrypt -pubin -inkey rsapublickey.pem -in plain.txt -out cipher.txt
#3.用公钥匙rsapublickey.pem验证签名signature.bin,输出到文件plain.tct (decript)
openssl rsautl -verify -pubin -inkey rsapublickey.pem -in signature.bin -out plain.tct

#4.使用私钥匙rsaprivatekey.pem给文件plain.txt签名,输出到文件signature.bin (encrpty)
openssl rsautl -verify -pubin -inkey rsapublickey.pem -in signature.bin -out plain.tct
#4.使用私钥匙rsaprivatekey.pem解密密文cipher.txt,输出到文件plain.txt
openssl rsautl -decrypt -inkey rsaprivatekey.pem -in cipher.txt -out plain.txt
WeiyiGeek.rsa密钥和公钥

WeiyiGeek.rsa密钥和公钥

WeiyiGeek.公钥私钥加解密

WeiyiGeek.公钥私钥加解密


1
2
3
4
5
6
7
8
9
10
11
12
#X.509应用例子;
1.从证书文件cert.pem中获取公钥匙,用3DES加密mail.txt,输出到文件mail.enc
openssl smime -encrypt -in mail.txt -des3 -out mail.enc cert.pem

2.从X.509证书文件cert.pem中获取接收人的公钥匙,用私钥匙key.pem解密S/MIME消息mail.enc,结果输出到文件mail.txt
openssl smime -decrypt -in mail.enc -recip cert.pem -inkey key.pem -out mail.txt

3.cert.pem为X.509证书文件,用私匙key,pem为mail.txt签名,证书被包含在S/MIME消息中,输出到文件mail.sgn
openssl smime -sign -in mail.txt -signer cert.pem -inkey key.pem -out mail.sgn

4.验证S/MIME消息mail.sgn,输出到文件mail.txt,签名者的证书应该作为S/MIME消息的一部分包含在mail.sgn中
openssl smime -verify -in mail.sgn -out mail.txt


3.信息摘要算法
OpenSSL实现了5种信息摘要算法,分别是MD2、MD5、MDC2、SHA(SHA1)和RIPEMD;SHA算法事实上包括了SHA和SHA1两种信息摘要算法此外,OpenSSL还实现了DSS标准中规定的两种信息摘要算法DSS和DSS1;
信息摘要算法:主要验证文件是否被更改,如果被更改则生成于验证的摘要算法不同;

1
2
3
4
5
6
7
#消息摘要算法应用例子:
1.用SHA1/MD5算法计算文件file.txt的哈西值,输出到stdout;
openssl dgst -sha1 file.txt
openssl dgst -md5 file.txt

2.用SHA1算法计算文件file.txt的哈西值,输出到文件digest.txt:
openssl sha1 -out digest.txt file.txt


1
2
3
4
5
6
7
8
9
10
11
12
1.用DSS1(SHA1)算法为文件file.txt签名(signature),输出到文件dsasign.bin;
#签名的private key必须为DSA算法产生的,保存在文件dsakey.pem中
openssl dgst -dss1 -sign dsakey.pem -out dsasign.bin file.txt

2.用dss1算法验证file.txt的数字签名dsasign.bin,验证的private key为DSA算法产生的文件dsakey.pem。
openssl dgst -dss1 -prverify dsakey.pem -signature dsasign.bin file.txt

3.用sha1算法为文件file.txt签名,输出到文件rsasign.bin,签名的private key为RSA算法产生的文件rsaprivate.pem。
openssl sha1 -sign rsaprivate.pem -out rsasign.bin file.txt

4.用sha1算法验证(verify)file.txt的数字签名rsasign.bin,验证的public key为RSA算法生成的rsapublic.pem。
openssl sha1 -verify rsapublic.pem -signature rsasign.bin file.txt


0x03 证书密钥管理

首先,OpenSSL实现了ASN.1的证书和密钥相关标准,提供了对证书、公钥、私钥、证书请求以及CRL等数据对象的DER、PEM和BASE64的编解码功能
OpenSSL提供了产生各种公开密钥对和对称密钥的方法、函数和应用程序,同时提供了对公钥和私钥的DER编解码功能。并实现了私钥的PKCS#12和PKCS#8的编解码功能;

密钥和证书管理是PKI的一个重要组成部分,OpenSSL为之提供了丰富的功能,支持多种标准;OpenSSL在标准中提供了对私钥的加密保护功能,使得密钥可以安全地进行存储和分发:
在此基础上,OpenSSL实现了对证书的X.509标准编解码、PKCS#12格式的编解码以及PKCS#7的编解码功能,并提供了一种文本数据库,支持证书的管理功能,包括证书密钥产生、请求产生、证书签发、吊销和验证等功能
事实上,OpenSSL提供的CA应用程序就是一个小型的证书管理中心(CA),实现了证书签发的整个流程和证书管理的大部分机制.

这里不得不提到SSL证书通过在客户端浏览器和Web服务器之间建立一条SSL安全通道(Secure socketlayer(SSL),SSL安全协议主要用来提供对用户和服务器的认证;对传送的数据进行加密和隐藏;确保数据在传送中不被改变,即数据的完整性,现已成为该领域中全球化的标准。由于SSL技术已建立到所有主要的浏览器和WEB服务器程序中,因此仅需安装服务器证书就可以激活该功能了)。即通过它可以激活SSL协议,实现数据信息在客户端和服务器之间的加密传输,可以防止数据信息的泄露。保证了双方传递信息的安全性,而且用户可以通过服务器证书验证他所访问的网站是否是真实可靠。

SSL网站不同于一般的Web站点,它使用的是“HTTPS”协议,而不是普通的“HTTP”协议。因此它的URL(统一资源定位器)格式为“https://www.baidu.com”。

什么是x509证书链?
答:x509证书一般会用到三类文件,key,csr,crt。

  • Key是私用密钥,openssl格式,通常是rsa算法。
  • csr是证书请求文件,用于申请证书。在制作csr文件的时候,必须使用自己的私钥来签署申请,还可以设定一个密钥。
  • crt是CA认证后的证书文件(windows下面的csr,其实是crt),签署人用自己的key给你签署的凭证。

首先要有一个CA根证书,然后用CA根证书来签发用户证书。用户进行证书申请:一般先生成一个私钥,然后用私钥生成证书请求(证书请求里应含有公钥信息),再利用证书服务器的CA根证书来签发证书。

什么是CA根证书
答:CA认证即电子认证服务,是指为电子签名相关各方提供真实性、可靠性验证的活动,实际上它相当于是一个机构。

特别说明:

  • 自签名证书(一般用于顶级证书、根证书): 证书的名称和认证机构的名称相同.
  • 根证书:根证书是CA认证中心给自己颁发的证书,是信任链的起始点。任何安装CA根证书的服务器都意味着对这个CA认证中心是信任的。
  • 数字证书则是由证书认证机构(CA)对证书申请者真实身份验证之后,用CA的根证书对申请人的一些基本信息以及申请人的公钥进行签名(相当于加盖发证书机构的公章)后形成的一个数字文件。
  • 数字证书包含证书中所标识的实体的公钥(就是说你的证书里有你的公钥),由于证书将公钥与特定的个人匹配,并且该证书的真实性由颁发机构保证(就是说可以让大家相信你的证书是真的),因此,数字证书为如何找到用户的公钥并知道它是否有效这一问题提供了解决方案。
WeiyiGeek.CA机构

WeiyiGeek.CA机构


证书类型与协议

描述:通常我们提到的证书里面包含了公钥、发布者的数字签名、有效期等内容,大多数证书文件它里面是不包含私钥的, 除了像PFX与JKS这样的密钥库带有密钥外;
X.509是一个度最基本的公钥格式(证书)标准,其主要定义了证书中需要包含的各种信息,我们常见的SSL就是使用这种证书标准,其详情可以参考RFC5280标准;

证书主要的文件类型和协议有: PEM(证书厂商常用)、DER、PFX(ISS常用)、JKS(Java常用)、KEY、KDB、CER(证书文件)、CSR(证书签名申请)、CRT(证书文件)、CRL、OCSP、SCEP等。
常见几种证书编码格式。

  • 1.带有私钥的证书: PKCS#12以pfx/JKS作为证书文件后缀名(证书密钥库)
  • 2.二进制编码的证书: 证书中没有私钥,DER 编码二进制格式的证书文件,以cer作为证书文件后缀名。
  • 3.Base64编码的证书: 证书中没有私钥,BASE64 编码格式的证书文件,也是以cer作为证书文件后缀名。


证书编码格式
(1) PEM - Privacy Enhanced Mail:Openssl使用该PEM格式来存放各种信息,它是 openssl 默认采用的信息存放方式,Apache和NGINX服务器偏向于使用这种编码格式。

1
2
#PEM格式证书的信息查看
openssl x509 -in certificate.pem -text -noout

WeiyiGeek.pem

WeiyiGeek.pem

Openssl 中的 PEM 文件一般包含如下信息:

  • 1) 内容类型:表明本文件存放的是什么信息内容;
  • 2) 头信息:表明数据是如果被处理后存放, openssl 中用的最多的是加密信息, 比如加密算法以及初始化向量 iv;
  • 3) 信息体:为 BASE64 编码的数据:可以包括所有私钥(RSA 和 DSA)、公钥(RSA 和 DSA)和 (x509) 证书
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
35
36
37
# PEM格式样式说明
# 1.使用PEM格式存储的证书:
-----BEGIN CERTIFICATE-----
MIIDBjCCAe6gAwIBAgIBATANBgkqhkiG9w0BAQsFADA8MTowOAYDVQQDDDFNeVNR
TF9TZXJ2ZXJfOC4wLjE2X0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4X
DTE5MDgxNTA5NDc0NloXDTI5MDgxMjA5NDc0NlowPDE6MDgGA1UEAwwxTXlTUUxf
U2VydmVyXzguMC4xNl9BdXRvX0dlbmVyYXRlZF9DQV9DZXJ0aWZpY2F0ZTCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOMzxWH6GiFOaENGcgN1AKxVlOfB
uVKM43J0i1sqyqJ+U2cGUYXyDYIgDaYio1Al75Esy7WgBdgKPD1XHBIVAHhfwBeD
YC2fUO1dl2LsqCHFy29ds8exEcAZgqsU51kSCakTJ5FIxSQj5G39G1+OG0B2xyUq
9FBMS+e3Ks/qmGruWoLjo8a7DUDtNxj/GKavRbWhtNu5yxc0A1xUq/MjnWWbwQog
dstoW2Pxo6xPih2jgRP1Mt9XtlxldsDPJQxXV3Ivi+w9Omtc1TK+HMY9YJu9S/oI
KpM6d0lUOxCt0OGPGaEn9fdYC74tNhwGUOrb6uLIXTrZFgIU9g/ozhxvm78CAwEA
AaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEA3opxpm/N
oN7778t6f0MU9xaNoIcMqzioPjyGJozFqdLJGJ2RHyuYPf15epUfOoJVhJ7tzvbF
S7m4odUkIG6nMMme0V9XnZn0W7NJFpb1UPJNBwymSSSzDMw2N9V6J1FDyQtn41XE
2mJT0aORrNimqehR2QccH/AZ7hIg/a/f6u7OTbqZ+pckBKsViboDcmo7dL0mUjKb
lvZttFXN+kVCGOptIfSccQyJlQByNgVUQSVpE1WyX+/zwwU+iXr7/LbRzzyHgR1l
zZEgvr7QHelBFzOYIST1h5vHhFAWGa4EtjhuAQZWBXh/xwG4o1VdciOpsvvz3COH
8EUv8YZROdrA5A==
-----END CERTIFICATE-----


#2.使用PEM格式存储的私钥:
-----BEGIN RSA PRIVATE KEY-----
MIICJjCCAdCgAwIBAgIBITANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx
.....
1p8h5vkHVbMu1frD1UgGnPlOO/K7Ig/KrsU=
-----END RSA PRIVATE KEY-----


#3.使用PEM格式存储的证书请求文件:
-----BEGIN CERTIFICATE REQUEST-----
MIICJjCCAdCgAwIBAgIBITANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx
.....
1p8h5vkHVbMu1frD1UgGnPlOO/K7Ig/KrsU=
-----END CERTIFICATE REQUEST-----

(2) DER - Distinguished Encoding Rules:辨别编码规则 (DER) 可包含所有私钥、公钥和证书
它是大多数浏览器的缺省格式,并按 ASN1 DER 格式存储, 它是无报头的 PEM 是用文本报头包围的 DER,Java和Windows服务器偏向于使用这种编码格式.

1
2
#查看DER格式证书的信息
openssl x509 -in certificate.der -inform der -text -noout


证书编码的转换

1
2
3
4
5
#PEM转为DER
openssl x509 -in cert.crt -outform der -out cert.der

#DER转为PEM
openssl x509 -in cert.crt -inform der -outform pem -out cert.pem

提示:要转换KEY文件也类似,只不过把x509换成rsa要转CSR的话,把x509换成req.


核心重点
描述:在我们学习证书申请,以及自签CA的时候对于不同的证书格式文件,总是搞得使用者一片茫然;
因为虽然我们已经知道有PEM和DER这两种编码格式, 但文件扩展名并不一定就叫”PEM”或者”DER”, 它们除了编码格式可能不同之外其内容也有差别,但它们大多数都能相互转换编码格式.

证书文件文件扩展名:

  • (1) .crt 格式:证书文件certificate的缩写,用于证书抄证书可以是DER编码,也可以是PEM编码(扩展名CER和CRT几乎是同义词), 常用于Linux系统大多数是PEM编码;
  • (2) .cer 格式:证书文件certificate的缩写,CRT证书的微软型式可以用微软的工具把CRT文件转换袭为CER文件(CRT和CER必须是相同编码的DER或者PEM), 常用于Windows系统大多数是DER编码(表现形式二进制格式的证书文件),;
  • (3) .key 格式:通常用来存放一个公钥或者私钥,并非X.509证书,编码可能是PEM或者DER
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #PEM编码查看
    openssl rsa -in private.key -text -noout
    $cat private.key
    -----BEGIN RSA PRIVATE KEY-----
    MIICJjCCAdCgAwIBAgIBITANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx
    .....
    1p8h5vkHVbMu1frD1UgGnPlOO/K7Ig/KrsU=
    -----END RSA PRIVATE KEY-----

    #DER编码查看
    openssl rsa -in private.key -text -noout -inform der
  • (4).csr 格式:证书签名请求(Certificate Signing Request),它是向权威证书颁发机构获得签名证书的申请,其核心内容是一个公钥(当然还附带了一些别的信息),在生成这个申请的时候,同时也会生成一个私钥,私钥要自己保管好;
    1
    2
    3
    4
    5
    #PEM编码查看
    openssl req -noout -text -in my.csr

    #DER编码查看
    openssl req -noout -text -inform der -in my.csr
  • (5)PFX/P12 格式: predecessor of PKCS#12包含公钥和私钥的二进制格式证书,对于nginx来说是分开存放在不同文件中(相对安全),但Windows的IIS则将它们存在一个PFX文件中(因此这个文件包含了证书及私钥)为了提高安全性PFX格式证书通常会有一个提取密码,当您想提取任何东西的时候都需要输入该密码;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #PFX -> PEM
    openssl pkcs12 -in for-iis.pfx -out iiscetificate.pem -nodes

    #PFX -> 导出crt和key
    openssl pkcs12 -in example.cn.ssl.pfx -nocerts -nodes -out example.key
    openssl pkcs12 -in example.cn.ssl.pfx -clcerts -nokeys -out example.crt

    #PEM -> PFX:将crt和key合并出pfx
    openssl pkcs12 -export -in certificate.crt -inkey privateKey.key -out certificate.pfx

    #其中CACert.crt是CA(权威证书颁发机构)的根证书,有的话也通过-certfile参数一起带进去,实际上PFX其实是个证书密钥库;
  • (6).jks 格式:即Java Key Storage实际也是一个证书密钥库Java的专利,跟OpenSSL关系不大利用Java的一个叫”keytool”的工具,可以将PFX转为JKS当然了keytool也能直接生成JKS(可以参考我的另外一篇文章Java工具使用补充说明)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # PEM -> JKS 把用户证书文件转换成keystore.jks文件
    # 1.把用户证书转换成P12格式
    $ openssl pkcs12 -export -in cert.pem -inkey cert.key -out keystore.p12 -passout pass:<passvalue>

    # 2.把p12格式文件加入到JKS格式
    $ keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -destkeystore keystore.jks \
    -srcstorepass <passvalue> -deststorepass <passvalue>

    # 3.查看结果
    $ keytool --list -keystore keystore.jks -storepass <passvalue>
    Keystore type: JKS
    Keystore provider: SUN
    Your keystore contains 1 entry
    1, Dec 13, 2018, PrivateKeyEntry,
    Certificate fingerprint (SHA1): 7D:38:3C:9E:B6:DC:4B:D1:A9:EC:D9:5C:C8:DF:01:E1:D2:C4:01:00

    # 4.另外,如果需要在keystore里面包含CA证书,则需要:
    $ openssl pkcs12 -export -name myalias2 -in cert.pem -inkey cert.key -chain -CAfile ca.pem -out keystore.p12 -passout pass:<passvalue>
  • (7).p7b 格式:以树状展示证书链(certificate chain),同时也支持单个证书,不含私钥。

  • (8).crl 格式:证书吊销列表Certificate Revocation List的缩写


自签证书-交互式

https://www.jianshu.com/p/81dbcde4fd7c

1
openssl req -new -x509 -newkey rsa:2048 -keyout ./server.key -out ./server.crt

CA根证书的生成步骤:

  • 1.生成CA私钥(.key)
  • 2.生成CA证书请求(.csr)
  • 3.自签名得到根证书(.crt)(CA给自已颁发的证书)。
    在实际的软件开发工作中,往往服务器就采用这种SSL自签名的方式,因为毕竟找第三方签名机构是要给钱的,也是需要花时间的。
  • 4采用dhparam加密服务器密钥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# (1) 创建私钥:Generate CA private key 
openssl genrsa -out ca.key 2048

# (2) 创建CSR证书申请文件:Generate CSR
openssl req -new -key ca.key -out ca.csr
# Country Name (2 letter code) [XX]:CN #地区
# State or Province Name (full name) []:CN #省份
# Locality Name (eg, city) [Default City]:CQ #城市
# Organization Name (eg, company) [Default Company Ltd]:weiyigeek #组织名称
# Organizational Unit Name (eg, section) []:weiyigeek #单元名称
# Common Name (eg, your name or your servers hostname) []:weiyigeek.top #通用名称即网站域名
# Email Address []:test@qq.com
# A challenge password []:weiyigeek #认证密码
# An optional company name []:

# (3) Generate Self Signed certificate(CA 根证书)
openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt
# Signature ok
# subject=/C=CN/ST=CN/L=CQ/O=weiyigeek/OU=weiyigeek/CN=weiyigeek.top/emailAddress=test@qq.com
# Getting Private key

# (4) 用dhparam加密服务器密钥
openssl dhparam -out dhparam.pem 2048


用户证书的生成步骤:
描述:生成私钥(.key)–>生成证书请求(.csr)–>用CA根证书签名得到证书(.crt)于上面的步骤差不多多的只是加密;

  • 1.服务器端用户证书:

    1
    2
    3
    4
    5
    6
    # private key
    $openssl genrsa -des3 -out server.key 2048
    # generate csr
    $openssl req -new -key server.key -out server.csr
    # generate certificate
    $openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key
  • 2.客户端用户证书:

    1
    2
    3
    4
    5
    6
    # private key
    $openssl genrsa -des3 -out client.key 1024
    # generate csr
    $openssl req -new -key client.key -out client.csr
    # generate certificate
    $openssl ca -in client.csr -out client.crt -cert ca.crt -keyfile ca.key


生成pem格式证书步骤
描述:有时需要用到pem格式的证书,可以用以下方式合并证书文件(crt)和私钥文件(key)来生成

1
2
$cat client.crt client.key > client.pem 
$cat server.crt server.key > server.pem

最后生成结果:

1
2
服务端证书: ca.crt, server.key, server.crt, server.pem
客户端证书: ca.crt, client.key, client.crt, client.pem


生成带有SAN的证书步骤

1
2
3
4
5
6
7
8
9
# 利用 addext 参数添加指定证书的SAN.
openssl req \
-newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
-addext "subjectAltName = DNS:registry-1.docker.io" \
-addext "subjectAltName = DNS:harbor.weiyigeek.top" \
-x509 -days 365 -out certs/domain.crt

# 查看证书有效期
openssl x509 -in domain.crt -noout -dates

【附录:在线SSL证书格式转换工具】


0x04 私有CA创建

自签证书-ca.conf

描述:我们会创建一个与公共CA类似的私有CA架构。会先有一个根CA,然后创建其他的二级CA。接着我们会通过CRL和OCSP服务提供证书吊销信息。为了让根CA的私钥可以离线保存, OCSP响应程序需要使用它们自己的身份。这并非是最简单的CA,但是相对来说比较安全。另外二级CA会在技术上进行限制,只能给允许的主机名签发证书

完成设置之后,必须将根证书安全地分发给所有客户端。一旦根证书分发完毕,就可以开始签发客户端和服务器证书了。有一个限制是以这种方式设置的OCSP响应程序主要用来测试,因为只能承受比较小的负载。

创建根 CA 说明:
本节描述了整个过程和常见的CA操作,即创建全新的CA有几个步骤:配置、创建目录结构和初始化密钥文件,最后生成根密钥和证书

根CA配置如下:

  • 1.第一部分包括了CA的名称、基础URL和CA可分辨名称等基本信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    [default]
    name = root-ca
    domain_suffix = wieyigeek.top
    default_ca = ca_default #默认CA配置
    aia_url = http://$name.$domain_suffix/$name.crt
    crl_url = http://$name.$domain_suffix/$name.crl
    ocsp_url = http://ocsp.$name.$domain_suffix:9080
    name_opt = utf8,esc_ctrl,multiline,lname,align

    [ca_dn]
    countryName = "CN"
    organizationName = "WeiyiGeek"
    commonName = "Root CA"
  • 2.第二部分直接控制了CA的操作以及告诉OpenSSL存放文件的路径,注意由于根CA只用作二级CA的签发,此处我将设置未10年;

    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
    35
    36
    [ca_default]
    home = /opt/cert
    database = $home/db/index
    serial = $home/db/serial
    crlnumber = $home/db/crlnumber
    new_certs_dir = $home/certs
    certificate = $home/certs/$name.crt
    private_key = $home/private/$name.key
    RANDFILE = $home/private/.random
    unique_subject = no
    default_days = 3650
    default_crl_days = 365
    copy_extensions = none
    # - 默认情况下使用SHA256作为签名摘要算法
    default_md = sha256
    policy = policy_c_o_match # 安全策略配置
    # - 默认策略( policy_c_o_match)限制了这张CA签发的证书的国家名和组织名会与CA本身一样 (公共CA通常不会这样使用但对于私有CA来说该方式比较合适)
    # - supplied(提供),optional(可选择的)
    [policy_c_o_match]
    countryName = match
    stateOrProvinceName = optional
    organizationName = match
    organizationalUnitName = optional
    commonName = supplied
    emailAddress = optional

    # - 公共CA策略
    # policy = policy_any
    # [policy_any]
    # countryName = match
    # stateOrProvinceName = match
    # organizationName = match
    # organizationalUnitName = match
    # localityName = optional
    # commonName = supplied
    # emailAddress = optional
  • 3.第三部包含了req命令的配置, req命令只会在创建自签发根证书的时候用到一次。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 最重要的部分是扩展:基本限制( basicContraints)扩展表明这个证书是一张CA,密钥用法( keyUsage)扩展用来说明这个CA的用处:
    [req]
    default_bits = 4096
    encrypt_key = yes
    default_md = sha256
    utf8 = yes
    string_mask = utf8only
    prompt = no
    distinguished_name = ca_dn #辨别名称
    req_extensions = ca_ext #证书请求扩展配置

    [ca_ext]
    basicConstraints = critical,CA:true
    subjectKeyIdentifier = hash
    keyUsage = critical,keyCertSign,cRLSign
  • 4.第四部分包括了根CA创建证书所需要的信息。因为基本限制( basicContraints)扩展的设置,所有的证书都将成为CA,但是我们需要把pathlen设置为0,表示这些CA无法再签发新的CA了。所有二级CA都会受到限制,也就是说他们签发的证书只能对一些域名的子集有效,并且会被限制使用场景

    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
    # 第一、扩展密钥用法( extendedKeyUsage)扩展限制了只能进行客户端验证( clientAuth)和服务器验证( serverAuth),也就是TLS的客户端和服务器验证。
    # 第二、名称限制( nameContraints)扩展限制了允许签发的域名只有example.com和example.org。理论上这样的设置让你可以签发二级CA给第三方,同时可以通过限制他们无法签发任意域名的主机名来保证安全。排除这两个IP段的要求来自CAB论坛的Baseline Requirements,该规范从技术上定义了对二级CA的限制。

    [sub_ca_ext]
    authorityInfoAccess = @issuer_info
    authorityKeyIdentifier = keyid:always
    basicConstraints = critical,CA:true,pathlen:0
    crlDistributionPoints = @crl_info
    extendedKeyUsage = clientAuth,serverAuth
    keyUsage = critical,keyCertSign,cRLSign
    nameConstraints = @name_constraints
    subjectKeyIdentifier = hash

    [crl_info]
    URI.0 = $crl_url

    [issuer_info]
    caIssuers;URI.0 = $aia_url
    OCSP;URI.0 = $ocsp_url

    [name_constraints]
    permitted;DNS.0=example.com
    permitted;DNS.1=example.org
    excluded;IP.0=0.0.0.0/0.0.0.0
    excluded;IP.1=0:0:0:0:0:0:0:0/0:0:0:0:0:0:0:0

    Tips: 实际上,名称限制( nameContraints)并不完美,因为当前还有很多主流的平台无法识别名称限制扩展。如果你将这个扩展标记为关键扩展,就会导致很多平台拒绝识别你的证书。如果将其标记为关键扩展,那么很多平台就不会识别这个扩展,导致名称限制实际没有任何效果。

  • 5.最后两部分的配置表示有了这个扩展的证书可以对OCSP响应进行签名。

    1
    2
    3
    4
    5
    6
    7
    8
    # 为了能够运行OCSP响应程序,我们生成一个特别的证书,并且将OCSP的签名能力赋予这张证书。
    [ocsp_ext]
    authorityKeyIdentifier = keyid:always
    # 从扩展可以看出这张证书不是一个CA
    basicConstraints = critical,CA:false
    extendedKeyUsage = OCSPSigning
    keyUsage = critical,digitalSignature
    subjectKeyIdentifier = hash


实际案例:

  • 1.创建“根CA配置”中说到的目录结构,并且会初始化一些CA操作中会用到的文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 根CA的目录结构
    sudo mkdir -vp /opt/cert/{certs,private,conf,server,client,db} && cd /opt/cert/
    # certs 目录将用于存放CA签署过的数字证书。
    # private 目录用于存放CA的私钥(安全的重点)。
    # conf 目录用于存放一些简化参数用的配置文件。
    # server 目录存放服务器证书文件。
    # client 目录存放客户端证书签名文件。
    # db 目录用于证书数据库(index),包括下一张证书以及CRL数字的文件。 OpenSSL会创建额外需要的一些文件
    sudo chmod 700 private
    touch db/index
    openssl rand -hex 16 > db/serial
    echo 1001 > db/crlnumber
  • 2.根CA证书与私钥生成需要分两步来创建;

    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    # (1) 首先生成密钥和CSR文件,备注--config 参数指定ca配置文件
    $ openssl req -new \
    -config conf/root-ca.conf \
    -out certs/root-ca.csr \
    -keyout private/root-ca.key
    # Generating a 4096 bit RSA private key
    # ..............................................++
    # ..............................................++
    # writing new private key to 'private/root-ca.key'
    # 输入 Privacy Enhanced Mail PEM 密码
    # Enter PEM pass phrase:
    # Verifying - Enter PEM pass phrase:


    # (2) 其次创建自签证书,备注采用-extension参数指向了配置文件的ca_ext部分;
    openssl ca -selfsign \
    -config conf/root-ca.conf \
    -in certs/root-ca.csr \
    -out certs/root-ca.crt \
    -extensions ca_ext
    # Using configuration from conf/root-ca.conf
    # Enter pass phrase for /opt/cert/private/root-ca.key:
    # Check that the request matches the signature
    # Signature ok
    # Certificate Details:
    # Certificate:
    # Data:
    # Version: 3 (0x2)
    # Serial Number: # 它会存储在数据库文件中
    # 37:56:c1:be:ba:88:0b:33:0e:06:ac:fe:58:fd:87:24
    # Issuer:
    # countryName = CN
    # organizationName = WeiyiGeek
    # commonName = Root CA
    # Validity
    # Not Before: Aug 20 04:58:11 2020 GMT
    # Not After : Aug 18 04:58:11 2030 GMT
    # Subject:
    # countryName = CN
    # organizationName = WeiyiGeek
    # commonName = Root CA
    # Subject Public Key Info:
    # Public Key Algorithm: rsaEncryption
    # Public-Key: (4096 bit)
    # Modulus:
    # 00:c3:80:3f:cf:fc:f8:8a:1f:74:d8:1f:9c:e3:b2:
    # ..........................................
    # 7c:69:69:32:5b:40:c1:70:1f:8e:2c:c6:20:6a:e9:
    # 81:d9:8b
    # Exponent: 65537 (0x10001)
    # X509v3 extensions:
    # X509v3 Basic Constraints: critical
    # CA:TRUE
    # X509v3 Subject Key Identifier:
    # 4B:B7:11:BE:C3:61:01:5F:C4:57:CC:9C:CE:E4:3C:3D:A6:E7:7F:56
    # X509v3 Key Usage: critical
    # Certificate Sign, CRL Sign
    # Certificate is to be certified until Aug 18 04:58:11 2030 GMT (3650 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
  • 3.查看生成的数据库文件及其结构;
    描述:db/index中的数据库是一个包含证书信息的明文文件,每行一个证书。我们刚刚创建根CA现在这个文件只有一行信息;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 证书 Serial Number:
    $cat /opt/cert/db/serial
    3756C1BEBA880B330E06ACFE58FD8725

    # 根中的所有证书信息包括(CA证书)
    $cat /opt/cert/db/index
    V 300818045811Z 3756C1BEBA880B330E06ACFE58FD8724 unknown /C=CN/O=WeiyiGeek/CN=Root CA
    # (1) 状态标记[ V表示有效( valid), R表示已吊销( revoked), E表示已过期( expired)]
    # (2) 过期时间(以YYMMDDHHMMSSZ格式表示)
    # (3) 吊销日期,如果没有被吊销则为空
    # (4) 序列号(十六进制)
    # (5) 文件路径(如果不知道就显示unknown)
    # (6) 可分辨名称
  • 4.根CA操作来签发电子证书

    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    # (1) 使用ca命令的-gencrl开关给新CA生成root-ca.crl文件
    $sudo openssl ca -gencrl -config conf/root-ca.conf -out certs/root-ca.crl
    # Using configuration from conf/root-ca.conf
    # Enter pass phrase for /opt/cert/private/root-ca.key: # 输入根密钥密码
    $cat certs/root-ca.crl
    # -----BEGIN X509 CRL-----
    # MIICjDB2AgEBMA0GCSqGSIb3DQEBCwUAMDMxCzAJBgNVBAYTAkNOMRIwEAYDVQQK
    # DAlXZWl5aUdlZWsxEDAOBgNVBAMMB1Jvb3QgQ0EXDTIwMDgyMDA2MzE1NVoXDTIx
    # MDgyMDA2MzE1NVqgDzANMAsGA1UdFAQEAgIQATANBgkqhkiG9w0BAQsFAAOCAgEA
    # fEI2Jd1gPYFUGDWfpveZMDsNDkg9sd+DROes2jSCx1r8+Mbg122IpijFYRTmaz8f
    # sz22AvB6FdMcvlVVB2zEVY+B0RykWU3uScE3Ns6mIHVmT7um5dISj/vYvEe0Fotj
    # VGXxaqvGffbDXRJHJ1ugbgJJHjvWOzrfp+aVayg6R89hYnoeZ5Zrv3LckUXh3WJ9
    # I23wYsy2XE9murZZ9ihgSMfVwrbY4D2pE/uPK/Tnrqgvw9qJgqyOpxVNKIJrkZWq
    # LcFG0sORLWkTeuHIaqZstGbD+bYfMuJNGXY7IZltdaS4/dONcz1DAa0hOBHmipwi
    # cTMON51SXDYuqQ3hjNBuevsxjWW99/tpVrtX/aWhFmgGoVEswy7uIQTca3y6goai
    # MKvBesHiL6B1JU2hTEEBMGVL+UXuGsFS4E+GfIAkdbnVd2uc806c7mtzIYvfG4Cu
    # bccjqWvo4Wr6irkbFdS/TY5dCsjeuEZ1vr15aYwAvmozOsRXfEhbXnB7eJXDZucq
    # ze7Zgc0I/G3Wy8TVHKnxCOL9CmffsVfsCrYFHd6Bvd2RvH2MtqdJpbGfpQd8Oc4S
    # nBJEQ6dz3aVBaxeY/3hLnuSjqr+z7x/0PMGXMTS6ohAw4ZPnva8qaCDscb6+kgGg
    # 0FxKZz/D0JYkrlSp3GOxwl8vvFnsiCavo8InFtQp4SM=
    # -----END X509 CRL-----


    # (2) 使用ca的命令来签发证书,注意的是-extensions开关需要指向配置文件里面正确的部分;
    # 例如,你肯定不希望再生成另一个根CA
    $ openssl ca \
    -config conf/root-ca.conf \
    -in certs/root-ca.csr \
    -out certs/sub-ca.crt \
    -extensions sub_ca_ext
    # Enter pass phrase for /opt/cert/private/root-ca.key:
    # Check that the request matches the signature
    # Signature ok
    # Certificate Details:
    # Certificate:
    # Data:
    # Version: 3 (0x2)
    # Serial Number:
    # 37:56:c1:be:ba:88:0b:33:0e:06:ac:fe:58:fd:87:25
    # Issuer:
    # countryName = CN
    # organizationName = WeiyiGeek
    # commonName = Root CA
    # Validity
    # Not Before: Aug 20 06:55:58 2020 GMT
    # Not After : Aug 18 06:55:58 2030 GMT
    # Subject:
    # countryName = CN
    # organizationName = WeiyiGeek
    # commonName = Root CA
    # Subject Public Key Info:
    # Public Key Algorithm: rsaEncryption
    # Public-Key: (4096 bit)
    # Modulus:
    # 00:c3:80:3f:cf:fc:f8:8a:1f:74:d8:1f:9c:e3:b2:
    # 7c:e5:b8:b3:2e:19:c7:91:b5:26:b4:c9:22:e1:3e:
    # ..............................................
    # 7c:69:69:32:5b:40:c1:70:1f:8e:2c:c6:20:6a:e9:
    # 81:d9:8b
    # Exponent: 65537 (0x10001)
    # X509v3 extensions:
    # Authority Information Access:
    # CA Issuers - URI:http://root-ca.wieyigeek.top/root-ca.crt
    # OCSP - URI:http://ocsp.root-ca.wieyigeek.top:9080

    # X509v3 Authority Key Identifier:
    # keyid:4B:B7:11:BE:C3:61:01:5F:C4:57:CC:9C:CE:E4:3C:3D:A6:E7:7F:56

    # X509v3 Basic Constraints: critical
    # CA:TRUE, pathlen:0
    # X509v3 CRL Distribution Points:

    # Full Name:
    # URI:http://root-ca.wieyigeek.top/root-ca.crl

    # X509v3 Extended Key Usage:
    # TLS Web Client Authentication, TLS Web Server Authentication
    # X509v3 Key Usage: critical
    # Certificate Sign, CRL Sign
    # X509v3 Name Constraints:
    # Permitted:
    # DNS:example.com
    # DNS:example.org
    # Excluded:
    # IP:0.0.0.0/0.0.0.0
    # IP:0:0:0:0:0:0:0:0/0:0:0:0:0:0:0:0

    # X509v3 Subject Key Identifier:
    # 4B:B7:11:BE:C3:61:01:5F:C4:57:CC:9C:CE:E4:3C:3D:A6:E7:7F:56
    # Certificate is to be certified until Aug 18 06:55:58 2030 GMT (3650 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


    # (3) 如果要吊销证书,可以使用ca命令的-revoke开关,不过需要有一份你想吊销的证书的副本。不过因为所有的证书都存在certs/目录下所以只需要知道序列号即可。如果知道证书的可分辨名称,就可以在数据库里面查到它的序列号了。
    # 选项 -crl_reason 可选参数值: unspecified、keyCompromise 、 CACompromise 、 affiliationChanged 、 superseded 、 cessationOfOperation 、certificateHold和removeFromCRL;
    $ openssl ca \
    -config conf/root-ca.conf \
    -revoke certs/serialnumber.pem \
    -crl_reason keyCompromise
    # $ openssl ca -config conf/root-ca.conf -revoke certs/sub-ca.crt -crl_reason keyCompromise
    # Using configuration from conf/root-ca.conf
    # Enter pass phrase for /opt/cert/private/root-ca.key:
    # Revoking Certificate 3756C1BEBA880B330E06ACFE58FD8725.
    # Data Base Updated
  • 5.创建用于OCSP签名的证书

    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    # (1) 首先需要给OCSP响应程序创建一个私钥private和csr,备注该操作对所有的非CA证书都适用所以缺省即可;
    openssl req -new \
    -newkey rsa:2048 \
    -subj "/C=CN/O=WeiyiGeek/CN=OCSP Root Responder" \
    -keyout private/root-ocsp.key \
    -out certs/root-ocsp.csr
    # Generating a 2048 bit RSA private key
    # ....................+++
    # .................................+++
    # writing new private key to 'private/root-ocsp.key'
    # Enter PEM pass phrase: # weiyigeekocsp
    # Verifying - Enter PEM pass phrase:


    # (2) 其次需要使用根CA签发一张证书,任然采用-extensions选择ocsp_ext以确保设置了OCSP签名所需要的扩展;
    # 在root-ca.conf配置文件中设置键值对如default_crl_days = 365,证书的生命周期减少为365天;
    $ openssl ca \
    -config conf/root-ca.conf \
    -in certs/root-ocsp.csr \
    -out certs/root-ocsp.crt \
    -extensions ocsp_ext \
    -days 30
    # Enter pass phrase for /opt/cert/private/root-ca.key:
    # Check that the request matches the signature
    # Signature ok
    # Certificate Details:
    # Certificate:
    # Data:
    # Version: 3 (0x2)
    # Serial Number:
    # 37:56:c1:be:ba:88:0b:33:0e:06:ac:fe:58:fd:87:26
    # Issuer:
    # countryName = CN
    # organizationName = WeiyiGeek
    # commonName = Root CA
    # Validity
    # Not Before: Aug 20 07:15:03 2020 GMT
    # Not After : Sep 19 07:15:03 2020 GMT
    # Subject:
    # countryName = CN
    # organizationName = WeiyiGeek
    # commonName = OCSP Root Responder
    # Subject Public Key Info:
    # Public Key Algorithm: rsaEncryption
    # Public-Key: (2048 bit)
    # Modulus:
    # 00:d1:6b:fe:4e:f1:a4:19:02:17:6e:62:69:d6:77:
    # ....
    # 08:1f:8b:d0:1c:45:29:50:56:16:e6:4f:13:1e:7f:
    # 5f:8b
    # Exponent: 65537 (0x10001)
    # X509v3 extensions:
    # X509v3 Authority Key Identifier:
    # keyid:4B:B7:11:BE:C3:61:01:5F:C4:57:CC:9C:CE:E4:3C:3D:A6:E7:7F:56
    # X509v3 Basic Constraints: critical
    # CA:FALSE
    # X509v3 Extended Key Usage:
    # OCSP Signing
    # X509v3 Key Usage: critical
    # Digital Signature
    # X509v3 Subject Key Identifier:
    # 42:F1:20:F8:82:77:81:F5:92:61:69:41:D8:40:C0:EA:35:03:E0:51
    # Certificate is to be certified until Sep 19 07:15:03 2020 GMT (30 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


    # (3) OCSP响应程序可以直接在根CA所在的服务器上进行测试,注意如果在生产环境中使用就必须将OCSP响应程序的密钥和证书放在别的地方;
    # Server (注意需要输入OCSP密钥密码)
    $ openssl ocsp -port 9080 \
    -index db/index \
    -rsigner certs/root-ocsp.crt \
    -rkey private/root-ocsp.key \
    -CA certs/root-ca.crt \
    -text

    # client 测试OCSP响应程序即ocsp证书是否过期(其他签名证书也可验证)
    $ openssl ocsp \
    -issuer certs/root-ca.crt \
    -CAfile certs/root-ca.crt \
    -cert certs/root-ocsp.crt \
    -url http://127.0.0.1:9080

    输出结果中的verify OK表示已经成功验证签名,而good表示这张证书还没有被吊销。

    1
    2
    3
    Response verify OK
    certs/root-ocsp.crt: good
    This Update: Aug 20 07:24:56 2020 GMT
    WeiyiGeek.vertify-OCSP

    WeiyiGeek.vertify-OCSP

Tips: 由于OCSP证书是没有吊销信息的所以无法吊销它们,因此您会希望极可能去减少他们的声明周期,上面设置成为30天但是后续需要频繁地创建新的OCSP证书(所以万事皆有好有坏);


  • 6.创建二级CA的过程和根CA几乎完全一样,但我们需要对原有的root-ca.conf进行适当的修改生成二级CA的配置;
    需求如下:

    1) 二级CA名称更改为sub-ca并且使用另一个可分辨名称;
    2) 将二级CA的OCSP响应程序放在另外一个端口,主要是因为ocsp命令不识别虚拟主机;
    3) 同样证书默认生命周期是365天我们会每隔30天生成全新的CRL文件;

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# (1) 二级CA初始化与配置文件
mkdir -vp /opt/cert/sub/{certs,private,conf,server,client,db}
sudo chmod 700 /opt/cert/sub/private
touch /opt/cert/sub/db/index
openssl rand -hex 16 > /opt/cert/sub/db/serial
echo 1001 > /opt/cert/sub/db/crlnumber

tee conf/sub-ca.conf <<-'EOF'
[default]
domain_suffix = wieyigeek.top
default_ca = sub_ca_default #默认CA配置
# -- 修改点开始---
name = sub-ca
ocsp_url = http://ocsp.$name.$domain_suffix:9081
# -- 修改点结束---
aia_url = http://$name.$domain_suffix/$name.crt
crl_url = http://$name.$domain_suffix/$name.crl
name_opt = utf8,esc_ctrl,multiline,lname,align

[ca_dn]
countryName = "CN"
organizationName = "WeiyiGeek"
# --- 修改点 ----
commonName = "Sub CA"

[sub_ca_default]
home = /opt/cert/sub
database = $home/db/index
serial = $home/db/serial
crlnumber = $home/db/crlnumber
new_certs_dir = $home/certs
certificate = $home/certs/$name.crt
private_key = $home/private/$name.key
RANDFILE = $home/private/.random
unique_subject = no

# --- 修改开始 ---
default_days = 365
default_crl_days = 30
copy_extensions = copy
# --- 修改结束 ---

# - 默认情况下使用SHA256作为签名摘要算法
default_md = sha256
policy = policy_c_o_match # 安全策略配置
# - 默认策略( policy_c_o_match)限制了这张CA签发的证书的国家名和组织名会与CA本身一样 (公共CA通常不会这样使用但对于私有CA来说该方式比较合适)
# - supplied(提供),optional(可选择的)
[policy_c_o_match]
countryName = match
stateOrProvinceName = optional
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[req]
default_bits = 4096
encrypt_key = yes
default_md = sha256
utf8 = yes
string_mask = utf8only
prompt = no
distinguished_name = ca_dn #辨别名称
req_extensions = ca_ext #证书请求扩展配置

[ca_ext]
basicConstraints = critical,CA:true
subjectKeyIdentifier = hash
keyUsage = critical,keyCertSign,cRLSign


[sub_ca_ext]
authorityInfoAccess = @issuer_info
authorityKeyIdentifier = keyid:always
basicConstraints = critical,CA:true,pathlen:0
crlDistributionPoints = @crl_info
extendedKeyUsage = clientAuth,serverAuth
keyUsage = critical,keyCertSign,cRLSign
nameConstraints = @name_constraints
subjectKeyIdentifier = hash

[crl_info]
URI.0 = $crl_url

[issuer_info]
caIssuers;URI.0 = $aia_url
OCSP;URI.0 = $ocsp_url

[name_constraints]
permitted;DNS.0=example.com
permitted;DNS.1=example.org
excluded;IP.0=0.0.0.0/0.0.0.0
excluded;IP.1=0:0:0:0:0:0:0:0/0:0:0:0:0:0:0:0

[ocsp_ext]
authorityKeyIdentifier = keyid:always
# 从扩展可以看出这张证书不是一个CA
basicConstraints = critical,CA:false
extendedKeyUsage = OCSPSigning
keyUsage = critical,digitalSignature
subjectKeyIdentifier = hash

# -- 修改点:server_ext 与client_ext 用于服务器和客户端证书的生成 ---
[server_ext]
authorityInfoAccess = @issuer_info
authorityKeyIdentifier = keyid:always
basicConstraints = critical,CA:false
crlDistributionPoints = @crl_info
extendedKeyUsage = clientAuth,serverAuth
keyUsage = critical,digitalSignature,keyEncipherment
subjectKeyIdentifier = hash

[client_ext]
authorityInfoAccess = @issuer_info
authorityKeyIdentifier = keyid:always
basicConstraints = critical,CA:false
crlDistributionPoints = @crl_info
extendedKeyUsage = clientAuth
keyUsage = critical,digitalSignature
subjectKeyIdentifier = hash
EOF

Tips: 配置文件中copy_extensions值为copy意味着在生成新证书的时候如果配置文件里面没有设置某些扩展,此时它将会使用CSR文件里面的扩展字段; 但是这个特性有几分危险因为允许其他人可以在一定程度上直接控制证书里面的内容(在准备CSR文件的时候有可能被攻击者加入某些需要字段,此时在生成证书便可能被复制加入到证书中),不过我认为在较小的环境中这么做是可以的。

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# (2) 按照根CA的过程创建一个同样的目录结构,不过可以使用另外一个名称比如sub-ca。
# 根二级CA的证书请求文件与密钥生成
openssl req -new \
-config conf/sub-ca.conf \
-out sub/certs/sub-ca.csr \
-keyout sub/private/sub-ca.key
# Generating a 4096 bit RSA private key
# writing new private key to 'sub/private/sub-ca.key'
# Enter PEM pass phrase: #pass -> weiyigeeksub


# (3) 使用根CA来签发证书,-extensions开关指向配置文件中的sub_ca_ext 从而使用二级CA所需要的扩展;
$ openssl ca \
-config conf/root-ca.conf \ # 此处的特殊性采用根CA签发二级CA
-in sub/certs/sub-ca.csr \
-out sub/certs/sub-ca.crt \
-extensions sub_ca_ext
# Using configuration from conf/root-ca.conf
# Enter pass phrase for /opt/cert/private/root-ca.key: weiyigeek
# 检查请求是否与签名匹配
# Signature ok
# Certificate:
# Data:
# Version: 3 (0x2)
# Serial Number:
# 37:56:c1:be:ba:88:0b:33:0e:06:ac:fe:58:fd:87:27
# Issuer:
# countryName = CN
# organizationName = WeiyiGeek
# commonName = Root CA
# Validity
# Not Before: Aug 20 09:06:16 2020 GMT
# Not After : Aug 18 09:06:16 2030 GMT
# 证书包含二级CA (关键点)
# Subject:
# countryName = CN
# organizationName = WeiyiGeek
# commonName = Sub CA
# Subject Public Key Info:
# Public Key Algorithm: rsaEncryption
# Public-Key: (4096 bit)
# Modulus:
# 00:b6:cc:db:86:9a:65:2d:f7:89:38:88:8d:52:9c:
# .....
# 93:39:c1
# Exponent: 65537 (0x10001)
# X509v3 extensions:
# Authority Information Access:
# CA Issuers - URI:http://root-ca.wieyigeek.top/root-ca.crt
# OCSP - URI:http://ocsp.root-ca.wieyigeek.top:9080
# X509v3 Authority Key Identifier:
# keyid:4B:B7:11:BE:C3:61:01:5F:C4:57:CC:9C:CE:E4:3C:3D:A6:E7:7F:56
# X509v3 Basic Constraints: critical
# CA:TRUE, pathlen:0
# X509v3 CRL Distribution Points:
# Full Name:
# URI:http://root-ca.wieyigeek.top/root-ca.crl
# X509v3 Extended Key Usage:
# TLS Web Client Authentication, TLS Web Server Authentication
# X509v3 Key Usage: critical
# Certificate Sign, CRL Sign
.....
# X509v3 Subject Key Identifier:
# 2E:68:BB:4E:04:63:99:70:0F:FB:DC:D9:9C:C2:9B:D6:27:D7:97:86
# Certificate is to be certified until Aug 18 09:06:16 2030 GMT (3650 days)
# 签署的证书? [y/n]:y
#1 / 1的证书请求被认证,提交? [y/n]y
# Write out database with 1 new entries | 写出有1个新条目的数据库
# Data Base Updated | 数据库更新


# (4) 使用ca命令的-gencrl开关给二级CA生成sub-ca.crl文件
$ sudo openssl ca -gencrl -config conf/sub-ca.conf -out sub/certs/sub-ca.crl
# Enter pass phrase for /opt/cert/sub/private/sub-ca.key: weiyigeeksub


# (5)二级CA之OCSP响应程序的密钥和证书生成:
# OCSP 密钥与证书请求文件生成
openssl req -new \
-newkey rsa:2048 \
-subj "/C=CN/O=WeiyiGeek/CN=OCSP Sub Responder" \
-keyout sub/private/sub-ocsp.key \
-out sub/certs/sub-ocsp.csr
# writing new private key to 'sub/private/sub-ocsp.key'
# Enter PEM pass phrase: # weiyigeeksubocsp
# Verifying - Enter PEM pass phrase:

# 其次需要使用根CA签发一张证书,任然采用-extensions选择ocsp_ext以确保设置了OCSP签名所需要的扩展;
# 在root-ca.conf 配置文件中设置键值对如default_crl_days = 365,证书的生命周期减少为365天;
$ openssl ca \
-config conf/sub-ca.conf \
-in sub/certs/sub-ocsp.csr \
-out sub/certs/sub-ocsp.crt \
-extensions ocsp_ext \
-days 30
# Enter pass phrase for /opt/cert/sub/private/sub-ca.key: weiyigeeksub
# Check that the request matches the signature
# Signature ok
# Certificate Details:
# Certificate:
# Data:
# Version: 3 (0x2)
# Serial Number:
# 37:56:c1:be:ba:88:0b:33:0e:06:ac:fe:58:fd:87:2a
# Issuer:
# countryName = CN
# organizationName = WeiyiGeek
# commonName = Sub CA
# Validity
# Not Before: Aug 20 14:58:01 2020 GMT
# Not After : Sep 19 14:58:01 2020 GMT
# Subject:
# countryName = CN
# organizationName = WeiyiGeek
# commonName = OCSP Sub Responder



# (4) 服务端/客户端证书请文件和密钥生成
# private key (此处采用私钥加密,在测试的时候可-nodes即禁止对私钥文件加密)
openssl genrsa -des3 -out sub/private/server.key 2048 # weiyigeekserver
openssl genrsa -des3 -out sub/private/client.key 2048 # weiyigeekclient
# generate csr (需要注意Organization Name与CA机构CA certificate一致为WeiyiGeek)
openssl req -new -key sub/private/server.key -out sub/certs/server.csr
# -----
# Country Name (2 letter code) [XX]:CN
# State or Province Name (full name) []:ChongQing
# Locality Name (eg, city) [Default City]:CQ
# Organization Name (eg, company) [Default Company Ltd]:WeiyiGeek
# Organizational Unit Name (eg, section) []:weiyigeek
# Common Name (eg, your name or your server's hostname) []:server.weiyigeek.top
# Email Address []:master@weiyigeek.top
openssl req -new -key sub/private/client.key -out sub/certs/client.csr
# -----
# Country Name (2 letter code) [XX]:CN
# State or Province Name (full name) []:ChongQing
# Locality Name (eg, city) [Default City]:CQ
# Organization Name (eg, company) [Default Company Ltd]:WeiyiGeek
# Organizational Unit Name (eg, section) []:client
# Common Name (eg, your name or your server's hostname) []:weiyigeek.top
# Email Address []:master@weiyigeek.top


# (5) 二级CA操作之签发服务器证书,即-extension server_ext
openssl ca \
-config conf/sub-ca.conf \
-in sub/certs/server.csr \
-out sub/certs/server.crt \
-extensions server_ext
# Enter pass phrase for /opt/cert/sub/private/sub-ca.key:
# Check that the request matches the signature
# Certificate:
# Data:
# Version: 3 (0x2)
# Serial Number:
# 5e:75:c7:d6:4e:33:0f:03:58:d4:82:d3:94:75:03:46
# Issuer:
# countryName = CN
# organizationName = WeiyiGeek
# commonName = Sub CA
# Validity
# Not Before: Aug 20 15:40:41 2020 GMT
# Not After : Aug 20 15:40:41 2021 GMT
# Subject:
# countryName = CN
# stateOrProvinceName = ChongQing
# organizationName = WeiyiGeek
# organizationalUnitName = weiyigeek
# commonName = server.weiyigeek.top
# emailAddress = master@weiyigeek.top
# Subject Public Key Info:
# Public Key Algorithm: rsaEncryption
# Public-Key: (2048 bit)
# Modulus:
# 00:e6:17:73:d8:66:9c:08:b6:2d:99:66:0c:a5:a3:
# ........
# 38:30:4e:c1:66:c2:cd:f3:b2:5e:2c:dd:17:3d:5b:
# 04:6d
# Exponent: 65537 (0x10001)
# X509v3 extensions:
# Authority Information Access:
# CA Issuers - URI:http://sub-ca.wieyigeek.top/sub-ca.crt
# OCSP - URI:http://ocsp.sub-ca.wieyigeek.top:9081 # Certificate Reponse 认证
# X509v3 Authority Key Identifier:
# keyid:0E:1B:6D:AA:0E:D5:6E:E4:C4:85:D6:48:37:3F:18:1B:FF:4C:BC:08
# X509v3 Basic Constraints: critical
# CA:FALSE
# X509v3 CRL Distribution Points:
# Full Name:
# URI:http://sub-ca.wieyigeek.top/sub-ca.crl
# X509v3 Extended Key Usage:
# TLS Web Client Authentication, TLS Web Server Authentication
# X509v3 Key Usage: critical
# Digital Signature, Key Encipherment
# X509v3 Subject Key Identifier:
# 20:F4:A9:32:B3:05:57:B1:10:E5:F7:73:D2:DF:E1:8D:45:8C:1D:67


# (6) 二级CA操作之签发客户端证书,即-extension client_ext
openssl ca \
-config conf/sub-ca.conf \
-in sub/certs/client.csr \
-out sub/certs/client.crt \
-extensions client_ext

测试证书:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Listen
openssl ocsp -port 9081 \
-index sub/db/index \
-rsigner sub/certs/sub-ocsp.crt \
-rkey sub/private/sub-ocsp.key \
-CA sub/certs/sub-ca.crt -text
# Enter pass phrase for sub/private/sub-ocsp.key: weiyigeeksubocsp
# Waiting for OCSP client connections...

# Client connection Test
openssl ocsp \
-issuer sub/certs/sub-ca.crt \
-CAfile certs/root-ca.crt \
-cert sub/certs/server.crt \
-url http://127.0.0.1:9081

注意事项:

  • (1) 当收到新证书申请请求的时候,你需要在对所有信息进行验证之后才能进行操作。你需要确保所有资料符合规定,特别是当你处理的CSR文件是别人生成的时。特别要注意证书的可分辨名称以及basicContraints和subjectAlternativeName扩展。
  • (2) 二级CA的CRL生成和证书的吊销过程与根CA是一样的。
  • (3) 唯一不同的是OCSP响应程序所使用的端口;二级CA使用的是9081端口;
  • (4) 推荐OCSP响应程序使用独立的证书,这样可以避免将二级CA部署到公开的服务器上.