openssl对SSL证书及密钥操作说明

1. 使用OpenSSL自建CA

OpenSSL是一个免费的、开源的加密库,用于处理数字证书,提供了一些命令行工具。部分工具可以提供证书颁发机构的相关功能。

使用OpenSSL可以自建测试CA,OpenSSL的使用文档为 https://www.openssl.org/docs/manmaster/man1/ 。

使用OpenSSL自建CA可参考 https://www.madboa.com/geek/openssl/ 或 https://jamielinux.com/docs/openssl-certificate-authority/index.html 。

1.1. OpenSSL基本配置

以下使用Red Hat Enterprise Linux Server release 6.4环境进行测试。

openssl的命令可通过-config选项指定使用的配置文件,当不指定该选项时,会使用默认配置文件/etc/pki/tls/openssl.cnf。

在/etc/pki/tls/openssl.cnf配置文件中,[ca]部分的default_ca属性为默认的ca配置,值为CA_default。

[CA_default]部分的dir属性为openssl相关的存储目录,值为/etc/pki/CA。database属性为数据库索引文件,值为/etc/pki/CA/index.txt。serial属性为证书当前序号,值为/etc/pki/CA/serial。

1.2. OpenSSL自建CA相关命令

1.2.1. ca

ca命令是一个最小的CA应用程序。它可对多种格式的证书请求进行签名,也可创建证书吊销列表。ca命令将颁布的证书及证书状态保存在文本格式的数据库中。

ca命令包含了多种选项,每种对应不同的用途。

1.2.2. genrsa

genrsa命令可以创建RSA私钥。

1.2.3. req

req命令主要用于创建及处理PKCS#10格式的证书请求。它还可以创建作为示例使用的根CA自签名证书。

1.2.4. x509

x509命令可用于多种用途,可用于显示证书信息,转换证书为多种格式,像迷你CA一样对证书请求进行签名,或者编辑证书信任设置。

1.3. 自建CA的常用模式

作为CA,需要处理由私钥与公共密钥组成的密钥对。首先需要创建的密钥对为根密钥对,包含了根密钥与根证书。该密钥对构成了你的CA的身份。

通常,根CA并不对服务器或客户端证书直接进行签名。根CA仅用于创建中级CA,中级CA被根CA信任,可代表根CA对证书进行签名。这是最好的方式,这种方式使根密钥保持离线并尽可能减少对根密钥的使用。若根密钥被攻破,结果是灾难性的。

中级CA可代表根CA对证书进行签名,根CA对中间证书进行签名,形成受信任证书链。

使用中级CA的主要目的是为了安全。根私钥可以保持离线并尽可能减少使用。若中间密钥被攻破,根CA可以撤销中间证书并创建新的中间密钥对。

1.4. x509v3配置

x509v3配置为X509 V3证书扩展配置格式,相关文档可查看 https://www.openssl.org/docs/manmaster/apps/x509v3_config.html 。

某些OpenSSl组件可以添加扩展属性至证书或证书请求中,扩展属性基于配置文件的内容。

有以下四种主要类型的扩展:string extensions,multi-valued extensions,raw extensions与arbitrary extensions。

String extensions简单地有一个字符串,示例如下。

nsComment="This is a Comment"

Multi-valued extensions有一个短形式与长形式。短形式是一个名字与值的列表,示例如下。

basicConstraints=critical,CA:true,pathlen:1

长形式允许值被放置在一个单独的部分,示例如下。

basicConstraints=critical,@bs_section

[bs_section]

CA=true
pathlen=1

以上两种形式是等同的。

raw extensions与arbitrary extensions介绍略。

1.4.1. 标准扩展

1.4.1.1. Basic Constraints

基本约束是一个multi-valued extensions,表明一个证书是否是CA证书。第一个(强制性的)名字为CA,参数值为TRUE或FALSE。如果CA参数为TRUE,后续可以包含非负值的可选的pathlen参数。

基本约束示例如下:

basicConstraints=CA:TRUE

basicConstraints=CA:FALSE

basicConstraints=critical,CA:TRUE, pathlen:0

