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

 

热门相关:仙城纪   刺客之王   薄先生,情不由己   刺客之王   薄先生,情不由己