CA与SSL
本帖最后由 ypengfei 于 2021-5-11 08:28 编辑这是很久以前写的一些东西,发上来看看大家是否有用。
# CA与SSL
### 一、名词解释:
**1. 对称加密:**
对称加密很简单,就是消息传递的双方共享同一个密码。消息发送人用密码对消息进行加密,然后将密文发给消息接收人,消息接受人使用此密码对密文进行解密,然后阅读。
**2. 非对称加密:**
非对称加密是指消息传递双方使用不同的密码,两个密码分别被称为私钥和公钥。私钥和公钥之间具备一定的数学关系:私钥加密的内容只有对应的公钥才能解密,公钥加密的内容只有对应的私钥才能解密。
```wiki
公钥:可以发给任意人
私钥:只能自己知道
pk为公钥,sk为私钥
通过公钥加密的数据,只能通过私钥解密
f(pk,data)=y// 加密
f(sk,y)=data// 解密
通过私钥加密的数据,只能通过公钥解密
f(sk,data)=y// 加密
f(pk,y)=data// 解密
```
需要使用此加密方式的人会具备私钥和公钥,私钥只有自己知道,公钥则对特定群体或者所有人公开。这种算法最大的优点就是安全,密码只有自己一个人知道,缺点则是计算量较大,效率低,不适合对大量内容进行加密。
<div style="font-size:15px">应用场景:加密邮件。张三要向李四发送一封加密的邮件,因此张三使用李四的公钥对邮件内容进行加密,然后将密文发送给李四,即使中途王五截获到邮件内容也无法解读。因为只有李四的私钥才能解密邮件内容。</div>
**3. 消息摘要(MessageDigest)**
所谓消息摘要是指使用单向哈希算法,以任意长度的报文计算得到的固定长度的哈希值。所谓单向是指改算法是不可逆的,根据消息摘要无法计算出输入报文。消息摘要的另一个特定是:对输入报文的任何改动,都会导致最终的计算结果(也就是消息摘要本身)发生巨大的变化。因此,消息摘要可以认为是数字信息的指纹。
<div style="font-size:15px">应用场景:常用的消息摘要算法有MD5、SHA等,我们下载Tomcat的时候,在软件下载链接后面经常看到pgp、md5、sha1等链接,点进去之后可以看到一串无意义的字符,这些就是与算法对应的消息摘要,用来确保你下载的软件包完整可靠,没有被篡改。当然,你需要根据你下载的软件自己计算出一个报文摘要,如果与之相同,说明你下载的软件包没有问题,否则可能已经被人动过手脚。</div>
**4. 数字签名(DigitalSignature):**
就是把消息摘要通过私钥进行加密发送给别人。
如果消息接受方需要验证真伪,首先使用消息发送方的公钥对数字签名进行解密从而得到报文消息摘要(如果解密失败,则签名肯定有问题)。然后使用相同的消息摘要算法重新计算接受到的消息报文的消息摘要,如果计算得到的消息摘要与解密得到的消息摘要不一致,则消息报文被人篡改。
**5. 数字证书(DigitalCertificate):**
数字证书类似网上身份证,由第三方权威机构签发,用于鉴别证书持有人的身份的真实性。数字证书上包含了证书持有人的基本信息(如:网站域名、邮箱地址等)、证书持有人的公钥、证书颁发机构信息、证书颁发机构的数字签名以及证书有效期。
数字证书的申请过程通常是:证书申请人向证书签发机构提交申请,申请中包含申请人身份的基本信息以及申请人公钥。证书签发机构通过各种手段核实申请来源以及申请信息的真实性。核实通过之后,真实签发机构向申请人签发数字证书。
证书签发机构也有一个证书,其中包含了证书签发机构的公钥。任何人都可以获得该证书,并使用此证书来验证该机构签发的所有证书的真伪。默认情况下,大多数操作系统内已经内置了全球知名证书签发单位的根证书。
**6. 证书请求文件CSR:**
CSR是Certificate Signing Request的英文缩写,即证书请求文件,也就是证书申请者在申请数字证书时由CSP(加密服务提供者)在生成私钥的同时也生成证书请求文件,证书申请者只要把CSR文件提交给证书颁发机构后,证书颁发机构使用其根证书私钥签名就生成了证书公钥文件,也就是颁发给用户的证书。
<span style="color:red">证书下发后,CSR无需使用,仅提交时候需要。 </span>
### 二、CA(Certificate Authority)
上面提到的数字证书就是CA发行的。CA是Certificate Authority的缩写,也叫“证书授权中心”。它是负责管理和签发证书的第三方机构,作用是检查证书持有者身份的合法性,并签发证书,以防证书被伪造或篡改。
所以,<span style="color:blue">CA实际上是一个机构</span>,负责“证件”印制核发。就像负责颁发身份证的公安局、负责发放行驶证、驾驶证的车管所。
CA证书==数字证书
<span style="color:blue">CA 证书就是CA颁发的证书,也就我们常说的数字证书,也就是1.5里描述的。</span>包含证书拥有者的身份信息,CA机构的签名,公钥和私钥。身份信息用于证明证书持有者的身份;CA签名用于保证身份的真实性;公钥和私钥用于通信过程中加解密,从而保证通讯信息的安全性。
CA本身也有自己的证书,我们成为根证书,包括公钥和私钥,暂且称为cpk,csk;
### 三、HTTPS过程讲解
> Https核心是非对称+对称+HASH+CA的一种组合方式,真正的数据传输是对称加密。
具体的HTTPS过程如下:
1. 浏览器<span style="color:red">明文</span>发送请求给服务端,请求包括本机支持的ssl版本、非对称加密算法、<span style="color:red">随机数1</span>;
2. 服务端处理此请求,返回确定的<span style="color:red">ssl版本、后续使用的对称加密算法、随机数2、以及CA颁发的证书</span>(证书里包括服务端加密后的pk f(csk,pk)=data、加密算法、签发者)
3. 浏览器接到返回后,首先验证证书是否通过,没通过会有提示(很常见),验证方法为用CA证书机构的cpk验证,cpk很多时候是系统自带的;
> 至此,是为了保证客户端获取的服务端的pk是安全可靠的。后续再确定传输用的秘钥之前,都通过pk进行数据的加解密传输。
4. 证书验证通过后,发送给服务端用pk加密过的的数据:<span style="color:red">随机数3、一个hash值hash(随机数1,随机数2)</span>;
5. 服务端解密数据,验证hash值:同样使用hash(<span style="color:red">随机数1</span>,<span style="color:red">随机数2</span>)算法,用计算结果跟客户端传过来的hash值进行对比,这里的<span style="color:red">随机数1</span>和<span style="color:red">2</span>不是用客户端传过来的,而是服务端在前边过程中自己记录下来的;
6. 验证通过后,通过hash算法(<span style="color:red">随机数1</span>、<span style="color:red">随机数2</span>、<span style="color:red">随机数3</span>)计算出一个<span style="color:red">key</span>,这个key是作为数据传输的对称加密秘钥用,不返回给客户端,对1.2.4步骤的数据全部进行哈希算法后,比如zz1,非对称加密返回zz1给客户端;
7. 客户端也用1.2.4步骤的数据全部进行哈希算法值zz2,然后比较服务端传过来的zz1是否相等,如果相等则服务端认证通过;
> 至此,通过以上步骤,就确定了key并且认证了服务端合法性。
8. 后续数据发送则通过这个key进行对称加密传输;
### 四、openssl命令
openssl命令的格式是"openssl command command-options args",command部分有很多种命令,这些命令需要依赖于openssl命令才能执行,所以称为伪命令(pseudo-command),每个伪命令都有各自的功能,大部分command都可以直接man command查看命令的用法和功能。红色是比较重要的命令。
* **<span style="color:red">openssl genrsa</span>**
> genrsa用于生成(https://zh.wikipedia.org/wiki/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95)私钥,不会生成公钥,因为公钥是基于私钥生成的。
```wiki
openssl genrsa [-out filename] [-passout arg] [-des] [-des3] [-idea]
选项说明:
-out filename:将生成的私钥保存至filename文件,若未指定输出文件,则为标准输出。
-numbits :指定要生成的私钥的长度,默认为1024。该项必须为命令行的最后一项参数。
-des|-des3|-idea:指定加密私钥文件用的算法,这样每次使用私钥文件都将输入密码,太麻烦所以很少使用。
-passout args:加密私钥文件时,传递密码的格式,如果要加密私钥文件时单未指定该项,则提示输入密码。
```
例子:
```shell
# 用aes256的算法生成一个私钥并保存在ca.key.pem文件里
openssl genrsa -aes256 -out ca.key.pem 4096
```
* **<span style="color:red">openssl req</span>**
req大致有3个功能:生成证书请求文件CSR、验证证书请求文件和创建根CA。以下是官方解释:
```wiki
The req command primarily creates and processes certificate requests in PKCS#10 format.It can additionally create self-signed certificates, for use as root CAs, for example.
```
1. 生成CSR文件
```shell
# 根据pri_key.pem私钥文件生成证书请求文件req1.csr
openssl req -new -key pri_key.pem -out req1.csr
#在敲下回车键后,默认会进入交互模式让你提供你个人的信息,直接回车将选择使用默认值,输入点"."将表示该信息项留空。"Common Name",它表示的是为哪个域名、子域名或哪个主机申请证书,未来证书请求被签署后将只能应用于"Common Name"所指定的地址。
```
2. 查看CSR文件
```shell
openssl req -in req1.csr -text
#将"-text"和"-noout"结合使用,则只输出证书请求的文件头部分。
openssl req -noout -text -in req1.csr
```
3. 验证CSR文件
```shell
openssl req -verify -in req1.csr
```
4. 创建自签名证书(可用于自建根CA时)
使用openssl req自签署证书时,需要使用"-x509"选项,由于是签署证书请求文件,所以可以指定"-days"指定所颁发的证书有效期。
```shell
# 用pri_key.pem私钥文件,req1.csr的证书请求文件,创建CA1.crt证书文件,证书有效期365天。
openssl req -x509 -key pri_key.pem -in req1.csr -out CA1.crt -days 365
```
实际上,"-x509"选项和"-new"或"-newkey"配合使用时,可以不指定证书请求文件,它在自签署过程中将在内存中自动创建证书请求文件,当然,既然要创建证书请求文件,就需要人为输入申请者的信息了。例如:
```shell
# 使用-new参数就不用特意创建CSR文件
openssl req -new -x509 -key pri_key.pem -out CA1.crt -days 365
```
* **openssl CA **
用于签署证书请求、生成吊销列表CRL以及维护已颁发证书列表和这些证书状态的数据库。
CA命令是用于签署证书的,所以它所需要的文件除了配置文件外就是私钥文件和证书请求文件,而签名后生成的文件是证书文件,因此使用"-in"指定的对象是待签署文件,"-infiles"则是指定多个待签署文件,"-keyfile"是指定私钥文件,"-out"是指定输出的证书文件。
```shell
openssl ca [-verbose] [-config filename] [-name section] [-startdate date] [-enddate date] [-days arg] [-md arg] [-policy arg] [-keyfile arg] [-key arg] [-passin arg] [-cert file]
[-selfsign] [-in file] [-out file] [-notext] [-outdir dir] [-infiles] [-ss_cert file] [-preserveDN] [-noemailDN] [-batch] [-extensions section] [-extfile section] [-subj arg] [-utf8]
【选项说明:】
-config filename :指定要使用的配置文件,指定后将忽略openssl.cnf中指定的关于ca的配置选项。
-name section :指定使用配置文件中的那个section。指定后将忽略openssl.cnf中的default_ca段。
-in filename :指定要被CA签署的单个证书请求文件。根CA为其他证书签署时使用。
-infiles :该选项只能是最后一个选项,该选项所接的所有参数都被认为是要被签署的证书请求文件,即一次性签署多个请求文件时使用的选项。
-selfsign :自签署。指定-ss_cert选项时该选项被忽略。
-ss_cert filename:将被CA自签署的单个证书文件。也就是说要重新签署证书。
-out filename :证书的输出文件,同时也会输出到屏幕。不指定时默认输出到stdout。
-outdir dir_name :证书的输出目录。指定该选项时,将自动在此目录下生成一个文件名包含16进制serial值的".pem"证书文件。
-cert :CA自己的证书文件。
-keyfile filename:指定签署证书请求时的私钥文件,即CA自己的私钥文件。
-key passwd_value:指定私钥的加密密码。
-passin arg :传递解密密码
-verbose :打印操作执行时的详细信息
-notext :禁止以文本格式将证书输出到"-out"指定的文件中
-days arg :证书有效期限,从创建时刻开始算startdate,有效期结束点为enddate。
-startdate :自定义证书的开始时间,和"-enddate"一起使用可以推算出证书有效期。
-enddate :自定义证书的结束时间。
-md alg :指定单向加密算法
-policy arg :该选项是配置文件中的section内容,该选项指定了证书信息中的field部分是否需要强制提供还是要强制匹配,
:或者可提供可不提供。详细的见配置文件说明。
-extensions section:指定当前创建的证书使用配置文件中的哪个section作为扩展属性。
-batch :签署时使用批处理模式,即非交互模式。该模式下不会有两次询问(是否签署、是否提交)。
-subj arg :替换证书请求中的subject,格式/type0=value0/type1=value1/type2=...
```
* **openssl x509(签署和自签署)**
主要用于输出证书信息,也能够签署证书请求文件、自签署、转换证书格式等。openssl x509工具**不会使用openssl配置文件中的设定,而是完全需要自行设定或者使用该伪命令的默认值,它就像是一个完整的小型的CA工具箱**。
```shell
openssl x509 [-in filename] [-out filename] [-serial] [-hash] [-subject_hash] [-issuer_hash] [-subject] [-issuer]
[-nameopt option] [-email] [-startdate] [-enddate] [-purpose] [-dates] [-modulus] [-pubkey] [-fingerprint] [-noout]
[-days arg] [-set_serial n] [-signkey filename] [-x509toreq] [-req] [-CA filename] [-CAkey filename] [-CAcreateserial]
[-CAserial filename] [-text] [-md2|-md5|-sha1|-mdc2] [-extfile filename] [-extensions section]
【输入输出选项:】
-in filename:指定证书输入文件,若同时指定了"-req"选项,则表示输入文件为证书请求文件。
-out filename :指定输出文件
-md2|-md5|-sha1|-mdc2:指定单向加密的算法。
【信息输出选项:】
-text:以text格式输出证书内容,即以最全格式输出,
:包括public key,signature algorithms,issuer和subject names,serial number以及any trust settings.
-certopt option:自定义要输出的项
-noout :禁止输出证书请求文件中的编码部分
-pubkey :输出证书中的公钥
-modulus :输出证书中公钥模块部分
-serial :输出证书的序列号
-subject :输出证书中的subject
-issuer :输出证书中的issuer,即颁发者的subject
-subject_hash:输出证书中subject的hash码
-issuer_hash :输出证书中issuer(即颁发者的subject)的hash码
-hash :等价于"-subject_hash",但此项是为了向后兼容才提供的选项
-email :输出证书中的email地址,如果有email的话
-startdate :输出证书有效期的起始日期
-enddate :输出证书有效期的终止日期
-dates :输出证书有效期,等价于"startdate+enddate"
-fingerprint :输出指纹摘要信息
```
### 五、自签证书
基于openssl来创建自签的证书,所谓自签证书就是自己做CA角色,即root CA角色,由于自己做root CA角色,没有收费CA角色受到行业认可,根证书也没有预先保存在操作系统里,因此浏览器对于自签CA签出来的证书,会提示有问题。
自己做CA角色,就要管理多个pair对,CA有csk(私钥)和cpk(公钥),他们保存在root key(ca.key.pem)和root certificate(ca.cert.pem)。
通常情况下,root CA 不会直接为服务器或者客户端签证,它们会先为自己生成几个中间 CA(intermediate CAs),这几个中间 CA 作为 root CA 的代表为服务器和客户端签证
**注意:一定要在绝对安全的环境下创建 root pair,可以断开网络、拔掉网线和网卡,当然,如果是测试玩一玩就不用这么认真了。**
**<span style="color:red">在自己做CA角色自己给别人颁发证书的时候,用独立的openssl配置文件配合比较方便,其中配置文件里的路径,需要绝对路径,否则会报错:Error opening CA private key,路径”/Users/xyz/ca“根据自己的实际情况修改</span>**
使用`openssl req -x509`、`openssl x509`和`openssl ca`都可以自签署证书请求文件,后边用的`openssl req -x509`、`openssl ca`命令来签订证书。
<span style="color:red">**整体流程简单来说先通过root openssl配置文件,把root 的key和cert创建出来,然后创建中间pair的key和CSR,再用root的key把中间pair的cert创建出来。在把网站证书的key创建出来,然后通过中间pair的key把网站证书的cert创建出来。**</span>
整个流程最主要的是弄清楚使用的是哪个秘钥,实际下边操作起来是看具体引用了哪个openssl的配置文件,因为秘钥参数是写在配置文件里的。
自签步骤:
#### (一)建立根CA(root pair)文件(key的cert)
1. 设定文件夹结构:
```shell
mkdir -p /Users/xyz/ca
cd /Users/xyz/ca
mkdir certs crl newcerts private
chmod 700 private
touch index.txt
echo 1000 > serial // 这将创建crlnumber文件,并从1000开始数字迭代。这将用于将来的证书吊销需求。???
```
2. 配置 openssl 设置
```shell
使用root-ca.md里的openssl模板,注意文件里的路径
```
3. 创建 root key文件,密码可为空,设定权限为只可读
```shell
cd /Users/xyz/ca
openssl genrsa -aes256 -out private/ca.key.pem 4096
Enter pass phrase for ca.key.pem: secretpassword
输入:123456// 这个密码自己记住
Verifying - Enter pass phrase for ca.key.pem: secretpassword
输入:123456// 重复输入密码验证
// 会在private目录里建立ca.key.pem文件
chmod 400 private/ca.key.pem
```
4. 创建 root cert,权限设置为可读
```shell
cd /Users/xyz/ca
# 用openssl -x509 -new命令,openssl.cnf配置文件,私钥文件,创建一个7300天(20年)的证书,-extensions v3_ca表示将配置文件里的v3_ca作为证书的扩展项,-x509 -new参数表示会自动创建中间的SCR文件,不用单独创建,上边的openssl命令里有说明
openssl req -x509 -new -days 7300 -sha256 -extensions v3_ca \
-config openssl.cnf \
-key private/ca.key.pem \
-out certs/ca.cert.pem
提示:Enter pass phrase for private/ca.key.pem:
输入上边的密码:123456
继续提示:
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) :CN # 注意:这里只能输入两个字符;
State or Province Name :Beijing
Locality Name []:# 直接回车
Organization Name :xyz Technology (Beijing) Co., Ltd.
Organizational Unit Name []:xyz Certificate Authorit
Common Name []:xyz Root CA
Email Address []: # 直接回车
# 到这里会在certs里生成ca.cert.pem文件
chmod 444 certs/ca.cert.pem# 修改为只读权限
```
5. 验证证书
```shell
openssl x509 -noout -text -in certs/ca.cert.pem
```
正常应该是包括:
* 数字签名(Signature Algorithm)
* 有效时间(Validity)
* 主体(Issuer)
* 公钥(Public Key)
* X509v3 扩展,openssl config 中配置了 v3_ca,所以会生成此项
至此root pair就创建完成了
#### (二)创建中间对
> 先把intermediate pair的的key的CSR文件创建出来,然后用Root CA把证书签出来。
>
> 用Root CA签pair证书,主要是需要引用Root CA的OpenSSL的配置文件,里边有Root CA的Key文件地址
1. **创建中间对(intermediate pair)**
目前我们已经拥有了 Root Pair,事实上已经可以用于证书的发放了,但是由于根证书很干净,特别容易被污染,所以我们需要创建中间 pair 作为 root pair 的代{过}{滤}理,生成过程同上,只是细节略微不一样。
2. 生成目录结构和 openssl 的配置,这里的配置是针对 intermediate pair 的,注意替换这里的/Users/xyz/ca路径地址
```shell
mkdir /Users/xyz/ca/intermediate
cd /Users/xyz/ca/intermediate
mkdir certs crl csr newcerts private
chmod 700 private
touch index.txt
echo 1000 > serial
echo 1000 > /Users/xyz/ca/intermediate/crlnumber
```
3. 配置intermediate key的openssl文件
```shell
使用intermediate-ca.md里的openssl模板
```
4. 创建 intermediate key,密码可为空,设定权限为只可读
```shell
cd /Users/xyz/ca
openssl genrsa -aes256 -out intermediate/private/intermediate.key.pem 4096
Enter pass phrase for intermediate.key.pem: secretpassword输入:123456
Verifying - Enter pass phrase for intermediate.key.pem: secretpassword 输入:123456
chmod 400 intermediate/private/intermediate.key.pem
```
5. 创建 intermediate csr文件,设定权限为只可读,这里需要特别注意的一点是 **Common Name 不要与 root pair 的一样**
```shell
cd /Users/xyz/ca
openssl req -config intermediate/openssl.cnf -new -sha256 \
-key intermediate/private/intermediate.key.pem \
-out intermediate/csr/intermediate.csr.pem
Country Name (2 letter code) :CN
State or Province Name :Beijing
Locality Name []: # 直接回车
Organization Name :xyz Technology (Beijing) Co., Ltd.
Organizational Unit Name []:xyz Certificate Authorit
Common Name []:xyz Intermediate CA // 这里注意,不要跟root pair的一样
Email Address []:
```
6. 使用root cert的openssl配置文件生成中间pair证书(也就是用Root CA签中间证书),使用 `v3_intermediate_ca` 扩展签名,密码可为空,中间 pair 的有效时间一定要为 root pair 的子集
```shell
cd /Users/xyz/ca
openssl ca -config openssl.cnf -extensions v3_intermediate_ca \
-days 3650 -notext -md sha256 \
-in intermediate/csr/intermediate.csr.pem \
-out intermediate/certs/intermediate.cert.pem
Sign the certificate? : y
1 out of 1 certificate requests certified, commit? y
```
此时 root 的 `index.txt` 中将会多出这么一条记录
```shell
V 300227150539Z 1000 unknown /C=CN/ST=Beijing/O=xyz Technology (Beijing) Co., Ltd./OU=xyz Certificate Authorit/CN=xyz Intermediate CA
```
7. 验证中间 pair 的正确性
```shell
openssl x509 -noout -text -in intermediate/certs/intermediate.cert.pem
输出一堆东西
openssl verify -CAfile certs/ca.cert.pemintermediate/certs/intermediate.cert.pem
输出:intermediate/certs/intermediate.cert.pem: OK
```
8. 浏览器在验证中间证书的时候,同时也会去验证它的上一级证书是否靠谱,创建证书链,将 root cert 和 intermediate cert 合并到一起,可以让浏览器一并验证
```shell
cat intermediate/certs/intermediate.cert.pem \
certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem
chmod 444 intermediate/certs/ca-chain.cert.pem
```
#### (三)创建服务器/客户端证书
>签证书的时候,需要引用intermediate pair的openssl配置文件,因为里边有intermediate pair的私钥
1. 创建服务器/客户端证书
生成我们服务器上需要部署的内容,上面已经解释了为啥需要创建中间证书。root pair 和 intermediate pair 使用的都是 4096 位的加密方式,一般情况下服务器/客户端证书的过期时间为一年,所以可以安全地使用 2048 位的加密方式。
```shell
cd /Users/xyz/ca
openssl genrsa -aes256 \
-out intermediate/private/www.xyz.net.key.pem 2048
Enter pass phrase for intermediate/private/www.xyz.net.key.pem:123456 # 输入密码:123456
Verifying - Enter pass phrase for intermediate/private/www.xyz.net.key.pem:123456 # 确认密码
chmod 400 intermediate/private/www.xyz.net.key.pem
```
2. 创建 `www.xyz.net` 的证书,配置文件需要处理chrome SAN问题,生成CSR
```shell
cd /Users/xyz/ca
openssl req -config intermediate/openssl.cnf \
-key intermediate/private/www.xyz.net.key.pem \
-new -sha256-out intermediate/csr/www.xyz.net.csr.pem
Enter pass phrase for www.xyz.net.key.pem: secretpassword
You are about to be asked to enter information that will be incorporated
into your certificate request.
-----
Country Name (2 letter code) :CN
State or Province Name []:Beijing
Locality Name []:Beijing
Organization Name []:xyz Technology (Beijing) Co., Ltd.
Organizational Unit Name []:web
Common Name []:xyz.net
Email Address []:yanpengfei@lanchaogroup.com
```
3. 使用 intermediate pair 签证上面证书
```shell
cd /Users/xyz/ca
openssl ca -config intermediate/openssl.cnf\
-extensions server_cert -days 375 -notext -md sha256 \
-in intermediate/csr/www.xyz.net.csr.pem \
-out intermediate/certs/www.xyz.net.cert.pem
Sign the certificate? :y
1 out of 1 certificate requests certified, commit? y
chmod 444 intermediate/certs/www.xyz.net.cert.pem
```
可以看到 `/Users/xyz/ca/intermediate/index.txt` 中多了一条记录
```shell
V 210311152405Z 1000 unknown /C=CN/ST=Beijing/L=Beijing/O=xyz Technology (Beijing) Co., Ltd./OU=web/CN=www.xyz.net/emailAddress=yanpengfei@lanchaogroup.com
```
4. 验证证书
```shell
openssl x509 -noout -text \
-in intermediate/certs/www.xyz.net.cert.pem
openssl verify -CAfile intermediate/certs/ca-chain.cert.pem \
intermediate/certs/www.xyz.net.cert.pem
输出:intermediate/certs/www.xyz.net.cert.pem: OK
```
5. 此时我们已经拿到了几个用于部署的文件
* /Users/xyz/ca/intermediate/certs/www.xyz.net.cert.pem
* /Users/xyz/ca/intermediate/private/www.xyz.net.key.pem
* /Users/xyz/ca/intermediate/certs/ca-chain.cert.pem // 根证书的组合文件
#### (四)使用证书
1. 双击 `/Users/xyz/ca/intermediate/certs/ca-chain.cert.pem` 将证书安装到系统中,目的是让本机信任这个 CA,将其当作一个权威 CA,安装 `root pem` 或者 `intermediate chain pem` 都是可以的,它们都具备验证能力。如果不执行这一步,浏览器依然会提示 `net:ERR_CERT_AUTHORITY_INVALID`。
上面申请测试证书时,我设置的 Common Name 为 `www.xyz.net`,由于不在线上机器测试,可以将其添加到 hosts
```shel
sudo vi /etc/hosts
127.0.0.1 www.xyz.net
```
2. 执行下方测试代码
node执行以下代码
```javascript
var https = require('https');
var fs = require('fs');
var options = {
key: fs.readFileSync('/Users/xyz/ca/intermediate/private/www.xyz.net.key.pem'),
cert: fs.readFileSync('/Users/xyz/ca/intermediate/certs/www.xyz.net.cert.pem'),
passphrase: '123456' // 如果生成证书的时候设置了密码,请添加改参数和密码
};
https.createServer(options, function(req, res) {
res.writeHead(200);
res.end('hello world');
}).listen(8000, function(){
console.log('Open URL: //www.xyz.net:8000');
});
```
```shell
node index.js
```
应该可以看到顺利的使用了https
> 使用错误的证书,依然是可以传输数据的,只不过数据传输不再加密,因此服务端无法强制客户端使用ssl加密跟服务器通讯。因此重要的公共服务系统要保证使用的是有效的证书。
#### (五)无 SNI 支持问题
很多公司由于业务众多,域名也是相当多的,为了方便运维,会让很多域名指向同样的 ip,然后统一将流量/请求分发到后端,此时就会面临一个问题:由于 TLS/SSL 在 HTTP 层之下,客户端和服务器握手的时候还拿不到 origin 字段,所以服务器不知道这个请求是从哪个域名过来的,而服务器这边每个域名都对应着一个证书,服务器就不知道该返回哪个证书啦。
SNI 就是用来解决这个问题的,官方解释是
> SNI(Server Name Indication)是为了解决一个服务器使用多个域名和证书的SSL/TLS扩展。一句话简述它的工作原理就是,在连接到服务器建立SSL链接之前先发送要访问站点的域名(Hostname),这样服务器根据这个域名返回一个合适的证书。
然后有将近 25% 的浏览器不支持该字段的扩展,这个问题有两个通用解决方案:
* 使用 VIP 服务器,每个域名对应一个 VIP,然后 VIP 与统一接入服务对接,通过 ip 来分发证书,不过运维成本很高,可能也需要大量的 VIP 服务器
* 采用多泛域名,将多个泛域名证书打包进一个证书,它的缺点是每次添加域名都需要更新证书。
### 六、其他应用场景说明
#### (一)k8s里证书的应用
k8s里,使用证书的地方非常大,比如kubectl调用apiserver的时候,就是通过https进行的。
K8s相关证书文件默认在/etc/kubernetes/pki目录里,admin.conf, controller-manager.conf and scheduler.conf这三个配置文里也引用了这些证书文件。
k8s有几个重要的根证书,分别是ca.crt、front-proxy-ca.crt和etcd-ca,具体信息如下:
```wiki
ca.crt
常用名称和签发者都是kubernetes,有效期为10年,秘钥用途为:数字签名,密钥加密,密钥证书签名
front-proxy-ca.crt
常用名称和签发者都是front-proxy-ca,有效期为10年,秘钥用途为:数字签名, 密钥加密, 密钥证书签名
etcd-ca.crt
常用名称和签发者都是etcd-ca,有效期为10年,秘钥用途为:数字签名, 密钥加密, 密钥证书签名
```
除了几个根证书,还有几个基于根证书签出来的业务证书:
* **apiserver** key和cert
* **apiserver-kubelet-client** key和cert
* **front-proxy-client** key和cert
* **apiserver-etcd-client** key和cert
这四套证书是比较重要的。
> * apiserver:由kubernets签发,有效期为1年,dns名称为:test-master01、kubernetes、kubernetes.default、kubernetes.default.svc、kubernetes.default.svc.cluster.local;ip地址为:10.96.0.1、192.168.0.142
> * apiserver-kubelet-client:由kubernetes签发,有效期为1年,没有dns和ip地址扩展
> * front-proxy-client:由front-proxy-ca签发,有效期为1年,没有dns和ip地址扩展
> * apiserver-etcd-client:由etcd-ca签发,有效期为1年,没有dns和ip地址扩展
其中apiserver、apiserver-kubelet-client和front-proxy-client三个需要固定续期,对于证书文件,k8s有一些命令作为支持:
**检查证书到期时间**
```shell
kubeadm alpha certs check-expiration
```
**手动更新证书:**
```shell
#kubeadm alpha certs renew命令可以手动更新证书,命令格式为:
kubeadm alpha certs renew
kubeadm alpha certs renew
#具体查看帮助文件,其中续订所有证书命令为:
kubeadm alpha certs renew all
输出:
certificate embedded in the kubeconfig file for the admin to use and for kubeadm itself renewed
certificate for serving the Kubernetes API renewed
certificate the apiserver uses to access etcd renewed
certificate for the API server to connect to kubelet renewed
certificate embedded in the kubeconfig file for the controller manager to use renewed
certificate for liveness probes to healtcheck etcd renewed
certificate for etcd nodes to communicate with each other renewed
certificate for serving etcd renewed
certificate for the front proxy client renewed
certificate embedded in the kubeconfig file for the scheduler manager to use renewed
```
**自动更新证书:**
> 自动续期证书google建议通过升级kubeadm集群版本来进行,升级kubeadm集群的过程中会自动续期证书,因为几个重要证书都是1年有效期,所以google希望至少是一年一升级是合适的。
[如何升级kubeadm集群](https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/)
当然k8s也可以使用自己私有的CA证书来签订需要的证书,具体查看相关资料,不在此进行整理了。
### 七、参考文献
1. [网络安全简介(CA、SSL、TLS)](https://blog.csdn.net/chenleiking/article/details/78448784)
2. [数字证书、CA、CA证书,傻傻分不清楚?这一篇看懂!](https://zhuanlan.zhihu.com/p/26859843)
3. [细说 CA 和证书](https://www.barretlee.com/blog/2016/04/24/detail-about-ca-and-certs/)
4. (https://www.cnblogs.com/f-ck-need-u/p/6091027.html)
5. (https://docs.lvrui.io/2018/11/01/k8s%E8%AF%81%E4%B9%A6%E7%9A%84KeyUsage%E9%97%AE%E9%A2%98/)
6. (https://www.cnblogs.com/f-ck-need-u/p/7048359.html#auto_id_4)
7. (https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-certs/#automatic-certificate-renewal)
8. (https://kubernetes.io/docs/setup/best-practices/certificates/)
本帖最后由 ypengfei 于 2021-5-10 15:46 编辑
intermediate-ca.md文件
中间pair证书的openssl模板 注意替换dir目录为自己的绝对地址# OpenSSL intermediate CA configuration file.
# Copy to `/root/ca/intermediate/openssl.cnf`.
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
# Directory and file locations.
dir = /Users/xyz/ca/intermediate
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
# The root key and root certificate.
private_key = $dir/private/intermediate.key.pem
certificate = $dir/certs/intermediate.cert.pem
# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/intermediate.crl.pem
crl_extensions = crl_ext
default_crl_days= 30
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_loose
[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName= optional
commonName = supplied
emailAddress = optional
[ 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`).
default_bits = 2048
distinguished_name= req_distinguished_name
string_mask = utf8only
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
# Extension to add when the -x509 option is used.
x509_extensions = v3_ca
[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
# Optionally, specify some defaults.
countryName_default = GB
stateOrProvinceName_default = England
localityName_default =
0.organizationName_default = Alice Ltd
organizationalUnitName_default=
emailAddress_default =
[ 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:0
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
###################
#
# 处理chrome问题
#
####################
subjectAltName = @alt_names
DNS.1=www.xyz.net
DNS.2=xyz.net
DNS.3=*.xyz.net
############
#
# 处理完成chrome问题
###########
[ 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
根证书openssl模板
注意替换dir目录为自己的绝对地址
# OpenSSL root CA configuration file.
# Copy to `/root/ca/openssl.cnf`.
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
# Directory and file locations.
dir = /Users/xyz/ca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
# The root key and root certificate.
private_key = $dir/private/ca.key.pem
certificate = $dir/certs/ca.cert.pem
# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/ca.crl.pem
crl_extensions = crl_ext
default_crl_days= 30
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_strict
[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName= optional
commonName = supplied
emailAddress = optional
[ 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`).
default_bits = 2048
distinguished_name= req_distinguished_name
string_mask = utf8only
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
# Extension to add when the -x509 option is used.
x509_extensions = v3_ca
[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
# Optionally, specify some defaults.
countryName_default = GB
stateOrProvinceName_default = England
localityName_default =
0.organizationName_default = Alice Ltd
organizationalUnitName_default=
emailAddress_default =
[ 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:0
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
页:
[1]