CA证书必须包含basicConstraints值,且CA参数需为TRUE。终端用户证书必须将CA参数设置为FALSE,或者不包含basicConstraints值。

pathlen参数指明了在证书链的当前证书之下允许存在的最大CA数量。当CA的pathlen值为0时,该CA仅能对终端用户证书进行签名,不能再对CA进行签名。

1.4.1.2. Authority Key Identifier

颁发机构密钥标识符扩展提供了对用于证书签名的私钥对应的公钥进行鉴定的方法。

颁发机构密钥标识符扩展允许两个选项:keyid与issuer。

当指定keyid选项时,会尝试从父证书中拷贝主体密钥标识符。

当指定issuer选项时,会从颁布者证书中拷贝颁布者与序号。

颁发机构密钥标识符示例如下:

authorityKeyIdentifier=keyid,issuer

1.4.1.3. Subject Key Identifier

主体密钥标识符扩展提供了对包含特定公钥的证书进行鉴定的方法。

主体密钥标识符是一个string extension,可为“hash”单词或十六进制字符串。当为“hash”时,会自动遵守RFC3280的方针;当为十六进制字符串时,该扩展值将包含该值,强烈不建议使用十六进制字符串形式。

RFC3280的地址为 http://www.ietf.org/rfc/rfc3280.txt 。

对于CA证书,主体密钥标识符应来自公共密钥或生成唯一值的方法。两个根据公钥生成密钥标识符的公共方法如下:

  1. 密钥标识符由160bit的SHA-1哈希值组成,哈希值数据来源为主体公钥的比特串(除标签、长度和未使用的毕特数外)。
  2. 密钥标识符由两部分组成,第一部分为一个4bit的类型字段,值为0100;随后的第二部分为主体公钥的比特串(除标签、长度和未使用的毕特数外)的SHA-1啥希值的60bit的最低有效位。

产生唯一值的一个常见方法是单调递增的整数序列。

对于终端用户证书,主体证书标识符应来自公钥。两个根据公钥生成密钥标识符的公共方法见上文。

主体密钥标识符的示例如下:

subjectKeyIdentifier=hash

1.4.2. 过时扩展

以下的扩展是非标准的,Netscape已明确废弃。不建议在新应用中使用这些扩展。

1.4.2.1. Netscape String extensions

Netscape注释(nsComment)是一个字符串扩展,包含一个会在某些浏览器中展示的注释。

Netscape字符串扩展的示例如下:

nsComment = "Some Random Comment"

1.5. OpenSSL自建CA步骤

使用OpenSSL自建CA的主要步骤如下。

1.5.1. 创建数据库与序号文件

在openssl.cnf的默认配置中,会使用/etc/pki/CA目录的index.txt与serial文件。假设使用/etc/pki/CA/目录保存生成的文件。

命令如下:

cd /etc/pki/CA/

rm -f index.txt*
rm -f serial*

touch index.txt serial
echo 01 > serial

index.txt与serial分别为数据库与序号文件,需要首先创建。若需将记录清除,需首先删除index.txt*与serial*文件。生成的serial文件中,初始序号设置为01。

1.5.2. 生成根私钥

命令如下:

# 生成根私钥
CAKEY=private/cakey.pem
CAKEYPASS=test_pass

openssl genrsa -out $CAKEY -aes256 -passout pass:$CAKEYPASS 2048

使用genrsa命令生成RSA私钥。

-out选项用于指定生成的私钥文件。

当指定了“-aes128|-aes192|-aes256|-camellia128|-camellia192|-camellia256|-des|-des3|-idea”等参数时,会使用指定的密码类型对私钥进行加密。当不指定“-aes128|-aes192|-aes256|-camellia128|-camellia192|-camellia256|-des|-des3|-idea”等参数,不会对私钥进行加密。

可通过-passout选项指定密码,若不指定-passout参数,则需要手工输入密码。

可通过-F4或-3选项指定公开指数,分别对应65537与3,默认值为65537。

最后的参数为私钥长度的位数,默认值为512。

