公钥基础设施PKI和数字证书
1. 简述
公钥基础设施(Public Key Infrastructure, PKI)是目前网络安全建设的基础和核心,是电子商务安全实施的基本保障。所有与数字证书相关的各种概念和技术,统称为PKI。
PKI 采用证书进行公钥管理,通过第三方的可信任机构(认证中心,即CA),把用户的公钥和用户的其他标识信息捆绑在一起,其中包括用户名和电子邮件地址等信息,以在Internet网上验证用户的身份。PKI把公钥密码和对称密码结合起来,在Internet网上实现密钥的自动管理,保证网上数据的安全传输。
数字证书是一个经证书授权中心数字签名的包含公开密钥拥有者信息和公开密钥的文件。最简单的证书包含一个公开密钥、名称以及证书授权中心的数字签名。一般情况下证书中还包括密钥的有效时间,发证机关(证书授权中心)的名称,该证书的序列号等信息,证书的格式遵循ITUT X.509国际标准。
X.509证书包含三个文件:key,csr,crt。
key是服务器上的私钥文件,用于对发送给客户端数据的加密,以及对从客户端接收到数据的解密。
csr是证书签名请求文件,用于提交给证书颁发机构(CA)对证书签名。
crt是由证书颁发机构(CA)签名后的证书,或者是开发者自签名的证书,包含证书持有人的信息,持有人的公钥,以及签署者的签名等信息。
备注:在密码学中,X.509是一个标准,规范了公开秘钥认证、证书吊销列表、授权凭证、凭证路径验证算法等。
2. 术语
cert:certificate,证书
key:秘钥
csr:certificate signing request,证书请求文件,证书签名申请
crl:certificate revoke list,证书吊销列表
CA:certificate authority,认证中心
Digital Certificate:数字证书
密钥:一般就是一个字符串或数字,在加密或者解密时传递给加密/解密算法。如在公钥密码体制中说到的公钥、私钥就是密钥,公钥是加密使用的密钥,私钥是解密使用的密钥。
3. 数字证书签发流程
CA的签发过程如下:
1)服务方S向第三方机构CA提交公钥、组织信息、个人信息(域名)等信息并申请认证(申请证书不需要提供私钥,确保私钥永远只能服务器掌握)。
2)CA 通过线上、线下等多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法,是否拥有域名的所有权等。
3)如信息审核通过,CA 会向申请者签发认证文件-证书。证书包含以下信息:申请者公钥、申请者的组织信息和个人信息、签发机构 CA 的信息、有效时间、证书序列号等信息的明文,同时包含一个签名。
签名的产生算法:首先,使用散列函数计算公开的明文信息的信息摘要,然后,采用 CA 的私钥对信息摘要进行加密,密文即签名。
4)客户端 C 向服务器 S 发出请求时,S 返回证书文件。
5)客户端 C 读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,然后,利用对应 CA 的公钥解密签名数据,对比证书的信息摘要,如果一致,则可以确认 证书的合法性,即公钥合法。
6)客户端然后验证证书相关的域名信息、有效时间等信息。
7)客户端会内置信任 CA 的证书信息(包含公钥),如果CA不被信任,则找不到对应 CA 的证书,证书也会被判定非法。
在这个过程注意几点:
1)申请证书不需要提供私钥,确保私钥永远只能服务器掌握。
2)证书的合法性仍然依赖于非对称加密算法,证书主要是增加了服务器信息以及签名。
3)内置 CA 对应的证书称为根证书,颁发者和使用者相同,自己为自己签名(用CA自己的私钥签名),即自签名证书(此证书中的公钥即为CA的公钥,可以使用这个公钥对证书的签名进行校验,无需另外一份证书)。
4)证书=公钥+申请者与颁发者信息+签名。
基础理论:
公共钥匙用来加密数据,私有钥匙用来计算签名。
公钥加密的消息只能用私钥解密,私钥签名的消息只能用公钥检验签名。
4. HTTPS证书验证
服务端认证的通信过程
1) 客户端发送请求到服务器端
2) 服务器端返回证书和公开密钥,公开密钥作为证书的一部分而存在
3) 客户端验证证书和公开密钥的有效性,如果有效,则生成共享密钥并使用公开密钥加密发送到服务器端
4) 服务器端使用私有密钥解密数据,并使用收到的共享密钥加密数据,发送到客户端
5) 客户端使用共享密钥解密数据
6) SSL加密建立………
客户端认证过程
客户端需要认证的过程跟服务器端需要认证的过程基本相同,并且少了最开始的两步。这种情况都是证书存储在客户端,并且应用场景比较少,一般金融才使用,比如支付宝、银行客户端都需要安装证书。
5. 证书签发
5.1 证书制作工具
可以使用工具openssl、keytool等工具生成自签名证书。
openssl:SSL 密码库工具,其提供了一个通用、健壮、功能完备的工具套件,用以支持SSL/TLS 协议的实现。
keytool:JDK里面内置的一个数字证书生产工具,只能生成自签名的数字证书。且不支持导出私钥。所有的数字证书是以一条一条(采用别名区别)的形式存入证书库的中,证书库中的每个证书包含该条证书的私钥,公钥和对应的数字证书的信息。
5.2 openssl生成证书
自签名证书分为自签名私有证书和自签名CA证书两种。自签名私有证书无法被吊销,自签名CA证书可以被吊销。能不能吊销证书的区别在于如果私钥不小心被恶意获取,如果证书不能被吊销那么黑客很有可能伪装成受信任的客户端与用户进行通信。如果你的规划需要创建多个客户端证书,那么使用自建 CA 签名证书的方法比较合适,只要给所有的客户端都安装了 CA 根证书,那么以该 CA 根证书签名过的客户端证书都是信任的,不需要重复的安装客户端证书。
注:Chrome已经不再支持证书中的commonName匹配,实际上,自2017年1月起就需要 subjectAltName 这个规则了。chrome58后 commonName 改成了SubjectAlternativeName 校验域名;所以要通过对已有证书添加 v3.ext 重新生成证书,在 v3.ext 里加入 subjectAltName。
注:由于是自建 CA 证书,在使用这个临时证书的时候,会在客户端浏览器报一个错误,签名证书授权未知或不可(signing certificate authority is unknown and not trusted.),但只要配置正确,继续操作并不会影响正常通信。
生成自签名私有证书
1. 生成私钥key
openssl genrsa -out [name].key 2048
如果需要备份或者转移私钥,需要先对私钥进行加密(需要输入密码,要牢记私钥密码):
openssl rsa -in /path/to/keyfile -des3 -out /path/to/encrypted.key
2. 通过key生成csr证书申请文件(文件中只包含了公钥和一些认证实体信息:用来做证书申请的)
生成 CSR 的过程中,会提示输入一些信息,包括:序列号、公钥、用户名称、签发者、CA签名和其他一些附属信息等。证书验证过程就是依赖于这信息和公钥对应的私钥进行。其中一个提示是 Common Name (e.g. YOUR name),这个非常重要,这一项应填入 FQDN(Fully Qualified Domain Name)完全合格域名/全称域名,如果您使用SSL加密保护网络服务器和客户端之间的数据流,举例被保护的网站是 https://test.example.cn,那么此处 Common Name 应输入 test.example.cn。
openssl req -new -key [name].key -out [name].csr
检查和打印csr
openssl req -text -noout -verify -in [name].csr
3. 通过key和csr生成crt证书
openssl x509 -req -days 365 -in [name].csr -signkey [name].key -out [name].crt
查看crt内容
openssl x509 -in [name].crt -text -noout
上述1-3可以通过如下一个命令一步实现:
openssl req -new -x509 -newkey rsa:2048 -keyout server.key -out server.crt
4. 通过已有证书添加v3.ext重新生成证书
v3.ext文件
authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = localhost
最后的 DNS.1 = localhost 也可以直接写成 DNS = localhost。
openssl x509 -req -extfile v3.ext -days 3650 -in server.csr -signkey server.key -out ssl.crt
附1:不需要新建v3.ext文件的方法,直接把subjectAltName添加到证书里:
openssl x509 -req -extfile <(printf "subjectAltName=DNS:localhost") -days 365 -in server.csr -signkey server.key -out ssl.crt
附2:一步到位,通过.cnf配置文件生成证书
上面的步骤是先生成证书,再用添加v3.ext文件的方法添加subjectAltName,下面直接用配置文件生成证书:
1) ssl.cnf
[req] prompt = no default_bits = 4096 default_md = sha256 distinguished_name = dn x509_extensions = v3_req [dn] C=CN ST=Shanghai L=Shanghai O=TEST OU=Testing Domain CN=localhost emailAddress=admin@localhost [v3_req] keyUsage=keyEncipherment, dataEncipherment extendedKeyUsage=serverAuth subjectAltName=@alt_names [alt_names] DNS.1=localhost
2) 通过ssl.cnf生成key和crt
openssl req -new -newkey rsa:2048 -sha1 -days 180 -nodes -x509 -keyout myssl.key -out myssl.crt -config d:\ssl\ssl.cnf
3)通过cnf文件生成csr
openssl req -new -config d:\ssl\ssl.cnf -key d:\ssl\myssl.key -out myssl.csr
4)查看生成的证书的命令
openssl x509 -in d:\ssl\myssl.crt -text -noout
生成自签名CA证书
创建自签 CA 证书,主要分为两个部分: 创建CA 根证书及签发客户端证书。
创建CA根证书
使用OpenSSL可以创建自己的CA,给需要验证的用户或服务器颁发证书,这就需要创建一个CA根证书。默认情况ubuntu和CentOS上都已安装好openssl。CentOS 6.x 上有关ssl证书的目录结构。
/etc/pki/CA/ newcerts 存放CA签署(颁发)过的数字证书(证书备份目录) private 用于存放CA的私钥 crl 吊销的证书 /etc/pki/tls/ cert.pem 软链接到certs/ca-bundle.crt certs/ 该服务器上的证书存放目录,可以放自己的证书和内置证书 ca-bundle.crt 内置信任的证书 private 证书密钥存放目录 openssl.cnf openssl的CA主配置文件
在创建 CA 根证书之前,需要做好如下准备工作:修改好 CA 的配置文件、序列号、索引等等。
touch index.txt serial echo 01 >> serial
openssl的配置文件为openssl.cnf,一般存储在/etc/pki/tls/目录下。一定要注意配置文件中[policy_match ]标签下设定的匹配规则。有可能因为证书使用的工具不一样,导致即使设置了csr中看起来有相同的countryName,stateOrProvinceName等,但在最终生成证书时依然报错。一般情况下,配置文件不需要改动。
1. 生成根证书密钥 # 生成CA根证书密钥 cd /etc/pki/CA/ openssl genrsa -out ./private/ca.key 2048 2. 生成根证书请求 # 新建根证书请求 openssl req -new -in /path/to/ca.key -out ca.csr 3. 生成根证书 #自签名,生成CA证书 openssl x509 -req -in /path/to/ca.csr -signkey /path/to/ca.key -extensions v3_ca -out /path/to/ca.crt
签发证书
我们可以用CA根证书签发证书,也可以创建中间CA,使用中间CA签发证书。创建中间CA的好处是即使中间CA的私钥泄露,造成的影响也是可控的,我们只需要使用root CA撤销对应中间CA的证书即可。此外root CA的私钥可以脱机妥善保存,只需要在撤销和更新中间CA证书时才会使用。基于根证书创建中间CA与创建根证书过程类似。我们新建一个目录用于保存中间证书信息。
#准备环境 mkdir /etc/pki/CA/intermediate cd /etc/pki/CA/intermediate mkdir certs crl newcerts private chmod 700 private touch index.txt echo 1000 > serial #生成密钥 cd /etc/pki/CA openssl genrsa -aes256 -out intermediate/private/ca.key 2048 #新建请求 openssl req -config intermediate_CA.cnf -sha256 -new -key intermediate/private/ca.key -out intermediate/certs/ca.csr #签发中间CA证书 openssl ca -config root_CA.cnf -extensions v3_ca -notext -md sha256 -in intermediate/certs/ca.csr -out intermediate/certs/ca.cert
利用根证书或者中间证书签发客户端证书的步骤如下:
1. 新建证书密钥 #新建密钥 openssl genrsa -out /path/to/server.key 2048 2. 新建证书请求 #新建证书请求 openssl req -new -in /path/to/server.key -out /path/to/server.csr 3. CA签发证书 #证书CA签名 openssl x509 -req -in /path/to/server.csr -CA /path/to/ca.crt -CAkey /path/to/ca.key -CAcreateserial -out /path/to/server.crt 4. CA证书的有效性验证 #验证证书 openssl verify -CAfile /path/to/ca.crt /path/to/server.crt #如果结果显示OK,说明我们颁发的证书是有效的。
吊销证书
当证书已经不再使用或者密钥泄露时,我们需要吊销证书来保证服务器的安全。
#获取要吊销的证书的serial openssl x509 -in /path/to/x.crt -noout -serial -subject #对比serial与subject 信息是否与index.txt中的信息一致 #如果一致,则可以吊销证书 openssl ca -revoke /etc/pki/CA/newcerts/SERIAL.pem #如果是第一次吊销证书,需要指定吊销的证书编号 echo 01 >/etc/pki/CA/crlnumber #更新吊销证书列表 openssl ca -gencrl -out /etc/pki/CA/crl.pem #完成后,可查看吊销的证书列表 openssl crl -in /etc/pki/CA/crl.pem -noout -text
6. HTTPS工具
SSL Server Test https://www.ssllabs.com/ssltest/
对服务器的 HTTPS 配置进行测试,指出潜在的问题,并对安全级别打分。
SSL Client Test https://www.ssllabs.com/ssltest/viewMyClient.html
测试客户端的配置情况
SSL Pulse https://www.ssllabs.com/ssl-pulse/
对全球顶尖 HTTPS 网站进行长期跟踪,统计和 HTTPS 有关的一些数据
SSL and TLS Deployment Best Practices https://www.ssllabs.com/projects/documentation/
最佳部署文档
Mozilla最佳部署文档 https://wiki.mozilla.org/Security/Server_Side_TLS
重点介绍密码套件配置、HTTPS 潜在的攻击、最佳部署等
Mozilla SSL Configuration Generator https://mozilla.github.io/server-side-tls/ssl-config-generator/
用于自动化为服务器配置 HTTPS 协议
Summarizing Known Attacks on TLS https://tools.ietf.org/html/rfc7457
详细描述 TLS/SSL 协议,历史上出现的漏洞
Recommendations for Secure Use of TLS https://tools.ietf.org/html/rfc7525
描述如何更好地部署 HTTPS 网站
参考:
1. 数字签名是什么? 阮一峰
2. PKI 体系概述
3. 自签名数字证书的使用 https://www.jianshu.com/p/44a3efae1d84
4. 自签名证书 https://www.jianshu.com/p/81dbcde4fd7c
6. 数字证书原理