证书生命周期
证书生命流程 | 描述 |
---|---|
证书申请 | 生成密钥对(使用genrsa、gendsa或req),填写用户信息,并将公钥和用户信息一起交给CA验证 |
证书颁发 | 首先验证证书请求上的签名;查阅证书请求用户信息(匹配、支持或可选);签发(ca或x509指令) |
证书验证 | 验证CA数字签名、证书的有效期、证书是否被吊销(verify或者ocsp) |
证书吊销 | 从CA的证书数据库中删除被吊销的证书;生成和公布证书吊销列表CRL(ca的revoke选项) |
证书过期 | 证书过期后,CA需要更新证书库中已经过期的证书的状态(ca指令对应updatedb更新数据库中证书的标记状态) |
证书封装类型
- X.509证书:X.509证书包含的内容主要是用户信息、整数序列号、签发者、有效期、公钥、其他信息及CA的数字签名。如果要在Windows平台查看和管理X.509证书,需要将X.509证书文件后缀名改成cer、der或者crt。OpenSSL本身的ca指令颁发的证书是X.5009标准格式。
- PKCS#12证书:PCKS#12格式证书可以将证书和其相应的私钥封装在一起。PKCS#12采用了PKCS#8的私钥封装格式对私钥进行了基于口令的加密。
- PKCS#7证书:所谓证书链,就是一个用户证书和一系列与其证书相关的CA证书的有序集合。PKCS#7证书可以包含多个证书和CRL。
证书类型 | 证书内容 | 适用范围 | OpenSSL支持 | Windows后缀 |
---|---|---|---|---|
X.509 | 用户信息、公钥、序列号、CA签名和其他证书信息 | 用户和被验证用户处于同一个CA域内的验证模型,用户不需要考虑私钥存储的问题 | 生成、适用和其他管理都支持 | der、cer、crt |
PKCS#12证书 | X.509证书和其相应私钥 | 需要同时使用X.509证书和其私钥的应用,比如导入证书到IE或Netscape浏览器 | 生成、使用和其他管理都基本支持 | pfx、p12 |
PKCS#7证书 | 多个X.509证书和CRL | 需要同时使用多个用户证书和CRL的验证过程或其他应用 | 生成和管理支持 | p7 |
证书使用
证书应用模型
证书链
用户A和用户B的证书是不同的CA签发的,CA1和CA2,但具有相同的根证书CA。证书链的认证流程如下:
- A将自己的证书、CA1的证书和根CA证书发送给B;
- B接收到A发送过来的整个证书链后,B从CA1提取公钥,验证用户证书A的合法性和有效性;
- B从根CA提取公钥,验证CA1证书的合法性和有效性;
- B利用根CA的公钥验证根CA证书的合法性和有效新(因为它是一个自签发根证书);
- B查找自己的信任证书库(通常是一些根CA的列表),看看上述通过验证的根CA是否在信任列表中,如果在,那么验证通过,否则验证不通过。
用户身份确认
证书验证通过后,还需要确认用户身份。一般的做法是,提取证书中的公钥并使用公钥加密一个随机数,然后发送给用户,要求用户解密并返回该数据。
OpenSSL支持的CA指令
指令 | 描述 |
---|---|
req | 根据给定的密钥对或者新生成的密钥对按OpenSSL配置文件指定的要求生成符合pkcs#10的证书请求。此外,还支持生成自签名根证书的功能 |
ca | 该指令模拟了一个ca服务器的功能和操作,包括签发证书、吊销证书、产生CRL等证书相关管理操作 |
x509 | 该指令是一个显示X.509证书内容和签发证书的工具,具备了使用特定私钥和证书进行证书签发的功能 |
verify | 验证证书程序 |
ocsp | 支持在线证书验证协议的指令,可以处理OCSP协议的一些标准格式信息操作,生成OCSP请求发送给其他OCSP服务器,甚至可以自己模拟一个OCSP服务程序 |
crl | 处理和显示CRL文件信息 |
crl2pkcs7 | 将CRL和其他证书封装成PKCS#7证书 |
pkcs12 | 将X.509证书和其相应私钥封装成PKCS#12证书,或者将PKCS#12证书转换位X.509证书 |
pkcs7 | 处理PKCS#7的证书,并可以将之转换位普通格式证书 |
申请证书
req指令
req指令选项:
选项 | 描述 |
---|---|
in | 指定了保存证书请求的文件名,默认是标准输入 |
out | 指定了输出文件名,默认是标准输出 |
key | 指定了输入私钥的文件,该文件内的私钥编码格式由keyform指定 |
keyout | 指定了新生成的私钥的输入保存文件,默认为OpenSSL配置文件中req字段default_keyfile选项的参数中获取输出私钥文件名 |
inform | 指定了选项in指定的输入证书请求文件的编码格式 |
outform | 指定了输出选项out输出的证书请求或自签发证书的编码格式 |
keyform | 指定了输入选项key指定的密钥编码格式 |
passin | 指定了读取key选项指定的私钥所需要的解密口令 |
passout | 指定了使用keyout选项输出私钥时使用的加密口令 |
pubkey | 指定输出PEM编码公钥到out指定文件中 |
new | 告诉指令生成新的证书请求操作,此时in选项指定的输入文件会被忽略 |
newkey | 告诉指令生成一个新的密钥对,该选项只有在没有使用key选项时才有效,newkey选项包含rsa:numbite和dsa:file两种形式 |
nodes | 告诉指令不对新生成的私钥进行加密保存,此时passout选项会被忽略 |
x509 | 告诉指令生成一个自签名证书而不是输出一个证书请求 |
* | 支持的算法类型 |
subj | 从指令行指定证书的主体名称,没有改选项,req指令默认从主配置文件获取国家代号、省份、单位名称等 |
days | 设定了生成的自签名根证书的有效期,单位是天,只有在使用x509时才有效 |
set_serial | 指定了生成的自签名根证书的序列号,默认根序列号时0,只有在使用x509时才有效 |
config | 指定req指定在生成证书请求的使用使用的OpenSSL配置文件,默认为openssl.cnf |
extensions | 指定了生成自签名根证书的时候使用的扩展字段,比如openssl.cnf文件中的v3_ca字段 |
reqexts | 指定了生成证书请求时使用的扩展字段,比如openssl.cnf文件中的v3_req字段 |
newhdr | 使用该选后将会在输出的PEM编码的证书请求开始和结束行增加“NEW”标记字符串 |
utf8 | 使用该选项后,输出信息将采用UTF8编码,默认时ASCII编码 |
noout | 使用该选项后,指令将不会输出编码的证书请求或自签发证书到out选项指定的文件中 |
subject | 告诉指令输出主题名信息,即使text选项已经输出,该选项还会再次输出 |
reqopt | 指定text输出的内容 |
nameopt | 输出字符编码选项,指定了如何显示主体名称和签发者名称,主要用于演示名称后不同编码的内容 |
verify | 对证书请求的数字签名进行验证操作,并给出失败或者成功的提示信息 |
rand | 指定了生成密钥对或者其他一些操作需要的随机种子文件 |
batch | 使用该选项将不在提示用户输入生成证书请求需要的用户信息,而是直接从主 |
verbose | 输出执行各个操作的详细信息 |
自签名证书:指用一对密钥对的私钥对自己相应的公钥生成的证书请求进行签名而颁发证书,这样证书申请人和签发人都是同一个,所以称为自签名根证书。如果证书不用于根CA,那么一般来说只有测试的意义。
生成证书密钥
使用RSA密钥生成证书请求
#方式1:直接使用req指令生成RSA密钥用于证书请求(缺点是私钥加密只能使用DES3-CBC,输出编码只能是PEM)
OpenSSL> req -new -newkey rsa:1024 -keyout RSAPrivateKey.pem -out RSAReq.pem -passout pass:12345678
#方式2:使用genrsa和req生成证书请求
#第一步
OpenSSL> genrsa -aes256 -passout pass:12345678 -out RSAPrivateKey.pem 1024
#第二步:
OpenSSL> req -new -key RSAPrivateKey.pem -passin pass:12345678 -out RSAReq.pem
使用DSA密钥生成证书请求
#方式1:使用dsaparam和req指令生成DSA密钥用于证书请求(缺点是私钥加密只能使用DES3-CBC,输出编码只能是PEM)
#第一步
OpenSSL> dsaparam -out DSAParam.pem 1024
#第二步
OpenSSL> req -new -newkey dsa:DSAParam.pem -keyout DSAPrivateKey.pem -out DSAReq.pem -passout pass:12345678
#方式2:使用dsaparam、genrsa和req指令生成证书请求
#第一步
OpenSSL> dsaparam -out DSAParam.pem 1024
#第二步
OpenSSL> gendsa -out DSAPrivateKey.pem -aes256 -passout pass:12345678 DSAParam.pem
#第三步
OpenSSL> gendsa -out DSAPrivateKey.pem -aes256 -passout pass:12345678 DSAParam.pem
双证书
一个整数用于密钥交换,一个证书用于数字签名。用于密钥交换的证书其密钥对一般由CA或者RA代替用户产生;而用于数字签名的证书的密钥则由用户自己产生。
在证书请求中增加扩展项
在某些特殊情况下,需要在证书中扩展一些标记以便实现一些特定的功能,比如,你可能需要在给你公司员工发放的证书中增加一项权限的功能,这可能给会给管理带来很大的方便,尤其对于有多个服务器的分布式系统中,这种证书尤其有用。
首先保证 openssl.cnf 文件中 oid_section = new_oids
没有被注释,然后在 [new_oids]
字段中定义一个 OID,其简短名和长名都是 UserRights, OID 为 2.5.4.555:
[ new_oids ]
......
......
UserRights=2.5.4.555
......
......
然后在 [ req_distinguished_name ]
字段中添加自定义配置:
[ req_distinguished_name ]
UserRights = User Rights
UserRights_default = US
UserRights_min = 2
UserRights_max = 2
申请用户证书请求
证书按照其在证书链中的位置分类,一般可以分为两种:终端用户证书和 CA 证书。所谓 CA 证书,是指该证书可以用于签发别的用户证书,也就是说,它可以有下级的证书。终端用户证书则用于具体应用程序或协议中,它不能用来签发别的证书,在证书链中,它处于最末端。
首先保证 openssl.cnf 配置文件中 v3_req 生效:req_extensions = v3_req
没有被注释,然后修改 [ v3_req ]
配置项:
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
申请 CA 证书请求
如果你要申请一个临时的 CA 证书,你可能并不需要签发这个证书,只需要生成一个申请一个 CA 证书的请求,然后发给上级 CA,然后等待它的签发就可以了。怎样生成一个 CA 证书请求,而不是用户证书请求呢?首先保证 openssl.cnf 配置文件中 v3_req 生效:req_extensions = v3_req
没有被注释,然后修改 [ v3_req ]
配置项:
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:TRUE
建立CA
有了 OpenSSl,建立一个 CA 服务器非常简单。这里我们需要直到 CA 服务器只是一个技术上的基础程序,而 CA 则是一个集技术个管理于一体的庞大机构。
CA 服务器的基本功能
- 接受证书请求:在线实时提交、在线非实时提交和本地提交
- 审核证书请求
- 签发证书
- 发布证书,发布对象有两种:一种是申请证书的用户本人,必须让他能够及时获得自己的证书;一种是其他用户,可以向他们提供获得所有用户证书的途径。一般通过 WEB 方式或 LDAP 方式发布。
- 吊销证书
- 生成和发布 CRL
- 证书库管理
CA 服务器的基本要素
- 一个具备基本功(CA 服务器基本功能)能的 CA 应用程序,可以使用 OpenSSL 的 ca 指令作为 CA 应用程序,当然也可以使用微软的CA服务器或 OpenCA。
- 一个 CA 证书和一个其相应的私钥,可能是自签名的根证书,也可能是向另一个 CA 申请的证书。如果我们搭建的 CA 服务自称体系,并不需要上级 CA 支持,那么使用 OpenSSL 的 req 指令生成一个自签名根证书作为 CA 服务器的证书即可;如果需要上级 CA 支持,只需要生成一个 CA 证书请求发送给上级 CA,然后等待上级 CA 签发你的证书。
- 证书数据库,用于存储证书(有时候还包括私钥)。可以使用 Mysql、Oracle、SQLServer 数据库,或自定义的文本数据库。
OpenSSL 模拟 CA 服务器结构
demoCA 根目录
|____newcerts 目录(存放新证书,如 01.pem)
|____cers 目录(存放签发者证书)
|____private 目录(存放私钥文件)
| |____cakey.pem(CA 私钥)
|____crl 目录(存放 CA 的 CRL)
|____cacert.pem 文件(CA 证书)