openssl ca(签署和自建CA)
用于签署证书请求、生成吊销列表CRL以及维护已颁发证书列表和这些证书状态的数据库。因为一般人无需管理crl,所以本文只介绍openssl ca关于证书管理方面的功能。
证书请求文件使用CA的私钥签署之后就是证书,签署之后将证书发给申请者就是颁发证书。在签署时,为了保证证书的完整性和一致性,还应该对签署的证书生成数字摘要,即使用单向加密算法。
由于openssl ca命令对配置文件(默认为/etc/pki/tls/openssl.cnf)的依赖性非常强,所以建议结合我的另一篇文章配置文件openssl.cnf来阅读,如果不明白配置文件,下面的内容很可能不知所云。
在配置文件中指定了签署证书时所需文件的结构,默认openssl.cnf中的结构要求如下:
[ CA_default ] dir = /etc/pki/CA # 定义路径变量 certs = $dir/certs # 已颁发证书的保存目录 database = $dir/index.txt # 数据库索引文件 new_certs_dir = $dir/newcerts # 新签署的证书保存目录 certificate = $dir/cacert.pem # CA证书路径名 serial = $dir/serial # 当前证书序列号 private_key = $dir/private/cakey.pem # CA的私钥路径名
其中目录/etc/pki/CA/{certs,newcerts,private}在安装openssl后就默认存在,所以无需独立创建,但证书的database文件index.txt和序列文件serial必须创建好,且序列号文件中得先给定一个序号,如"01"。
[root@docker-03 ~]# touch /etc/pki/CA/index.txt [root@docker-03 ~]# echo "01" > /etc/pki/CA/serial
另外,要签署证书请求,需要CA自己的私钥文件以及CA自己的证书,先创建好CA的私钥,存放位置为配置文件中private_key所指定的值,默认为/etc/pki/CA/private/cakey.pem。
[root@docker-03 ~]# openssl genrsa -out /etc/pki/CA/private/cakey.pem Generating RSA private key, 2048 bit long modulus ......+++ ...........................................+++ e is 65537 (0x10001)
(1).使用openssl ca自建CA
要提供CA自己的证书,测试环境下CA只能自签署,使用"openssl req -x509"、"openssl x509"和"openssl ca"都可以自签署证书请求文件,此处仅介绍openssl ca命令自身自签署的方法。
先创建CA的证书请求文件,建议使用CA的私钥文件/etc/pki/CA/private/cakey.pem来创建待自签署的证书请求文件,虽非必须,但方便管理。创建请求文件时,其中Country Name、State or Province Name、Organization Name和Common Name默认是必须提供的。
[root@docker-03 ~]# openssl req -new -key /etc/pki/CA/private/cakey.pem -out rootCA.csr 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) [XX]:CN State or Province Name (full name) []:SX Locality Name (eg, city) [Default City]:TY Organization Name (eg, company) [Default Company Ltd]:ZDC Organizational Unit Name (eg, section) []:ZDC Common Name (eg, your name or your server's hostname) []:www.ljj.com Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
然后使用openssl ca命令自签署该证书请求文件。如果有两次交互式询问则表示自签署将成功,如果失败,则考虑数据库文件index.txt是否创建、序列号文件serial是否存在且有序号值、私钥文件cakey.pem是否路径正确、创建证书请求文件时是否该提供的没有提供等情况。
[root@docker-03 ~]# openssl ca -selfsign -in rootCA.csr Using configuration from /etc/pki/tls/openssl.cnf Check that the request matches the signature Signature ok Certificate Details: Serial Number: 1 (0x1) Validity Not Before: Mar 4 11:03:39 2020 GMT Not After : Mar 4 11:03:39 2021 GMT Subject: countryName = CN stateOrProvinceName = SX organizationName = ZDC organizationalUnitName = ZDC commonName = www.ljj.com X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: CF:A0:E4:A5:0E:E4:4A:8A:31:F4:12:B5:F0:63:FB:59:40:A2:4B:0F X509v3 Authority Key Identifier: keyid:CF:A0:E4:A5:0E:E4:4A:8A:31:F4:12:B5:F0:63:FB:59:40:A2:4B:0F Certificate is to be certified until Mar 4 11:03:39 2021 GMT (365 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 Certificate: Data: Version: 3 (0x2) Serial Number: 1 (0x1) Signature Algorithm: sha256WithRSAEncryption Issuer: C=CN, ST=SX, O=ZDC, OU=ZDC, CN=www.ljj.com Validity Not Before: Mar 4 11:03:39 2020 GMT Not After : Mar 4 11:03:39 2021 GMT Subject: C=CN, ST=SX, O=ZDC, OU=ZDC, CN=www.ljj.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:c6:68:0b:68:97:19:99:a1:6d:79:37:97:3b:24: a9:68:60:0f:75:4e:6f:26:d0:b1:92:2f:a0:7c:75: f6:37:72:c4:1d:42:5a:48:16:57:c4:45:75:a1:95: b7:66:9a:a5:2e:e9:9b:e4:a4:32:e6:5a:09:b4:e6: d3:63:89:85:34:98:85:84:32:61:1a:b7:02:25:99: 90:09:25:d8:01:46:ac:8e:7f:dc:37:a4:5e:64:cb: b7:e3:fa:2e:c7:60:05:cd:61:e7:62:9c:a3:95:cd: 07:84:91:57:8c:13:36:37:f6:bf:3e:60:df:48:a4: 58:b1:49:24:db:78:35:b4:b0:5f:4a:4a:a5:b8:46: 00:73:dd:b8:6f:9c:a1:19:af:51:9f:7b:82:7b:b0: b2:1b:57:2b:74:d3:35:1d:cc:ab:c9:fc:ea:aa:07: de:d3:d9:6a:1f:ac:91:1f:10:b4:11:0a:46:2b:d5: cb:e0:19:74:32:12:ba:76:ac:76:db:f3:c8:c3:e3: 69:a1:f8:89:ac:82:90:7c:04:c5:9d:e0:af:d0:19: 25:ec:03:38:ba:e8:b3:2d:84:b6:aa:73:b2:25:14: 13:10:47:5c:77:f0:33:55:0c:a0:1c:df:5f:3b:a6: 02:74:dc:d1:5e:33:90:e5:43:87:00:97:73:e2:95: ff:3d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: CF:A0:E4:A5:0E:E4:4A:8A:31:F4:12:B5:F0:63:FB:59:40:A2:4B:0F X509v3 Authority Key Identifier: keyid:CF:A0:E4:A5:0E:E4:4A:8A:31:F4:12:B5:F0:63:FB:59:40:A2:4B:0F Signature Algorithm: sha256WithRSAEncryption 2a:76:7f:4f:2b:ed:14:e9:7f:51:9b:96:97:04:7d:50:93:d6: 90:8f:21:83:a1:d4:27:4c:21:4b:2c:21:6c:4b:a5:30:8f:48: c9:d7:16:1f:c2:0e:fd:ec:d4:cb:2e:fb:6d:67:ca:96:35:eb: 53:57:eb:f6:c4:fc:7c:47:47:90:34:de:56:82:ed:18:7c:55: 3f:ae:81:2e:9a:65:8c:de:8a:7a:c4:c9:04:80:5c:68:9f:9d: 99:30:5f:8b:7d:e3:c2:b4:8b:4c:7e:41:92:b8:70:1e:8d:cc: f5:6f:89:79:1e:ec:27:c3:58:c8:3f:d1:95:bb:91:09:c2:00: 5f:d8:c2:7b:09:7c:ac:1f:e3:64:47:fd:70:17:a1:00:37:a6: 25:cd:a4:39:87:ad:a7:2d:da:58:91:1b:d0:a8:1a:85:3d:e8: 68:74:f6:36:b2:80:62:21:34:c3:5d:d0:e1:60:51:62:a8:59: f1:3e:54:0c:ce:ca:27:93:df:8c:57:14:eb:59:9c:25:28:68: 11:e2:ff:31:20:f2:08:d5:44:2e:25:ca:5b:70:94:22:e0:71: 9a:be:5b:41:90:8f:eb:cc:e1:c6:67:8e:7a:60:78:8d:f3:6f: e2:e8:bc:c4:87:de:31:0e:0d:da:3c:d3:a5:71:ca:64:08:ff: dc:02:9f:6c -----BEGIN CERTIFICATE----- MIIDjjCCAnagAwIBAgIBATANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJDTjEL MAkGA1UECAwCU1gxDDAKBgNVBAoMA1pEQzEMMAoGA1UECwwDWkRDMRQwEgYDVQQD DAt3d3cubGpqLmNvbTAeFw0yMDAzMDQxMTAzMzlaFw0yMTAzMDQxMTAzMzlaMEwx CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJTWDEMMAoGA1UECgwDWkRDMQwwCgYDVQQL DANaREMxFDASBgNVBAMMC3d3dy5samouY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEAxmgLaJcZmaFteTeXOySpaGAPdU5vJtCxki+gfHX2N3LEHUJa SBZXxEV1oZW3ZpqlLumb5KQy5loJtObTY4mFNJiFhDJhGrcCJZmQCSXYAUasjn/c N6ReZMu34/oux2AFzWHnYpyjlc0HhJFXjBM2N/a/PmDfSKRYsUkk23g1tLBfSkql uEYAc924b5yhGa9Rn3uCe7CyG1crdNM1Hcyryfzqqgfe09lqH6yRHxC0EQpGK9XL 4Bl0MhK6dqx22/PIw+NpofiJrIKQfATFneCv0Bkl7AM4uuizLYS2qnOyJRQTEEdc d/AzVQygHN9fO6YCdNzRXjOQ5UOHAJdz4pX/PQIDAQABo3sweTAJBgNVHRMEAjAA MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAd BgNVHQ4EFgQUz6DkpQ7kSoox9BK18GP7WUCiSw8wHwYDVR0jBBgwFoAUz6DkpQ7k Soox9BK18GP7WUCiSw8wDQYJKoZIhvcNAQELBQADggEBACp2f08r7RTpf1GblpcE fVCT1pCPIYOh1CdMIUssIWxLpTCPSMnXFh/CDv3s1Msu+21nypY161NX6/bE/HxH R5A03laC7Rh8VT+ugS6aZYzeinrEyQSAXGifnZkwX4t948K0i0x+QZK4cB6NzPVv iXke7CfDWMg/0ZW7kQnCAF/YwnsJfKwf42RH/XAXoQA3piXNpDmHract2liRG9Co GoU96Gh09jaygGIhNMNd0OFgUWKoWfE+VAzOyieT34xXFOtZnCUoaBHi/zEg8gjV RC4lyltwlCLgcZq+W0GQj+vM4cZnjnpgeI3zb+LovMSH3jEODdo806VxymQI/9wC n2w= -----END CERTIFICATE----- Data Base Updated [root@docker-03 ~]#
自签署成功后,在/etc/pki/CA目录下将生成一系列文件。
[root@docker-03 ~]# tree -C /etc/pki/CA /etc/pki/CA ├── certs ├── crl ├── index.txt ├── index.txt.attr ├── index.txt.old ├── newcerts │ └── 01.pem ├── private │ └── cakey.pem ├── serial └── serial.old 4 directories, 7 files
其中newcerts目录下的01.pem即为刚才自签署的证书文件,因为它是CA自身的证书,所以根据配置文件中的"certificate=$dir/cacert.pem"项,应该将其放入/etc/pki/CA目录下,且命名为cacert.pem,只有这样以后才能签署其它证书请求。
[root@docker-03 ~]# cp /etc/pki/CA/newcerts/01.pem /etc/pki/CA/cacert.pem
至此,自建CA就完成了,查看下数据库索引文件和序列号文件。
[root@docker-03 ~]# cat /etc/pki/CA/index.txt V 210304110339Z 01 unknown /C=CN/ST=SX/O=ZDC/OU=ZDC/CN=www.ljj.com
[root@docker-03 ~]# cat /etc/pki/CA/serial 02
那么,下次签署证书请求时,序列号将是"02"。
将上述自建CA的过程总结如下:
[root@docker-03 ~]# touch /etc/pki/CA/index.txt
[root@docker-03 ~]# echo "01" > /etc/pki/CA/serial
[root@docker-03 ~]# openssl genrsa -out /etc/pki/CA/private/cakey.pem
[root@docker-03 ~]# openssl req -new -key /etc/pki/CA/private/cakey.pem -out rootCA.csr
[root@docker-03 ~]# openssl ca -selfsign -in rootCA.csr
[root@docker-03 ~]# cp /etc/pki/CA/newcerts/01.pem /etc/pki/CA/cacert.pem^C
以上过程是完全读取默认配置文件创建的,其实很多过程是没有那么严格的,openssl ca命令自身可以指定很多选项覆盖配置文件中的项,但既然提供了默认的配置文件及目录结构,为了方便管理,仍然建议完全采用配置文件中的项。
(2).为他人颁发证书。
首先申请者创建一个证书请求文件。
[root@docker-03 ~]# openssl req -new -key privatekey.pem -out youwant1.csr
其中Country Name、State or Province Name、Organization Name和Common Name必须提供,且前三者必须和CA的subject中的对应项完全相同。这些是由配置文件中的匹配策略决定的。
[ ca ] default_ca = CA_default # The default ca section [ CA_default ] policy = policy_match [ policy_match ] countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional
"match"表示openssl ca要签署的证书请求文件中的项要和CA证书中的项匹配,即要相同,"supplied"表示必须要提供的项,"optional"表示可选项,所以可以留空。
现在就可以将证书请求文件发送给CA,让CA帮忙签署。
[root@docker-03 ~]# openssl ca -in youwant1.csr
签署成功后,查看下/etc/pki/CA下的文件结构。
[root@docker-03 ~]# tree -C /etc/pki/CA/
其中"02.pem"就是刚才签署成功的证书,将此证书发送给申请者即表示颁发完成。
再看下数据库索引文件和序列号文件。
[root@docker-03 ~]# cat /etc/pki/CA/index.txt
(3).openssl ca命令用法
经过上面的示例,应该对openssl ca命令的用法大致了解了,下面是其完整的用法说明,不包括crl相关功能。
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]
要注意,ca命令是用于签署证书的,所以它所需要的文件除了配置文件外就是私钥文件和证书请求文件,而签名后生成的文件是证书文件,因此使用"-in"指定的对象是待签署文件,"-infiles"则是指定多个待签署文件,"-keyfile"是指定私钥文件,"-out"是指定输出的证书文件。
【选项说明:】 -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=...
配置文件关于ca的部分,其中被标记为必须项的表示配置文件中或者命令行中必须给出该选项及其值。
new_certs_dir :等同于"-outdir"选项。必须项 certificat :等同于"-cert"选项,CA自己的证书文件。必须项 private_key :等同于"-keyfile"选项,签署证书请求文件时的私钥文件,即CA自己的私钥文件。必须项 default_days :等同于"-days"选项 default_startdate:等同于"-startdate"选项。 default_enddate :等同于"-enddate"选项。 default_md :等同于"-md"选项。必须项 database :openssl维护的数据库文件。存放证书条目信息及状态信息。必须项 serial :已颁发证书的序列号(16进制)文件。必须项且该文件中必须存在一个序列值 unique_subject :如果设置为yes,database中的subject列值必须不重复。如果设置为no,允许subject重复。默认是yes, :这是为了兼容老版本的Openssl,推荐设置为no。 x509_extensions :等同于"-extensions"选项。 policy :等同于"-policy"选项。必须项 name_opt/cert_opt:证书的展示格式,虽非必须但建议设置为ca_default,若不设置将默认使用老版本的证书格式(不建议如此)。 :伪命令ca无法直接设置这两个选项,而伪命令x509的"-nameopt"和"-certopt"选项可以分别设置。 copy_extensions :决定证书请求中的扩展项如何处理的。如果设置为none或不写该选项,则扩展项被忽略并且不复制到证书中去。 :如果设置为copy,则证书请求中已存在而证书中不存在的扩展项将复制到证书中。 :如果设置为copyall,则证书请求中所有的扩展项都复制到证书中,此时若证书中已存在某扩展项,则先删除再复制。 :该选项的主要作用是允许证书请求为特定的扩展项如subjectAltName提供值。 :使用该选项前请先查看man ca中的WARNINGS部分。建议一般简单使用时设置为none或不设置。