当生成成功时,提示信息为“Generating RSA private key, 2048 bit long modulus … e is 65537 (0x10001)”,当指定-3参数时,提示“e is 3 (0x3)”。

1.5.3. 生成自签名根证书

命令如下:

# 生成自签名根证书
CAKEY=private/cakey.pem
CACERT=cacert.crt
CASUBJECT='/C=CN/ST=CA1_province/L=CA1_city/CN=CA1_url/O=CA1_O/OU=CA1_OU'
CAKEYPASS=test_pass

openssl req -new -x509 -sha256 -extensions v3_ca -subj $CASUBJECT -days 3650 -key $CAKEY -out $CACERT -passin pass:$CAKEYPASS

使用req命令生成自签名证书。

当指定-new选项时,会创建新的证书请求。

当指定-x509选项时,将会输出自签名证书而不是证书请求。主要用于创建测试证书或自签名根CA。

可指定用于对请求进行签名的消息摘要,dgst命令支持的摘要类型均可使用,如-sha256。可使用“openssl dgst -help”命令查看支持的摘要类型。若不指定进行签名的摘要类型,则会使用openssl配置文件的[req]部分的default_md属性,默认值为sha1。

-extensions选项的参数值v3_ca对应openssl.cnf配置文件中的[v3_ca]部分。[v3_ca]部分的配置为典型CA的扩展配置,basicConstraints字段为CA:true。

-subj选项用于设置新请求的主体名称,或在处理请求时取代主体名称。参数格式为“/类型0=值0/类型1=值1/类型2=…”,字符可使用“\”进行转义,空格不会被跳过。-subj选项含义可参考前文“X.500 Distinguished Names”部分。当未指定-subj选项时,需要通过标准输入进行配置。

openssl.cnf配置文件中的[req]部分的distinguished_name字段值为req_distinguished_name,req_distinguished_name部分定义了X.500识别名各字段的限制与默认值。

当指定-x509选项时,-days选项用于设置证书有效期,单位为天,默认值为30天。

-key选项用于指定需要读取的私钥,可以接受PEM格式文件中的PKCS#8格式的私钥。

-out选项用于指定生成的证书文件路径,默认值为标准输出。

-passin参数用于指定读取的私钥的密码,若不指定则需要通过标准输入进行设置。

通过-outform选项可以设置生成文件的格式,可选参数为DER或PEM,默认为PEM。

当生成成功时,无提示信息。

1.5.4. 生成中级CA私钥

命令如下:

# 生成中级CA私钥
CA2KEY=private/cakey2.pem
CA2KEYPASS=test_pass

openssl genrsa -out $CA2KEY -aes256 -passout pass:$CA2KEYPASS 2048

当生成成功时,与生成根私钥成功时提示相同。

1.5.5. 生成中级CA证书签名请求

命令如下:

# 生成中级CA证书签名请求
CA2KEY=private/cakey2.pem
CA2CSR=CA2.csr
CA2SUBJECT='/C=CN/ST=CA2_province/L=CA2_city/CN=CA2_url/O=CA2_O/OU=CA2_OU'
CA2KEYPASS=test_pass

openssl req -new -extensions v3_ca -subj $CA2SUBJECT -key $CA2KEY -out $CA2CSR -passin pass:$CA2KEYPASS

当生成成功时,无提示信息。

1.5.6. 对中级CA证书签名请求进行签名

命令如下:

# 对中级CA证书签名请求进行签名,生成证书
CAKEY=private/cakey.pem
CACERT=cacert.crt
CA2CSR=CA2.csr
CA2CERT=CA2.crt
CAKEYPASS=test_pass

openssl ca -extensions v3_ca -md sha256 -in $CA2CSR -out $CA2CERT -cert $CACERT -keyfile $CAKEY -notext -days 3650 -policy policy_anything -passin pass:$CAKEYPASS -batch

使用ca命令对证书签名请求进行签名,生成证书。

-md选项用于设置消息摘要算法,默认值为sha1。OpenSSL dgst命令支持的算法均可使用。

-in选项用于指定需要被CA签名的证书签名请求文件。

