OpenSSL 介绍(5)--数字证书
本文主要介绍如何使用 OpenSSL 来对数字证书进行管理;文中所使用到的软件版本:OpenSSL 1.1.1s、CentOS 7.9.2009。
1、数字证书
摘要算法用来确保数据没有被篡改,非对称加密算法可以对数据进行加解密,签名算法可以确保数据完整性和抗否认性,把这些算法集合到一起,并搞一套完善的标准,这就是数字证书。因此,数字证书就是集合了多种密码学算法,用于实现数据加解密、身份认证、签名等多种功能的一种安全标准。
数字证书可以防止中间人攻击,因为它采用链式签名认证,即通过根证书(Root CA)去签名下一级证书,这样层层签名,直到最终的用户证书。而 Root CA 证书内置于操作系统中,所以,任何经过 CA 认证的数字证书都可以对其本身进行校验,确保证书本身不是伪造的。
我们在上网时常用的 HTTPS 协议就是数字证书的应用,浏览器会自动验证证书的有效性。
要使用数字证书,首先需要创建证书。正常情况下,一个合法的数字证书需要经过 CA 签名,这需要认证域名并支付一定的费用。开发的时候,我们可以使用自签名的证书,这种证书可以正常开发调试,但不能对外作为服务使用,因为其他客户端并不认可未经 CA 签名的证书。
2、用法
2.1、生成和处理证书请求(req)
通过 openssl req -help 命令查看用法:
shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl req -help Usage: req [options] Valid options are: -help Display this summary -inform PEM|DER Input format - DER or PEM -outform PEM|DER Output format - DER or PEM -in infile Input file -out outfile Output file -key val Private key to use -keyform format Key file format -pubkey Output public key -new New request -config infile Request template file -keyout outfile File to send the key to -passin val Private key password source -passout val Output file pass phrase source -rand val Load the file(s) into the random number generator -writerand outfile Write random data to the specified file -newkey val Specify as type:bits -pkeyopt val Public key options as opt:value -sigopt val Signature parameter in n:v form -batch Do not ask anything during request generation -newhdr Output "NEW" in the header lines -modulus RSA modulus -verify Verify signature on REQ -nodes Don't encrypt the output key -noout Do not output REQ -verbose Verbose output -utf8 Input characters are UTF8 (default ASCII) -nameopt val Various certificate name options -reqopt val Various request text options -text Text form of request -x509 Output a x509 structure instead of a cert request (Required by some CA's) -subj val Set or modify request subject -subject Output the request's subject -multivalue-rdn Enable support for multivalued RDNs -days +int Number of days cert is valid for -set_serial val Serial number to use -addext val Additional cert extension key=value pair (may be given more than once) -extensions val Cert extension section (override value in config file) -reqexts val Request extension section (override value in config file) -precert Add a poison extension (implies -new) -* Any supported digest -engine val Use engine, possibly a hardware device -keygen_engine val Specify engine to be used for key generation operations
参数说明:
参数 | 说明 |
-in infile | 指定输入文件 |
-out outfile | 指定输出文件 |
-key val | 指定私钥 |
-new | 生成一个新的 CSR(Cerificate Signing Request) |
-keyout outfile | 指定私钥输出文件 |
-newkey val | 生成新的私钥,指定算法及密钥长度;如:rsa:2048 |
-nodes | 生成证书时不需设置密码 |
-x509 | 输出 x509 格式证书,而不是输出证书请求 |
-days +int | 指定证书有效天数 |
2.2、证书工具(x509)
x509 命令是一个多用途的证书工具,可以显示证书信息、转换证书格式、签名证书请求以及改变证书的信任设置等;通过 openssl x509 -help 命令查看用法:
shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl x509 -help Usage: x509 [options] Valid options are: -help Display this summary -inform format Input format - default PEM (one of DER or PEM) -in infile Input file - default stdin -outform format Output format - default PEM (one of DER or PEM) -out outfile Output file - default stdout -keyform PEM|DER|ENGINE Private key format - default PEM -passin val Private key password/pass-phrase source -serial Print serial number value -subject_hash Print subject hash value -issuer_hash Print issuer hash value -hash Synonym for -subject_hash -subject Print subject DN -issuer Print issuer DN -email Print email address(es) -startdate Set notBefore field -enddate Set notAfter field -purpose Print out certificate purposes -dates Both Before and After dates -modulus Print the RSA key modulus -pubkey Output the public key -fingerprint Print the certificate fingerprint -alias Output certificate alias -noout No output, just status -nocert No certificate output -ocspid Print OCSP hash values for the subject name and public key -ocsp_uri Print OCSP Responder URL(s) -trustout Output a trusted certificate -clrtrust Clear all trusted purposes -clrext Clear all certificate extensions -addtrust val Trust certificate for a given purpose -addreject val Reject certificate for a given purpose -setalias val Set certificate alias -days int How long till expiry of a signed certificate - def 30 days -checkend intmax Check whether the cert expires in the next arg seconds Exit 1 if so, 0 if not -signkey val Self sign cert with arg -x509toreq Output a certification request object -req Input is a certificate request, sign and output -CA infile Set the CA certificate, must be PEM format -CAkey val The CA key, must be PEM format; if not in CAfile -CAcreateserial Create serial number file if it does not exist -CAserial val Serial file -set_serial val Serial number to use -text Print the certificate in text form -ext val Print various X509V3 extensions -C Print out C code forms -extfile infile File with X509V3 extensions to add -rand val Load the file(s) into the random number generator -writerand outfile Write random data to the specified file -extensions val Section from config file to use -nameopt val Various certificate name options -certopt val Various certificate text options -checkhost val Check certificate matches host -checkemail val Check certificate matches email -checkip val Check certificate matches ipaddr -CAform PEM|DER CA format - default PEM -CAkeyform PEM|DER|ENGINE CA key format - default PEM -sigopt val Signature parameter in n:v form -force_pubkey infile Force the Key to put inside certificate -next_serial Increment current certificate serial number -clrreject Clears all the prohibited or rejected uses of the certificate -badsig Corrupt last byte of certificate signature (for test) -* Any supported digest -subject_hash_old Print old-style (MD5) subject hash value -issuer_hash_old Print old-style (MD5) issuer hash value -engine val Use engine, possibly a hardware device -preserve_dates preserve existing dates when signing
参数说明:
参数 | 说明 |
-inform format | 输入格式,DER 或 PEM |
-in infile | 输入文件 |
-outform format | 输出格式,DER 或 PEM |
-out outfile | 输出文件 |
-keyform PEM|DER|ENGINE | 私钥格式 |
-noout | 不输出证书内容 |
-signkey val | 指定签名私钥 |
-text | 以文本格式打印证书信息 |
2.3、CA(ca)
ca 命令是一个小型 CA 系统,它能签发证书请求和生成 CRL;它维护一个已签发证书状态的文本数据库。通过 openssl ca -help 命令查看用法:
shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl ca -help Usage: ca [options] Valid options are: -help Display this summary -verbose Verbose output during processing -config val A config file -name val The particular CA definition to use -subj val Use arg instead of request's subject -utf8 Input characters are UTF8 (default ASCII) -create_serial If reading serial fails, create a new random serial -rand_serial Always create a random serial; do not store it -multivalue-rdn Enable support for multivalued RDNs -startdate val Cert notBefore, YYMMDDHHMMSSZ -enddate val YYMMDDHHMMSSZ cert notAfter (overrides -days) -days +int Number of days to certify the cert for -md val md to use; one of md2, md5, sha or sha1 -policy val The CA 'policy' to support -keyfile val Private key -keyform format Private key file format (PEM or ENGINE) -passin val Input file pass phrase source -key val Key to decode the private key if it is encrypted -cert infile The CA cert -selfsign Sign a cert with the key associated with it -in infile The input PEM encoded cert request(s) -out outfile Where to put the output file(s) -outdir dir Where to put output cert -sigopt val Signature parameter in n:v form -notext Do not print the generated certificate -batch Don't ask questions -preserveDN Don't re-order the DN -noemailDN Don't add the EMAIL field to the DN -gencrl Generate a new CRL -msie_hack msie modifications to handle all those universal strings -crldays +int Days until the next CRL is due -crlhours +int Hours until the next CRL is due -crlsec +int Seconds until the next CRL is due -infiles The last argument, requests to process -ss_cert infile File contains a self signed cert to sign -spkac infile File contains DN and signed public key and challenge -revoke infile Revoke a cert (given in file) -valid val Add a Valid(not-revoked) DB entry about a cert (given in file) -extensions val Extension section (override value in config file) -extfile infile Configuration file with X509v3 extensions to add -status val Shows cert status given the serial number -updatedb Updates db for expired cert -crlexts val CRL extension section (override value in config file) -crl_reason val revocation reason -crl_hold val the hold instruction, an OID. Sets revocation reason to certificateHold -crl_compromise val sets compromise time to val and the revocation reason to keyCompromise -crl_CA_compromise val sets compromise time to val and the revocation reason to CACompromise -rand val Load the file(s) into the random number generator -writerand outfile Write random data to the specified file -engine val Use engine, possibly a hardware device
参数说明:
参数 | 说明 |
-config val | 指定 OpenSSl 的配置文件 |
-days +int | 指定证书的有效天数 |
-keyfile val | 指定私钥 |
-keyform format | 指定私钥格式,PEM 或 ENGINE |
-in infile | 指定 PEM 格式的证书请求文件 |
-out outfile | 指定输出文件 |
-cert infile | 指定 CA 证书 |
2.4、个人证书(pkcs12)
pkcs12 命令能生成和分析 pkcs12 格式证书,通过 openssl pkcs12 -help 命令查看用法:
shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl pkcs12 -help Usage: pkcs12 [options] Valid options are: -help Display this summary -nokeys Don't output private keys -keyex Set MS key exchange type -keysig Set MS key signature type -nocerts Don't output certificates -clcerts Only output client certificates -cacerts Only output CA certificates -noout Don't output anything, just verify -info Print info about PKCS#12 structure -chain Add certificate chain -twopass Separate MAC, encryption passwords -nomacver Don't verify MAC -descert Encrypt output with 3DES (default RC2-40) -certpbe val Certificate PBE algorithm (default RC2-40) -export Output PKCS12 file -noiter Don't use encryption iteration -maciter Use MAC iteration -nomaciter Don't use MAC iteration -nomac Don't generate MAC -LMK Add local machine keyset attribute to private key -nodes Don't encrypt private keys -macalg val Digest algorithm used in MAC (default SHA1) -keypbe val Private key PBE algorithm (default 3DES) -rand val Load the file(s) into the random number generator -writerand outfile Write random data to the specified file -inkey val Private key if not infile -certfile infile Load certs from file -name val Use name as friendly name -CSP val Microsoft CSP name -caname val Use name as CA friendly name (can be repeated) -in infile Input filename -out outfile Output filename -passin val Input file pass phrase source -passout val Output file pass phrase source -password val Set import/export password source -CApath dir PEM-format directory of CA's -CAfile infile PEM-format file of CA's -no-CAfile Do not load the default certificates file -no-CApath Do not load certificates from the default certificates directory -* Any supported cipher -engine val Use engine, possibly a hardware device
参数说明:
参数 | 说明 |
-clcerts | 仅输出客户端证书,不输出 CA 证书 |
-export | 导出 pkcs12 证书 |
-inkey val | 指定输入私钥 |
-in infile | 指定输出证书 |
-out outfile | 指定输出的 pcks12 证书文件 |
3、具体使用
3.1、生成证书请求
shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl genrsa -out server.key #生成私钥 shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl req -new -key ca.key -out server.csr #生成证书请求
需要先生成私钥,再根据私钥生成证书请求;依次输入 Country Name、State or Province Name、Locality Name 、Organization Name、Organizational Unit Name、Common Name 信息,生成证书请求文件:nginx.csr。
3.2、根据证书请求生成证书
shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl x509 -req -days 3650 -in nginx.csr -signkey server.key -out server.pem
3.3、一步生成私钥和证书
/home/mongo/soft/openssl-1.1.1s/bin/openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout server.key -out server.pem
等同于 3.1 和 3.2 中命令。
3.4、打印证书信息
/home/mongo/soft/openssl-1.1.1s/bin/openssl x509 -in server.pem -noout -text
3.5、证书格式转换
/home/mongo/soft/openssl-1.1.1s/bin/openssl x509 -in server.pem -out server.cer -outform der
把 PEM 格式证书转成 DER 格式证书。
3.6、给自己颁发根证书,由根证书签发下级证书
3.6.1、建立根证书
shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl genrsa -out ca.key #生成私钥 shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl req -new -key ca.key -out ca.csr #生成证书请求 shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl x509 -req -days 3650 -in ca.csr -signkey ca.key -out ca.pem #生成根证书
生成证书请求时输入如下信息:
Country Name = CN State or Province Name = JS Locality Name = NJ Organization Name = ABC Organizational Unit Name = ABC_123 Common Name = ROOT
3.6.2、生成服务端证书
生成服务端证书给 WEB 应用服务器(如:nginx)使用。
shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl genrsa -out server.key #生成私钥 shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl req -new -key nginx.key -out server.csr #生成证书请求 shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl ca -days 3650 -in server.csr -cert ca.pem -keyfile ca.key -out server.pem #生成服务端证书
生成证书请求时输入如下信息:
Country Name = CN State or Province Name = JS Locality Name = NJ Organization Name = ABC Organizational Unit Name = ABC_123 Common Name = abc.com #可以输入服务器的域名或 IP
3.6.2、生成客户端证书
shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl genrsa -des3 -out client.key 1024 #生成私钥,指定密钥的加密算法,提高安全性 shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl req -new -key client.key -out client.csr #生成证书请求 shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl ca -days 1500 -in client.csr -cert ca.pem -keyfile ca.key -out client.pem #生成客户端证书 shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl pkcs12 -export -clcerts -in client.pem -inkey client.key -out client.p12 #生成 pkcs12 格式的客户端证书
生成证书请求时输入如下信息:
Country Name = CN State or Province Name = JS Locality Name = NJ Organization Name = ABC Organizational Unit Name = ABC_123 Common Name = client #可以输入客户端的名称标识
生成 pkcs12 格式证书时,需要先输入私钥的密码,然后再设置输出的 pkcs12 证书的密码。
4、错误处理
4.1、unable to access the xxx/newcerts directory
在进行 ca 命令操作时,可能会报如下的错误:
unable to access the xxx/newcerts directory
或
./demoCA/newcerts: No such file or directory
4.1.1、原因分析
这主要是由于 CA 目录不存在或当前用户无访问权限导致的。
4.1.2、解决方法
4.1.2.1、普通用户使用 root 安装的 OpenSSL
对于这种情况可以通过指定 OpenSSL 配置文件的方式来处理。
A、拷贝 OpenSSL 配置文件
cp /etc/pki/tls/openssl.cnf /home/mongo/openssl.cnf
B、修改拷贝的配置文件中 CA 目录
#dir = /etc/pki/CA # Where everything is kept dir = /home/mongo/test/CA
在 CA 目录(/home/mongo/test/CA)下创建 newcerts 目录(空目录)、index.txt 文件(空文件)、serial 文件(内容为一个数字,如:00)。
C、执行 ca 命令时指定配置文件的位置
/home/mongo/soft/openssl-1.1.1s/bin/openssl ca -days 1000 -in client.csr -cert ca.pem -keyfile ca.key -out client.pem -config /home/mongo/openssl.cnf
4.1.2.2、root 用户使用 OpenSSL 或普通用户使用自己安装的 OpenSSL
对于这种情况可以先修改默认配置文件中的 CA 目录,再在设置的 CA 目录下创建对应的目录及文件。
A、修改默认配置文件中 CA 目录
找到 OpenSSL 的默认配置文件并修改:
#dir = ./demoCA # Where everything is kept dir = /home/mongo/soft/openssl-1.1.1s/ssl/CA
在 CA 目录(/home/mongo/soft/openssl-1.1.1s/ssl/CA)下创建 newcerts 目录(空目录)、index.txt 文件(空文件)、serial 文件(内容为一个数字,如:00)。
B、正常执行 ca 命令
/home/mongo/soft/openssl-1.1.1s/bin/openssl ca -days 1000 -in client.csr -cert ca.pem -keyfile ca.key -out client.pem