SSL证书基础与申请流程
一、基本概念
- SSL(Secure Socket Layer) 安全套接层,是1994年由Netscape公司设计的一套协议,并于1995年发布了SSL3.0版本。
- TLS(Transport Layer Security) 传输层安全,是IETF在SSL3.0基础上设计的协议,实际上相当于SSL的后续版本。TLS与SSL 3.0之间存在显著差别,主要是它们所支持的加密算法不同,所以TLS与SSL 3.0不能互操作。
- HTTPS(Hypertext Transfer Protocol Secure),由于其安全层使用的是TLS/SSL,因此HTTPS也可以称为HTTP over TLS或HTTP over SSL。它使用默认端口443,而不是像HTTP那样使用端口80来和TCP/IP进行通信。
关系: HTTPS和HTTP协议位于应用层;SSL与TLS协议位于传输层与应用层之间对网络连接进行加密;TCP协议位于传输层,IP协议位于网络层。如下图所示:
- HTTPS证书 又叫“SSL证书”、“SSL安全证书”、“SSL数字证书”。SSL证书需要向国际公认的证书认证机构(简称CA,Certificate Authority) 申请。
二、加密算法和证书的基本概念
两种常用的加密方式,分别是对称加密和非对称加密:
- 对称加密:加密使用的秘钥和解密使用的秘钥是相同的,也就是说加密和解密都使用同一个秘钥。加密算法是公开的;秘钥是绝对保密的。
- 非对称加密:加密使用的秘钥和解密使用的秘钥是不相同的,HTTPS在证书验证的时候,采用的RSA密码体制就是一种非对称加密。
RSA是一种公钥秘钥密码体制,被广泛使用,这个密码体制分为三部分,1公钥、2私钥、3加密算法。
- 公钥和加密算法是公布的;私钥是自己保密的。
- 通过公钥加密的密文只有对应的私钥才能解密;通过私钥加密的密文也只有对应的公钥才能解密。
- 公钥给别人加密使用;私钥给自己解密使用。
CA机构除了给别人颁发证书以外,它也有自己的证书,称之为 “根证书”,根证书在验证证书的过程中起着核心的作用。 根证书的公钥和私钥分别叫 “根公钥” 和 “根私钥”。 根公钥和加密算法是对外公布的,根私钥是机构自己绝对保密的。
证书,有点像个人身份证,是由权威的CA机构颁发的,证书的主要内容有:
- 公钥(Public Key):公钥是一串很长的2048 Bits的字符串
- ISSUER(证书的发布机构)、Subject(证书持有者)、证书有效期等
- 指纹和指纹算法
指纹是一个证书的签名,是通过指纹算法计算出来的一个hash值。
验证证书的原理: CA机构颁发证书之前,会把所颁发证书的全部内容用自己的根私钥通过指纹算法计算得到一个hash值,即指纹,这个hash值只有对应的根公钥才能解密。 验证证书时,根公钥 + 指纹算法 ==> hash值,如果该hash值跟证书上的指纹相同,就代表证书没有被篡改过。
三、SSL单向验证的握手流程
-
客户端发送hello给服务器 (发送内容包括:客户端支持的SSL/TLS协议版本列表;客户端支持的对称加密算法列表;客户端生成的随机数A;等等)
-
服务器返回hello,返回它的CA数字证书(crt public) (返回内容还包括:双方都支持的SSL/TLS协议版本;双方都支持的对称加密算法;服务器端生成的随机数B;等等)
-
客户端验证CA数字证书 首先从证书的内容中获取证书的颁发机构,世界上就几个权威的CA机构,这几个机构的信息都是预先嵌入到浏览器中的;如果收到的数字证书其颁发机构没有在我们浏览器系统中,会警告提示无法确认证书真假。当从浏览器中找到CA机构,根公钥 + 指纹算法 ==> hash ,如果与指纹相等,就代表证书没有被篡改过。在证书完好的基础上,再检查证书上的使用者的URL(比如facebook.com)和我们请求的URL是否相等,如果相等,那么就可以证明当前浏览器连接的网址也是正确的,而不是一些钓鱼网站之类的。
-
客户端将一个对称加密算法的秘钥发给服务器 客户端生成一个随机数C(称为pre-master-key)用作生成对称加密算法的key秘钥,通过证书公钥加密成密文,将密文发送给服务器。 因为此密文是用公钥加密的,该密文只有私钥持有者才能解密。
-
客户端和服务器端计算获得对称加密秘钥 此时客户端和服务器端都拿到了随机数A、随机数B、随机数C,双发通过这3个随机数,各自使用相同的秘钥交换算法(DH算法)计算出同一个master secret,紧接着根据这个master secret推导出相同的hash secret和session secret。 在客户端和服务端的master secret是依据三个随机数推导出来的,它是不会在网络上传输的,只有双方知道,不会有第三者知道。
-
握手结束,建立对称加密的连接。 延伸知识:对称加密传输时,发送方用hash secret对HTTP报文做一次运算生成一个MAC,附在HTTP报文的后面,然后用session-secret加密所有数据(HTTP+MAC),然后发送。接收方则先用session-secret解密数据,得到HTTP+MAC,再用相同的算法计算出自己的MAC,如果两个MAC相等,证明数据没有被篡改。(MAC,即Message Authentication Code,称为报文摘要,能够查知报文是否遭到篡改,从而保护报文完整性)
另:SSL双向验证和单向验证的不同之处
SSL单向验证过程中,客户端会验证自己访问的服务器端,服务器端对客户端不做验证。 双向验证是,服务器端需要验证客户端,则需要开启服务器端验证。
- 第2步中服务器端第一次回应客户端时,会要求客户端提供其证书。
- 第4步中当客户端验证完服务器端证书后,回应的内容中会增加两个信息:客户端证书和客户端证书验证消息(CertificateVerify message)。 客户端证书验证消息:客户端将之前所有收到的和发送的消息组合起来,并用hash算法得到一个hash值,然后用客户端密钥库的私钥对这个hash进行签名,这个签名就是CertificateVerify message。
- 第5步前增加1步:服务器端收到客户端证书后,会做如下处理:首先确认客户端发送的证书有效合法;再用客户端证书中的公钥验证收到信息中的签名,以确定这个证书是客户端发出的。
四、证书申请操作
(一)基本概念
CSR(Certificate Signing Request),它是向CA机构申请数字身份证书时使用的请求文件。
在生成请求文件前,我们需要准备一对密钥,私钥信息自己保存,请求中会附上公钥信息以及国家,城市,域名,Email等信息,CSR中还会附上签名信息。
当提交CSR文件后,等待CA机构给我们签名,签好名后会收到crt文件
,即证书。
SSL证书编码格式有两种:
- PEM(Privacy Enhanced Mail),通常用于数字证书认证机构(Certificate Authorities,CA),扩展名为
.pem
、.crt
、.cer
、.key
。内容为Base64编码的ASCII码文件,有类似-----BEGIN CERTIFICATE-----
和-----END CERTIFICATE-----
的头尾标记。Apache和nginx等类似的服务器使用PEM格式证书。 - DER(Distinguished Encoding Rules),使用二进制,而不是Base64编码的ASCII。扩展名为
.der
,但也常用.cer
。所有类型的认证证书和私钥都可以存储为DER格式。Java是其典型使用平台。
(二)具体操作
- 安装openssl工具
- 新建一个秘钥 生成一个2048bit的RSA秘钥,用des3算法加密(需输入密码,每次用均需输入密码)。
$ openssl genrsa -des3 -out zzz-private-key.pem 2048
注意: 位数越高,越安全,但压解越耗时。非对称秘钥不对大块数据进行加密,仅握手,可用高位数;对称秘钥传输数据用,慎重大位数的秘钥。 注意: 申请证书时,该秘钥为服务器端的私钥,要自行严密保管!同稍后申请下来的证书一起安装在服务器端。
- 新建证书签名请求(CSR文件)
$ openssl req -new -key zzz-private-key.pem -out zzz-csr.pem
需要输入证书相关的信息:
名称 | 描述 | 示例 |
---|---|---|
国家名称 | 代表国家的两个字母 ISO 缩写 | US美国;CN中国 |
州或省 | 组织所在州或省的名称。此名称不可使用缩写 | 华盛顿州 |
所在地名称 | 组织所在城市的名称 | Seattle |
组织名称 | 组织的法定全称。请勿缩写组织名称 | 示例 Corp |
组织部门 | 可选,用于提供额外的组织信息 | 市场营销 |
Common Name | 申请证书的域名。如果两者不能精确匹配,那么您会收到一条证书名称检测警告 | yourdomain.com |
服务器管理员的电子邮件地址 | someone@yourdomain.com |
-
向CA提交CSR文件申请(详见下文使用acme申请)
-
域名所有权验证(DCV) 手动验证一般有三种方式,任选:
- DNS 记录验证:域名后台添加记录。注意巨坑:namecheap.com的record中,Host会隐性添加域名后缀。手动填写时,千万不要填域名后缀。
- File验证:将CA提供的验证文件上传到服务器,提交下载路径。
- 邮箱验证:(需要域名下的邮箱地址,略)
-
等待CA签名,下发证书 下载证书。解压有2个文件,一个为
xxx.crt
、另一个为xxx.ca-bundle
。 将两个文件的内容粘贴到一个新的.crt
文件(如server.crt
)里,注意ca-bundle
文件的内容在后。 -
将证书
server.crt
和私钥zzz-private-key.pem
安装到服务器。
五、局域网使用自签发证书
(一)CA
-
创建CA秘钥:
$ openssl genrsa -out ca-key.pem 2048 # -aes256 指定算法(可选)
-
书写根CA的配置文件
ca.cnf
:
[ req ]
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
prompt = no
[ req_distinguished_name ]
countryName = CN
stateOrProvinceName = Beijing
localityName = Beijing
organizationName = Super Powerful Root CA
organizationalUnitName = I.T. Department
commonName = Super Powerful Root CA
emailAddress = admin@x.com
[ v3_ca ]
basicConstraints = CA:true
- 创建CA证书:
$ openssl req -new -x509 -days 365 -key ca-key.pem -config ca.cnf -extensions v3_ca -out ca.pem # -sha256 指定算法(可选)
(二)Server
-
创建server端秘钥:
$ openssl genrsa -out server-key.pem 2048
-
创建 certificate signing request (CSR) 文件:
$ openssl req -new -key server-key.pem -out server.csr
注意: “Common Name” 一定要是服务器的IP。因为局域网内用,所以IP。
- 创建 extensions config
server.cnf
文件:
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = CN
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Beijing
localityName = Locality Name (eg, city)
localityName_default = Beijing
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = Super Powerful Root CA
commonName = Common Name
commonName_default = 192.168.0.1
commonName_max = 64
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
IP.1 = 192.168.0.1
IP.2 = 127.0.0.1
IP.3 = 192.168.0.5
DNS.1 = 192.168.0.1
注意: “Common Name” 一定要是服务器的IP。因为局域网内用,所以IP。 “IP” 填写所有需要访问这个server的IP,要包括自己。 “DNS” 填写所有需要访问这个server的DNS。
-
用CA签署创建server证书:
$ openssl x509 -req -days 365 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile server.cnf -extensions v3_req
-
验证一下:
$ openssl verify -CAfile ca.pem server-cert.pem
$ openssl verify -trusted ca.pem server-cert.pem
-
部署:
- 单向验证:将
server-cert.pem
和server-key.pem
设置于服务器;将ca.pem
在客户端设为可信任的CA根证书(例如windows系统用mmc.exe)。 - 双向验证:此外还需创建客户端的证书。
(三)Client
-
创建client端秘钥和CSR文件:
$ openssl genrsa -out client-key.pem 2048
$ openssl req -new -key client-key.pem -out client.csr
注意: “Common Name” 一定要是该客户端的IP。 -
创建 extensions config
client.cnf
文件:$ echo extendedKeyUsage = clientAuth > client.cnf
-
用CA签署创建client证书:
$ openssl x509 -req -days 365 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -extfile client.cnf -extensions v3_req
-
验证一下:
$ openssl verify -CAfile ca.pem client-cert.pem
$ openssl verify -trusted ca.pem -trusted server-cert.pem client-cert.pem
六、使用acme脚本申请Lets’Encrypt证书
(一)下载
- 官方下载
$ curl https://get.acme.sh | sh -s email=my@example.com
# 或者
$ wget -O - https://get.acme.sh | sh -s email=my@example.com
# 或者
$ git clone https://github.com/acmesh-official/acme.sh.git
$ cd ./acme.sh
$ ./acme.sh --install -m my@example.com
- 下载已封装好的
# 例如Openwrt系统:
$ opkg install acme acme-dnsapi
(二)域名准备(namecheap.com为例)
- 准备一个域名,并将其IP设为当前acme运行主机的公网IP。
- 开启Namecheap API,记录Api Key;公网IP加入白名单:官方指南
(三)申请
$ export NAMECHEAP_USERNAME="..."
$ export NAMECHEAP_API_KEY="..."
$ export NAMECHEAP_SOURCEIP="..." # 公网IP
# 注意:申请时上述信息将存储在 `~/.acme.sh/account.conf` ;后续有变化记得更新。
$ cd /usr/lib/acme/client # 该路径为openwrt系统中的路径
# $ ./acme.sh --upgrade # 从github下载,可能被墙
$ ./acme.sh --register-account -m xxx@xxx.com
$ ./acme.sh --set-default-ca --server letsencrypt
$ ./acme.sh --issue --dns dns_namecheap -d example.com -d *.example.com --days 90 --server letsencrypt
$ ./acme.sh --install-cronjob # 添加计划任务,自动续签临期证书
成功后,结果存储在:~/.acme.sh/exmple.com
- Key
exmple.com.key
(使用这个) - Cert
exmple.com.cer
- Intermediate CA Cert
ca.cer
- Full Chain Certs (Cert + Intermediate CA Cert)
fullchain.cer
(使用这个)
(三)续签
- 更新
~/.acme.sh/account.conf
- 更新 namecheap.com 中的 Namecheap API 的IP白名单
./acme.sh --renew -d example.com -d *.example.com --days 90 --force --server letsencrypt
附录
HTTPS一般使用的加密与HASH算法如下:
- 非对称加密算法:RSA,DSA/DSS
- 对称加密算法:AES,RC4,3DES
- HASH算法:MD5,SHA1,SHA256
最后修改于 2024-02-24