-out选项用于指定生成的证书文件,默认为标准输出。证书详情也会以PEM格式保存到文件中(当指定-spkac选项时会使用DER格式)。

-cert选项用于指定CA证书文件。

-keyfile选项指定用于对证书签名证书进行签名的私钥。

-notext选项指定不会将文本格式的证书信息输出到文件中。当不指定该选项时,会将文本格式的证书信息输出到文件中,证书无法直接使用。文本格式的证书信息与“openssl x509 -text”命令的输出结果相同,详细说明见后文。

-days选项用于设置证书有效期,单位为天。在openssl.cnf配置文件中,[ca]部分的default_ca为CA_default,[CA_default]部分的default_days字段为默认有效期,值为365。

-policy选项可以设置使用的策略。在openssl.cnf配置文件中,[ca]部分的default_ca为CA_default,[CA_default]部分的policy为policy_match,[policy_match]部分的countryName、stateOrProvinceName与organizationName均为match。当使用policy_match时,在执行ca命令时,CA证书与证书请求的X.500识别名C(countryName)、ST(stateOrProvinceName)与O(organizationName)需相同,若不相同则会提示“The xxx field needed to be the same in the CA certificate () and the request ()”。openssl.cnf配置文件中,[policy_anything]部分的countryName、stateOrProvinceName与organizationName均为optional。当使用policy_anything时,在执行ca命令时,CA证书与证书请求的X.500识别名C(countryName)、ST(stateOrProvinceName)与O(organizationName)可不相同。将openssl.cnf配置文件中的[CA_default]部分的policy修改为policy_anything,或在执行openssl ca命令时,指定“-policy policy_anything”,则上述的信息可不相同。

使用-batch选项时,不会出现确认提示。否则会提示“Sign the certificate?”、“1 out of 1 certificate requests certified, commit?”

若指定-subj选项,可以取代证书请求中的主体名称。

无论ca命令是否执行成功,均会出现以下提示:

Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details: xxx
Certificate is to be certified until xx (xx days)

ca命令执行成功时,/etc/pki/CA/index.txt文件中会增加生成的证书信息,/etc/pki/CA/serial文件内容为当前证书的序号,会在原有基础加1。提示信息如下。

Write out database with 1 new entries
Data Base Updated

若根据index.txt与serial文件内容判断当前需要生成的证书已生成过时,ca命令会执行失败,提示信息如下。

failed to update database
TXT_DB error number 2

1.5.7. 对证书签名请求进行签名

本步骤处理的证书签名请求文件生成过程可查看前文JAVA密钥库部分的“生成证书签名请求”内容。

命令如下:

# 对证书签名请求进行签名,生成证书
CA2KEY=private/cakey2.pem
CA2CERT=CA2.crt
TESTCSR=certreq.csr
TESTSIGNEDCERT=server_signed.crt
CAKEYPASS=test_pass

openssl ca -extensions usr_cert -md sha256 -in $TESTCSR -out $TESTSIGNEDCERT -cert $CA2CERT -keyfile $CA2KEY -notext -days 3650 -policy policy_anything -passin pass:$CAKEYPASS -batch

-extensions选项的参数值usr_cert对应openssl.cnf配置文件中的[usr_cert]部分。[usr_cert]部分的配置为CA对证书请求进行签名时的扩展配置,basicConstraints字段为CA:FALSE(生成的证书非CA证书),nsComment字段为"OpenSSL Generated Certificate"。

执行完毕的提示信息见上文。

1.6. OpenSSL其他命令

1.6.1. 查看证书信息

命令如下:

# 查看证书信息
CERT=

openssl x509 -noout -text -in $CERT

使用x509命令查看证书信息。

指定-noout选项时,不会输出证书内容。

指定-text选项时,会以文本形式输出证书内容。证书的详细内容会输出,包括公钥,签名算法,颁布者与主体名称,序号,任意扩展属性与信任设置。

-in选项指定需要查看的证书文件。

-inform选项可指定证书格式,默认PEM,若需查看的证书格式为DER,需要指定“-inform DER”。

使用上述命令查看证书信息结果示例如下:

Certificate:  
    Data:  
        Version: 3 (0x2)  
        Serial Number: xx  
        Signature Algorithm: xx  
        Issuer: C=xx, ST=xx, L=xx, O=xx, OU=xx, CN=xx  
        Validity  
            Not Before: xx  
            Not After : xx  
        Subject: C=xx, ST=xx, L=xx, O=xx, OU=xx, CN=xx  
        Subject Public Key Info:  
            Public Key Algorithm: xx  
                Public-Key: (xx bit)  
                Modulus:  
                    xx  
                Exponent: xx  
        X509v3 extensions:  
            X509v3 Basic Constraints:   
                CA:xx  
            Netscape Comment:   
                xx  
            X509v3 Subject Key Identifier:   
                xx  
            X509v3 Authority Key Identifier:   
                xx  
  
    Signature Algorithm: xx  
        xx  

Serial Number属性为证书序号,对应生成证书时的serial文件内容。

Signature Algorithm属性对应生成证书时选择的消息摘要算法。

Issuer属性对应对证书签名请求进行签名的CA的X.500识别名。

Validity属性对应生成证书时设置的证书有效期。

Subject属性对应终端用户证书的证书签名请求生成时指定的X.500识别名。

Public-Key属性为密钥长度。

X509v3 extensions字段的X509v3 Basic Constraints属性为CA:FALSE或CA:TRUE。

1.6.2. 证书格式转换

命令如下:

# PEM(BASE64)转DER(二进制)
infile=
outfile=

openssl x509 -outform DER -in $infile -out $outfile

# DER(二进制)转PEM(BASE64)
infile=
outfile=

openssl x509 -inform DER -in $infile -out $outfile

使用x509命令进行证书格式转换,-inform与-outform选项分别用于指定输入文件与输出文件的证书格式,支持PEM(BASE64)与DER(二进制)等,默认格式为PEM。

-in与-out选项分别用于指定输入与输出文件。当未指定-in选项时,会从标准输入读取证书内容。当未指定-out选项时,会默认输出到标准输出。

当证书格式转换成功时,无提示信息。

1.6.3. PKCS#12导出私钥

# p12导出私钥
set tmp_p12=server.p12
set out_pem=tmp.rsa.pem
set server_pem=server.key
set pwd_new=123456

openssl pkcs12 -in %tmp_p12% -nodes -out %out_pem% -passin pass:%pwd_new%
openssl rsa -in %out_pem% -check > %server_pem% 

1.6.4. PEM格式的私钥转PKCS#8格式的私钥

查看pkcs8的topk8命令

-topk8

Normally a PKCS#8 private key is expected on input and a traditional format private key will be written. With the -topk8 option the situation is reversed: it reads a traditional format private key and writes a PKCS#8 format key.

使用pkcs8命令时,指定topk8选项,将传统格式转换为PKCS#8格式,若不指定,则将PKCS#8格式转换为传统格式

openssl pkcs8 -topk8 -in final.key -inform PEM -out pkcs8.key -outform DER -nocrypt
openssl pkcs8 -topk8 -in final.key -inform PEM -out pkcs8-PEM.key -outform PEM -nocrypt

openssl pkcs8 -in pkcs8.key -inform DER -out traditional-PEM.key -outform PEM -nocrypt
openssl pkcs8 -in pkcs8.key -inform DER -out traditional-DER.key -outform DER -nocrypt

BEGIN RSA PRIVATE KEY与BEGIN PRIVATE KEY的区别,可参考 https://tls.mbed.org/kb/cryptography/asn1-key-structures-in-der-and-pem 、 http://stackoverflow.com/questions/20065304/what-is-the-differences-between-begin-rsa-private-key-and-begin-private-key 。

2. openssl连接测试

使用openssl的s_client命令可以连接SSL服务器进行测试,例如:

openssl s_client -connect www.baidu.com:443 -showcerts
发布了37 篇原创文章 · 获赞 0 · 访问量 2327

猜你喜欢

转载自blog.csdn.net/a82514921/article/details/104589443
今日推荐