openssl密钥证书管理(Key and Certificate Management)

这篇具有很好参考价值的文章主要介绍了openssl密钥证书管理(Key and Certificate Management)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言       

        前两日应别人要求提供一份CSR文件过去,方便他们生成相关证书,对于这一块本来也不熟,于是找到openssl官网,想找找相关的教程看看,一番小找,果有收获,是个宝藏,源文档在这(OpenSSL Cookbook烹饪宝典),有意者可前往一观(最好是能仔细看看官方提供的原文,百度众多的博客文章,难为佳策,不如一见本尊为妥)。

        本文只是节选概括了其中的部分内容,不为全部,可能会有些理解的偏颇,望周悉。

私钥和证书管理   

        现在很多网站(或web server)为了安全访问都采用了证书认证的模式(以支持SSL),这个过程主要有3大步:

(1)生成一个私钥(private key);

(2)创建一个CSR(Certificate Signing Request)文件,将它提供给一个CA;

(3)在网站(或web server)安装CA提供的证书文件。

私钥

        在运行一个TLS server之前我们首先要做的就是准备好一个私钥文件,在准备私钥文件之前我们得决定私钥的一些属性,比如私钥算法、私钥长度、保护密码等等。

私钥算法

        OpenSSL支持RSA/DSA/ECDSA/EdDSA算法(这些算法的一些数学原理大家可以找些条理清晰,没有大毛病的文章看看,比如这里),但是实际过程中,只是使用了其中的部分,用的最多的还是RSA和ECDSA(DSA和EdDSA并不被大范围支持)。

私钥长度

        如果在生成私钥时不指定其密钥长度,那么它会使用一个默认值,但这往往不是太安全(长度比较小,破解难度小),我们需要指定一个更大长度的(前提硬件得能能力支持),目前比较推荐的是2048-bit的RSA算法私钥以及256 bits的ECDSA。

保护密码

        为私钥设置一个保护密码(使用这份私钥时会提示提供密码,失败则不能使用该私钥文件),并不是必须的,但为了安全程度更高一点还是比较推荐的,但是呢,使用了保护密码,在日常使用上会比较烦,因为每次使用私钥时都被提示需要输入该私钥的密码(一个字符串明文),所以有些场景为了简易部署和使用,可能会不使用该保护密码,毕竟除了方便性,保护密码能提供的保护力度也是有限的,有些地方则会采用硬件保护的方式来确保私钥的安全。

生成私钥

        生成RSA私钥,使用genpkey命令,带保护密码的完整命令如下,保护密码也提供了加密算法,这里是AES-128(也可以是AES-256,-aes-256-cbc),避免使用其他算法,比如DES/3DES/SEED等:

$openssl genpkey -out private.key -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -aes-128-cbc

openssl密钥证书管理(Key and Certificate Management),AAA,openssl,ssl,证书,密钥

按提示创建一个包含密码并再确认重输一次。

如果不要保护密码,那么可以参考下面的命令:

$openssl genpkey -out private.key -algorithm RSA -pkeyopt rsa_keygen_bits:2048

后面还会提到另外一种生成方式(与csr文件同时)。

查看私钥

        当通过genpkey命令生成私钥时,这份私钥会被保存为PKCS #8格式(文本),cat private.key一下看起来会像下面这样:

root@ubuntu:/tmp# openssl genpkey -out private.key -algorithm RSA -pkeyopt rsa_keygen_bits:2048
...............................................+++
........................................+++
root@ubuntu:/tmp# cat private.key 
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCiFKjjCTCIv4al
FX6tE0sKwd8o/cGET9lilw77M3SSHYf++Eczu9h5y4JUVtKmXc81uLgFWVQ/Jvkq
TTW/d+P8FdXUBRfQEW0CLKaa3ONaOnVtrQjLp4eYGQbhXifotYGnnDUFyUdyy0Eq
obdMJrTixA5HGAGOodHPgwzw5dVkGPmMrcGJjcYU1QsBikYpQ2hIYu5qlUS2BgeM
Yhkxks07iVKNYAOp3YD3owaGpXUzvjTi0h22o5QExE8LV99nI5ZkwvJknVy2+k20
kzFqwSD6ohfVJ5GEBmUSJlOE2+dvgGRblEgr5ByTt5fcMGK2+4x7Np4k65XZiY9O
WBixzXdjAgMBAAECggEABNrPkDVXQdFSzCEPsUlxpvnVoFmxcTAfF8fkh/urkzDV
QPrYzyDiRAundLVBDAClUzucL3TUhCu7rNuxL3H83zEcPYSFiRLsi/MgbmUNXkd/
+vAC4m67LgAZ56g1U9AT+RxBrlGwFS0nX4qGff5uzpgGwXRjn40TRr7rJVANCzl0
EkwHJOgvrm9US4R5BZw1RVe69W5UB9fvYvyo0rzHmK6e/mkKpzixmBQZ6Mk26jV2
IiwYkMt4WyCSPFhKDEBsOVVYRob6vtkBFDA5OoukJ99jpG0qu4DAXgRiTS+7qqYB
ktdI3lZHmIehoPDCmqJJj6UitocpVyH/b2PI0q9oUQKBgQDS6z7rX6ga3d0mGUPk
4vdRTVTRGgy+74X0vRbVxJY5zOTcx/hOdnzWezNsYSN1eCx2Z/Pku9Mg9kneuo6U
EHIwtQHSeKS2S7EB/Ic6KLqW+HgTK42wi3r+husRNB+M08RvN1q0tV0IH5Xf6cxl
5pGmFV8Cwx7tySla/qdyDUpmGwKBgQDEuSe0Q85g7c4yhdf7BTD6vV6rkuA65Wmc
y+WyWuk7NolgYRz5HIKY6Pqfo3hjLqyx4LC+JTGWUgqgtag/qVAtgrAXdizo87sG
cdhmAiPrwDwUE0KcrX6BsyuRZsVfH35ftWSFCVpbbEb+8nhkLhBpV0aKmkjTlVpC
/1PE969oWQKBgCDy+wtOEDbSPf/7pm2VP0mGKR/ZT/Br/qMy/uQ6J7Wz2nTbEGFB
hVMEQA5IRn/NXDTLHIC5DsxxbSzMPAXJY+1T+YrlqeWIgYhr6LwfLLb07d0gyquv
vnEQppwzZlJbqq4tGZBtXLEuLf2iynmIwWwOnp8R2D0RVdKPQZ1BkkPNAoGACG9P
7oDBxpIrtyrZ+d9dHEMmXgDsMFpJzvlHHgCb43gRJ9rCHURFrTzAEjw2GzqTGQVj
TqPVnnZiEkX3stMVpv3lgvwELPDWYg5bkvQgiikx6kJxJrqho/oEsjVP3SZCiuQC
LVobT7QyzxeiZdk7xuiBE8xNtxS+TAUamGVuVfECgYBsO01qj45/rbfr1V4njdol
+qIsJiuuSkZ7OvWkb3qMgqTmjzFJjgJwcIpsnC5tc2ObVP2oKdD3rxTygFyN4lK6
uQOqPd1auSJG3uMt892IHO/zSfoHjL6D5L9YVdDWrtRRmB0NjS9LOrH5sRbToFG1
HRvSTWAtZdCMivKieiv6fQ==
-----END PRIVATE KEY-----

        虽然私钥看起来是由一堆随机数据组成的,但是实际上可不是这样,它是有自己的数据结构组成,我们可以通过pkey命令看看:

root@ubuntu:/tmp# openssl pkey -in private.key -text -noout
Private-Key: (2048 bit)
modulus:
    00:a2:14:a8:e3:09:30:88:bf:86:a5:15:7e:ad:13:
    4b:0a:c1:df:28:fd:c1:84:4f:d9:62:97:0e:fb:33:
    74:92:1d:87:fe:f8:47:33:bb:d8:79:cb:82:54:56:
    d2:a6:5d:cf:35:b8:b8:05:59:54:3f:26:f9:2a:4d:
    35:bf:77:e3:fc:15:d5:d4:05:17:d0:11:6d:02:2c:
    a6:9a:dc:e3:5a:3a:75:6d:ad:08:cb:a7:87:98:19:
    06:e1:5e:27:e8:b5:81:a7:9c:35:05:c9:47:72:cb:
    41:2a:a1:b7:4c:26:b4:e2:c4:0e:47:18:01:8e:a1:
    d1:cf:83:0c:f0:e5:d5:64:18:f9:8c:ad:c1:89:8d:
    c6:14:d5:0b:01:8a:46:29:43:68:48:62:ee:6a:95:
    44:b6:06:07:8c:62:19:31:92:cd:3b:89:52:8d:60:
    03:a9:dd:80:f7:a3:06:86:a5:75:33:be:34:e2:d2:
    1d:b6:a3:94:04:c4:4f:0b:57:df:67:23:96:64:c2:
    f2:64:9d:5c:b6:fa:4d:b4:93:31:6a:c1:20:fa:a2:
    17:d5:27:91:84:06:65:12:26:53:84:db:e7:6f:80:
    64:5b:94:48:2b:e4:1c:93:b7:97:dc:30:62:b6:fb:
    8c:7b:36:9e:24:eb:95:d9:89:8f:4e:58:18:b1:cd:
    77:63
publicExponent: 65537 (0x10001)
privateExponent:
    04:da:cf:90:35:57:41:d1:52:cc:21:0f:b1:49:71:
    a6:f9:d5:a0:59:b1:71:30:1f:17:c7:e4:87:fb:ab:
    93:30:d5:40:fa:d8:cf:20:e2:44:0b:a7:74:b5:41:
    0c:00:a5:53:3b:9c:2f:74:d4:84:2b:bb:ac:db:b1:
    2f:71:fc:df:31:1c:3d:84:85:89:12:ec:8b:f3:20:
    6e:65:0d:5e:47:7f:fa:f0:02:e2:6e:bb:2e:00:19:
    e7:a8:35:53:d0:13:f9:1c:41:ae:51:b0:15:2d:27:
    5f:8a:86:7d:fe:6e:ce:98:06:c1:74:63:9f:8d:13:
    46:be:eb:25:50:0d:0b:39:74:12:4c:07:24:e8:2f:
    ae:6f:54:4b:84:79:05:9c:35:45:57:ba:f5:6e:54:
    07:d7:ef:62:fc:a8:d2:bc:c7:98:ae:9e:fe:69:0a:
    a7:38:b1:98:14:19:e8:c9:36:ea:35:76:22:2c:18:
    90:cb:78:5b:20:92:3c:58:4a:0c:40:6c:39:55:58:
    46:86:fa:be:d9:01:14:30:39:3a:8b:a4:27:df:63:
    a4:6d:2a:bb:80:c0:5e:04:62:4d:2f:bb:aa:a6:01:
    92:d7:48:de:56:47:98:87:a1:a0:f0:c2:9a:a2:49:
    8f:a5:22:b6:87:29:57:21:ff:6f:63:c8:d2:af:68:
    51
prime1:
    00:d2:eb:3e:eb:5f:a8:1a:dd:dd:26:19:43:e4:e2:
    f7:51:4d:54:d1:1a:0c:be:ef:85:f4:bd:16:d5:c4:
    96:39:cc:e4:dc:c7:f8:4e:76:7c:d6:7b:33:6c:61:
    23:75:78:2c:76:67:f3:e4:bb:d3:20:f6:49:de:ba:
    8e:94:10:72:30:b5:01:d2:78:a4:b6:4b:b1:01:fc:
    87:3a:28:ba:96:f8:78:13:2b:8d:b0:8b:7a:fe:86:
    eb:11:34:1f:8c:d3:c4:6f:37:5a:b4:b5:5d:08:1f:
    95:df:e9:cc:65:e6:91:a6:15:5f:02:c3:1e:ed:c9:
    29:5a:fe:a7:72:0d:4a:66:1b
prime2:
    00:c4:b9:27:b4:43:ce:60:ed:ce:32:85:d7:fb:05:
    30:fa:bd:5e:ab:92:e0:3a:e5:69:9c:cb:e5:b2:5a:
    e9:3b:36:89:60:61:1c:f9:1c:82:98:e8:fa:9f:a3:
    78:63:2e:ac:b1:e0:b0:be:25:31:96:52:0a:a0:b5:
    a8:3f:a9:50:2d:82:b0:17:76:2c:e8:f3:bb:06:71:
    d8:66:02:23:eb:c0:3c:14:13:42:9c:ad:7e:81:b3:
    2b:91:66:c5:5f:1f:7e:5f:b5:64:85:09:5a:5b:6c:
    46:fe:f2:78:64:2e:10:69:57:46:8a:9a:48:d3:95:
    5a:42:ff:53:c4:f7:af:68:59
exponent1:
    20:f2:fb:0b:4e:10:36:d2:3d:ff:fb:a6:6d:95:3f:
    49:86:29:1f:d9:4f:f0:6b:fe:a3:32:fe:e4:3a:27:
    b5:b3:da:74:db:10:61:41:85:53:04:40:0e:48:46:
    7f:cd:5c:34:cb:1c:80:b9:0e:cc:71:6d:2c:cc:3c:
    05:c9:63:ed:53:f9:8a:e5:a9:e5:88:81:88:6b:e8:
    bc:1f:2c:b6:f4:ed:dd:20:ca:ab:af:be:71:10:a6:
    9c:33:66:52:5b:aa:ae:2d:19:90:6d:5c:b1:2e:2d:
    fd:a2:ca:79:88:c1:6c:0e:9e:9f:11:d8:3d:11:55:
    d2:8f:41:9d:41:92:43:cd
exponent2:
    08:6f:4f:ee:80:c1:c6:92:2b:b7:2a:d9:f9:df:5d:
    1c:43:26:5e:00:ec:30:5a:49:ce:f9:47:1e:00:9b:
    e3:78:11:27:da:c2:1d:44:45:ad:3c:c0:12:3c:36:
    1b:3a:93:19:05:63:4e:a3:d5:9e:76:62:12:45:f7:
    b2:d3:15:a6:fd:e5:82:fc:04:2c:f0:d6:62:0e:5b:
    92:f4:20:8a:29:31:ea:42:71:26:ba:a1:a3:fa:04:
    b2:35:4f:dd:26:42:8a:e4:02:2d:5a:1b:4f:b4:32:
    cf:17:a2:65:d9:3b:c6:e8:81:13:cc:4d:b7:14:be:
    4c:05:1a:98:65:6e:55:f1
coefficient:
    6c:3b:4d:6a:8f:8e:7f:ad:b7:eb:d5:5e:27:8d:da:
    25:fa:a2:2c:26:2b:ae:4a:46:7b:3a:f5:a4:6f:7a:
    8c:82:a4:e6:8f:31:49:8e:02:70:70:8a:6c:9c:2e:
    6d:73:63:9b:54:fd:a8:29:d0:f7:af:14:f2:80:5c:
    8d:e2:52:ba:b9:03:aa:3d:dd:5a:b9:22:46:de:e3:
    2d:f3:dd:88:1c:ef:f3:49:fa:07:8c:be:83:e4:bf:
    58:55:d0:d6:ae:d4:51:98:1d:0d:8d:2f:4b:3a:b1:
    f9:b1:16:d3:a0:51:b5:1d:1b:d2:4d:60:2d:65:d0:
    8c:8a:f2:a2:7a:2b:fa:7d

如果你想提取该私钥文件的公共部分(公钥),我们可以这样干(rsa):

$openssl pkey -in private.key -pubout -out private-public.key
root@ubuntu:/tmp# openssl pkey -in private.key -pubout -out private-public.key
root@ubuntu:/tmp# cat private-public.key 
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAohSo4wkwiL+GpRV+rRNL
CsHfKP3BhE/ZYpcO+zN0kh2H/vhHM7vYecuCVFbSpl3PNbi4BVlUPyb5Kk01v3fj
/BXV1AUX0BFtAiymmtzjWjp1ba0Iy6eHmBkG4V4n6LWBp5w1BclHcstBKqG3TCa0
4sQORxgBjqHRz4MM8OXVZBj5jK3BiY3GFNULAYpGKUNoSGLuapVEtgYHjGIZMZLN
O4lSjWADqd2A96MGhqV1M7404tIdtqOUBMRPC1ffZyOWZMLyZJ1ctvpNtJMxasEg
+qIX1SeRhAZlEiZThNvnb4BkW5RIK+Qck7eX3DBitvuMezaeJOuV2YmPTlgYsc13
YwIDAQAB
-----END PUBLIC KEY-----

        如果像上面这样-----BEGIN PUBLIC KEY-----开始以-----END PUBLIC KEY-----收尾,说明提取导出公钥成功了(如果没有-pubout参数,那么导出的文件内容其实跟原始的私钥文件是一样的,可以通过cat方式看看BEGIN XXX KEY到底是私钥还是公钥)。

        另外一种ECDSA算法的私钥生成流程也是差不多的,只不过需要选择曲线参数,并以此确定私钥的长度(不能随意选择),我们试试(曲线为P-256,也可以叫secp256r1):

$openssl genpkey -out private2.key -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -aes-128-cbc

        OpenSSL支持很多曲线类型(通过openssl ecparam -list_curves查看支持的种类),但是一般都比较建议使用P-256(别名secp256r1或prime256v1)和P-384(secp384r1)为web server生成密钥文件,前者更为推荐。

        目前新加的x25519/x448/ed25519/ed448也被支持,只不过需要加个-algorithm参数进行选择,比如下面的命令会生成ed25519曲线的私钥(有点老的openssl可能不支持这些曲线)。

$openssl genpkey -algorithm ed25519

证书签名请求文件CSR

CSR生成

        有两种方法,各有千秋,其中差别,自个体会。

命令行方法

        私钥准备好了,我们就可以生成一份CSR文件并提供给CA中心得到目标证书了(它包含请求证书的实体的公钥和有关该实体的一些信息。这些数据都将是证书的一部分。CSR总是使用与其携带的公钥相对应的私钥进行签名)。

        生成CSR文件(利用私钥文件)的过程需要我们根据其提示输入一些具体信息(以区别其他的CSR文件),这些信息包括国家代码、省份(或州)、公司名称、组织名称、组织单元名称、邮箱地址等等,但是有一点需要注意,这些信息并不是都需要填写的,有些可以为空(为空的我们不能直接按回车键,而是也要输入一个·,否则openssl会自动填充一个默认值,如果你不想使用默认值的话,那就要输入·),我们来试试。

root@ubuntu:/tmp# openssl req -new -key private.key -out private.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) [AU]:CN
State or Province Name (full name) [Some-State]:Shanghai
Locality Name (eg, city) []:Shanghai
Organization Name (eg, company) [Internet Widgits Pty Ltd]:GD
Organizational Unit Name (eg, section) []:DR
Common Name (e.g. server FQDN or YOUR name) []:mike
Email Address []:.

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:.
An optional company name []:.
root@ubuntu:/tmp# 

        上面我准备的私钥文件不带保护密码,所以没有提示输入密码相关的内容。这里面有个challenge password字段,它是为了吊销证书过程使用的一种保护机制,但一般都不建议使用它,不用管,管了也容易与保护密码(后面还有共享密钥)等概念相混淆,也起不到好的保护作用。

配置文件方法

        除了上面这种比较常见的命令行方式外,我们还可以提前将一些填充信息写到配置文件(可以参考freeRADIUS工程中certs文件夹下提供的配置文件示例),然后在生成CSR时读取配置文件就行,这样也方便后期的更新。

官方提供的一个配置文件内容如下(fd.cnf):

openssl密钥证书管理(Key and Certificate Management),AAA,openssl,ssl,证书,密钥

然后通过下面的命令生成CSR:

$openssl req -new -config fd.cnf -key fd.key -out fd.csr
检查CSR

        在我们将CSR文件提交给CA中心生成证书之前,我们最好先检查下CSR的信息是否正确,以免多次提交,浪费时间浪费资源。效果如下:

root@ubuntu:/tmp# openssl req -text -in private.csr -noout
Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=CN, ST=Shanghai, L=Shanghai, O=GD, OU=DR, CN=mike
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:a2:14:a8:e3:09:30:88:bf:86:a5:15:7e:ad:13:
                    4b:0a:c1:df:28:fd:c1:84:4f:d9:62:97:0e:fb:33:
                    74:92:1d:87:fe:f8:47:33:bb:d8:79:cb:82:54:56:
                    d2:a6:5d:cf:35:b8:b8:05:59:54:3f:26:f9:2a:4d:
                    35:bf:77:e3:fc:15:d5:d4:05:17:d0:11:6d:02:2c:
                    a6:9a:dc:e3:5a:3a:75:6d:ad:08:cb:a7:87:98:19:
                    06:e1:5e:27:e8:b5:81:a7:9c:35:05:c9:47:72:cb:
                    41:2a:a1:b7:4c:26:b4:e2:c4:0e:47:18:01:8e:a1:
                    d1:cf:83:0c:f0:e5:d5:64:18:f9:8c:ad:c1:89:8d:
                    c6:14:d5:0b:01:8a:46:29:43:68:48:62:ee:6a:95:
                    44:b6:06:07:8c:62:19:31:92:cd:3b:89:52:8d:60:
                    03:a9:dd:80:f7:a3:06:86:a5:75:33:be:34:e2:d2:
                    1d:b6:a3:94:04:c4:4f:0b:57:df:67:23:96:64:c2:
                    f2:64:9d:5c:b6:fa:4d:b4:93:31:6a:c1:20:fa:a2:
                    17:d5:27:91:84:06:65:12:26:53:84:db:e7:6f:80:
                    64:5b:94:48:2b:e4:1c:93:b7:97:dc:30:62:b6:fb:
                    8c:7b:36:9e:24:eb:95:d9:89:8f:4e:58:18:b1:cd:
                    77:63
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: sha256WithRSAEncryption
         5c:0b:c1:fd:da:b1:7c:28:93:85:63:a0:13:db:5b:d3:e2:d1:
         d0:95:d5:b1:61:cf:db:f4:d6:d0:b9:5b:4d:05:0f:fb:41:c3:
         9a:78:e4:29:49:ac:0e:3d:30:26:df:0a:a9:73:9a:60:d7:24:
         f6:87:0b:a2:cf:53:1a:ad:a3:66:40:3c:91:b4:a8:f5:98:65:
         cf:91:30:90:94:11:00:79:f8:e5:9b:70:25:1b:b4:05:20:30:
         da:05:1a:f1:71:e3:07:ed:bf:d8:cb:d4:ed:9d:45:89:b8:6b:
         6d:8a:e2:65:49:2d:c5:54:68:37:9f:e6:5d:89:7d:c7:bb:cc:
         6a:1e:0b:ec:84:9a:25:b9:be:3b:bd:46:80:3b:0c:3f:d7:f9:
         d3:ee:22:99:3c:76:3e:08:a0:dd:ce:40:49:21:bc:bb:67:9f:
         4b:2b:79:54:e6:19:f3:22:de:c9:cd:3c:f4:77:37:de:71:c0:
         c4:74:06:d3:16:b1:3e:71:89:ee:ef:57:2a:c0:23:24:65:80:
         eb:f4:2a:1c:ce:3b:92:44:c1:a2:68:26:b8:06:5d:5a:98:81:
         9a:94:1d:87:20:72:c0:6b:16:1d:4e:82:14:b7:4f:0d:fd:0d:
         07:d4:16:d9:38:b7:9c:3b:90:0d:79:c9:fc:71:7f:ba:a5:44:
         98:25:a5:d0
CSR重生

        如果需要更新证书(可能过期或其他原因),按照常规流程,我们得再一次生成私钥,再生成CSR,重新输入各种信息,再提交CSR,但如果之前填写的信息都一样不用变动呢,那么再按流程走稍显繁琐了,此种情况,我们可以通过利用之前的私钥及证书文件重新导出一个全新的CSR文件:

openssl x509 -x509toreq -in client.crt -out client.csr -signkey client.key

私钥最好是每次都重新生成一次(毕竟也不麻烦),既增加了安全系数也获得了心安,何乐不为。

一键生成私钥和CSR

        上文所介绍的都是按部就班的流程,先生成私钥再根据此私钥生成CSR,那么我们有没有一步到位的命令呢,还真有,下面的命令记好:

$openssl req -newkey rsa:2048 -keyout client.key -out client.csr -nodes

注意最后一个参数-nodes,意思是不用保护密码(给私钥),如果需要则将-nodes参数去掉即可。

自签名证书

        自签名,顾名思义,自己给自己的CSR文件进行签名。当我们自己在配置TLS server(自用)或想快速测试一些认证功能时,一般都可以使用自签名证书来布置。

        我们来用之前生成的private.key和private.csr文件生成我们自签名证书client.crt。

root@ubuntu:/tmp# openssl x509 -req -days 365 -in private.csr -signkey private.key -out client.crt
Signature ok
subject=/C=CN/ST=Shanghai/L=Shanghai/O=GD/OU=DR/CN=mike
Getting Private key
root@ubuntu:/tmp# 
root@ubuntu:/tmp# cat client.crt 
-----BEGIN CERTIFICATE-----
MIIDNDCCAhwCCQDrUJJRjOrRSzANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQGEwJD
TjERMA8GA1UECAwIU2hhbmdoYWkxETAPBgNVBAcMCFNoYW5naGFpMQswCQYDVQQK
DAJHRDELMAkGA1UECwwCRFIxDTALBgNVBAMMBG1pa2UwHhcNMjQwNDExMDMxNzIw
WhcNMjUwNDExMDMxNzIwWjBcMQswCQYDVQQGEwJDTjERMA8GA1UECAwIU2hhbmdo
YWkxETAPBgNVBAcMCFNoYW5naGFpMQswCQYDVQQKDAJHRDELMAkGA1UECwwCRFIx
DTALBgNVBAMMBG1pa2UwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCi
FKjjCTCIv4alFX6tE0sKwd8o/cGET9lilw77M3SSHYf++Eczu9h5y4JUVtKmXc81
uLgFWVQ/JvkqTTW/d+P8FdXUBRfQEW0CLKaa3ONaOnVtrQjLp4eYGQbhXifotYGn
nDUFyUdyy0EqobdMJrTixA5HGAGOodHPgwzw5dVkGPmMrcGJjcYU1QsBikYpQ2hI
Yu5qlUS2BgeMYhkxks07iVKNYAOp3YD3owaGpXUzvjTi0h22o5QExE8LV99nI5Zk
wvJknVy2+k20kzFqwSD6ohfVJ5GEBmUSJlOE2+dvgGRblEgr5ByTt5fcMGK2+4x7
Np4k65XZiY9OWBixzXdjAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFNpS8j4jNHM
IMVVd4DRT3NUPNTVXGYVn0KfX4F0laO7PDyGRRpJQwFnd01X1ca6xdNJcjCvItZd
EnaQxy+RwhM9cvMVHdiLitZa/UQJ8/wtEnIsbZLIp4VEIjVPk1FArESOXlV9LoUE
qefqJhCQw4IMMv8OD8rK7nNeLnpLhano5xXlXZZgdY61//rD29de1rdna99BWMXs
RChdNJTu8SGoEgYYfOfwQO4hu2Fd/WWwDel1ME8JXNY1esF+Ccg4x+Hy6zcZhQ9t
fpHA0EFr6oltttEli/ZIzsZDhJvjB4Rhpj/b6Ih71rlHqRvddS0vCfLMRKiI2I2i
M5Co7S3VMXg=
-----END CERTIFICATE-----

我们还可以在未准备好CSR文件的情况,去生成自签名证书(记住是自签名哈),命令如下:

$openssl req -new -x509 -days 365 -key private.key -out client1.crt
root@ubuntu:/tmp# openssl req -new -x509 -days 365 -key private.key -out client1.crt
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) [AU]:

可以看到,还是需要输入一些信息的(这些信息很重要,不可能真正省略嘛),还有另外一个办法一次性将需要的信息填充出来(-subj,借鉴了配置文件的方法),如下:

$openssl req -new -x509 -days 365 -key private.key -out client1.crt -subj "/C=CN/L=Shanghai/O=GD/"

创建对多个域名有效的证书

        默认情况,一个证书中的common name只对应一个域名,那么如果有个不一样的域名的网站,那就需要另外一个证书(即使这俩网站是同一个网站,比如www.feistyduck.com和feistyduck.com,还有www.blumitek.com和www.blumitech.com这样的情况),理论上这样没错,但实际使用中的确有一些不便,有没有什么办法能让一张证书对应多个主机名呢?

        不但有,还有两种方法。

        第一种方法是使用名为Subject Alternative Name(SAN)的X.509扩展名列出所有需要的主机名(域名)。第二种是使用通配符。在更方便的时候,也可以使用这两种方法的组合。在实践中,对于大多数网站,我们可以指定一个裸域名和一个通配符来覆盖所有子域。

        演练一下。

        我们创建一份文本文件fd.ext,里面写上所有可能的域名,再结合下通配符,内容如下:

subjectAltName = DNS:*.feistyduck.com, DNS:feistyduck.com

我们再来使用x509命令去生成一张证书,但是我们要添加-extfile参数来指定读取ext文件:

$openssl x509 -req -days 365 -in private.csr -signkey private.key -out client.crt -extfile fd.ext

我们在证书生成后检查下内容信息有什么变化。

查看证书

        证书可不像私钥文件(文本)那样可以直接用cat方式浏览,但我们可以使用x509命令进行查看。

$ openssl x509 -text -in fd.crt -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            76:bc:fb:f6:06:0e:61:eb:99:5e:83:ea:ef:92:0b:32:4f:fd:3b:51
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: C = GB, L = London, O = Feisty Duck Ltd, CN = www.feistyduck.com
        Validity
            Not Before: Aug 15 09:31:54 2020 GMT
            Not After : Aug 15 09:31:54 2021 GMT
        Subject: C = GB, L = London, O = Feisty Duck Ltd, CN = www.feistyduck.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:8a:d5:de:69:30:c7:77:b0:a0:54:f7:b3:34:9a:
                    96:1c:23:81:e3:9c:0c:81:a6:8a:a5:14:76:f4:4c:
                    b3:10:cb:ee:50:d1:ea:70:e9:7f:8f:75:67:f9:12:
                    83:b0:11:e7:6c:64:de:bc:af:bd:3f:43:da:b8:41:
                    96:75:34:63:85
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Subject Alternative Name: 
                DNS:*.feistyduck.com, DNS:feistyduck.com
    Signature Algorithm: ecdsa-with-SHA256
         30:45:02:20:4d:36:34:cd:e9:3e:df:18:52:e7:74:c4:a1:97:
         91:6a:e7:c1:6d:12:01:63:d1:fd:90:28:32:70:24:5c:be:35:
         02:21:00:bd:02:64:c9:8b:27:8f:79:c7:a4:41:7c:31:2f:98:
         29:3e:db:8c:f3:f1:d7:bb:fa:fe:95:48:be:16:e1:ab:1b

有看到下面的内容吧。

openssl密钥证书管理(Key and Certificate Management),AAA,openssl,ssl,证书,密钥

        自签名证书仅仅包含了证书数据的最基本部分,一般来说证书主体里面是要添加签名信息的。而来自CA中心颁发的证书则包含了更多的信息(通过X509扩展机制)。

检查公共证书

        下面是一个公共证书的部分内容(此一节内容全翻译自原文):

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            03:5e:50:53:75:08:1a:f2:7d:27:64:4f:d5:6f:1a:02:07:89
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
        Validity
            Not Before: Aug  2 23:10:45 2020 GMT
            Not After : Oct 31 23:10:45 2020 GMT
        Subject: CN = www.feistyduck.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:c8:14:4f:33:9a:db:bb:e7:e3:78:93:46:5d:56:
                    a7:bc:58:86:43:dc:ea:c1:01:52:4b:0f:20:b7:38:
                    [...]
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            [...]

       可以看到其与自签名证书的内容看起来差不多,但由CA中心颁发的公共证书与自签名证书还是有几点区别,一个是拥有不同的父级(如颁发者信息所示Issuer),还有一个就是X.509扩展部分。

非CA颁发的证书,字段X509v3 Basic Constraints可能有可能无,如果有,它应该是这样:

openssl密钥证书管理(Key and Certificate Management),AAA,openssl,ssl,证书,密钥

 可以看到,CA:FALSE。

openssl密钥证书管理(Key and Certificate Management),AAA,openssl,ssl,证书,密钥

        密钥使用(KU)和扩展密钥使用(EKU)扩展限制了证书的用途。如果存在这些扩展,则只允许列出的用途。如果扩展不存在,则没有使用限制。在上图看到的是典型的web服务器证书,例如,它不允许代码签名。

openssl密钥证书管理(Key and Certificate Management),AAA,openssl,ssl,证书,密钥

        CRL分发点扩展列出了可以在其中找到CA的证书吊销列表(CRL)信息的地址。在需要吊销证书的情况下,此信息非常重要。CRL是CA签署的已吊销证书列表,每隔一定时间(例如七天)发布。

openssl密钥证书管理(Key and Certificate Management),AAA,openssl,ssl,证书,密钥 

        证书策略扩展用于指示颁发证书所依据的策略。例如,我们可以在这里找到用于确定所有者身份的验证类型的指示。可以找到扩展验证(EV)指标(如上图所示)。这些指示符采用唯一对象标识符(OID)的形式,其中一些是通用的,另一些是颁发CA特有的。OID 2.23.140.1.2.1表示域验证证书。此外,此扩展通常包含一个或多个证书实践声明(CPS)点,这些点通常是网页或PDF文档。 

openssl密钥证书管理(Key and Certificate Management),AAA,openssl,ssl,证书,密钥

        授权信息访问(AIA)扩展通常包含两条重要信息。首先,它列出了CA的在线证书状态协议(OCSP)响应程序的地址,该响应程序可用于实时检查证书吊销。扩展还可能包含一个链接,指向可以找到颁发者证书(链中的下一个证书)的位置。如今,服务器证书很少由受信任的根证书直接签名,这意味着用户必须在其配置中包含一个或多个中间证书。错误很容易犯,会使证书失效。一些客户端将使用此扩展中提供的信息来修复不完整的证书链,但许多客户端不会。

openssl密钥证书管理(Key and Certificate Management),AAA,openssl,ssl,证书,密钥 

        主题密钥标识符和权威密钥标识符扩展分别建立唯一的主题和权威密钥标识。证书的颁发机构密钥标识符扩展中指定的值必须与颁发证书的使用者密钥标识符扩展指定的值匹配。这些信息在证书路径构建过程中非常有用,在这个过程中,客户端试图找到从叶(服务器)证书到受信任根的所有可能路径。证书颁发机构通常会将一个私钥与多个证书一起使用,该字段允许软件可靠地识别哪个证书可以与哪个密钥匹配。在现实世界中,服务器提供的许多证书链都是无效的,但这一事实经常被忽视,因为浏览器能够找到替代的信任路径。

openssl密钥证书管理(Key and Certificate Management),AAA,openssl,ssl,证书,密钥 

        Subject Alternative Name扩展名用于列出证书有效的所有主机名(域名)。这个扩展过去是可选的;如果不存在,客户端将返回使用公共名称(CN)中提供的信息,该名称是Subject字段的一部分。如果存在扩展,则在验证过程中会忽略CN字段的内容。 

openssl密钥证书管理(Key and Certificate Management),AAA,openssl,ssl,证书,密钥

        最后,最新添加的是证书透明性(CT)扩展,用于将日志记录证明携带到各种公共CT日志中。根据证书的生存期,您可以看到两到五个签名证书时间戳(SCT)。对于承认证书有效所必需的SCT的数量和类型,没有一套统一的要求。从技术上讲,这取决于每个客户指定他们期望的内容。在实践中,Chrome是第一个需要CT的浏览器,其他客户端可能也会效仿它。 

密钥和证书的格式转换

        在刚开始接触证书认证的时候,百度了很多内容,尤其是被各种乱七八糟的格式搞自闭,动不动就报证书格式问题,根据百度到的转换命令强制转换 之后依然是各种问题,人生至郁时刻。

证书格式

Binary(DER)

        包含使用DER ASN.1编码的原始形式的X.509证书。

ASCII (PEM)

        包含使用base64编码的DER证书,以-----BEGIN CERTIFICATE-----开头以-----END CERTIFICATE-----收尾,在一个文件只包含一份证书的这种情况下比较常见(尽管一些程序允许一个文件可以包含多份证书)。举个例子,较旧的Apache web服务器版本要求服务器证书单独存在于一个文件中,所有中间证书一起存在于另一个文件。

PKCS #7

        RFC 2315中定义的一种为传输签名或加密数据而设计的复杂格式。它通常与.p7b和.p7c扩展一起使用,并且可以根据需要包括整个证书链。Java的keytool实用程序支持这种格式。

PKCS #12 (PFX)

        见下文解释,主要是Windows平台在用,比如在window server上生成导出密钥和证书时,可能会将二者共同导出到一个文件中(可选加密密码),这个文件就是.pfx后缀的。

密钥格式

旧版OpenSSL

        包含一个原始形式的私钥,使用DER ASN.1编码。从历史上看,OpenSSL使用基于PKCS#1的格式。现在,如果使用正确的命令(即genpkey),OpenSSL默认为PKCS#8。

ASCII (PEM)

        包含一个base64编码的DER密钥,有时还包含额外的元数据(例如,用于密码保护的算法)。页眉和页脚中(-----xxx-----这个东西)的文本可能不同,具体取决于所使用的基本密钥格式。

PKCS #8

       私钥存储的新默认格式(刚开始我们生成的私钥就是这种格式)。PKCS#8是在RFC 5208中定义的。如果出于任何原因需要从PKCS#8转换为传统格式,请使用pkcs8命令。   

PKCS #12 (PFX)

        一种复杂的格式,可以存储和保护服务器密钥以及整个证书链。它通常与.p12和.pfx扩展名一起使用。此格式通常用于Microsoft产品,但也用于客户端证书。如今,PFX名称被用作PKCS#12的同义词,尽管PFX在很久以前引用了一种不同的格式(PKCS#11的早期版本)。你不太可能在任何地方遇到旧版本。

格式转换

PEM-DER

        这两种格式的证书我们使用x509命令工具进行转换。

PEM->DER

$ openssl x509 -inform PEM -in fd.pem -outform DER -out fd.der

DER->PEM

$ openssl x509 -inform DER -in fd.der -outform PEM -out fd.pem

        对于这两种格式的私钥互转的语法也是一样的,只是针对不同加密算法的密钥我们要使用不同的命令(替换x509),如rsa(RSA密钥)和dsa(DSA密钥)。如果是PKCS #8格式的密钥呢可以使用pkey命令。

PKCS #12 (PFX)

        将PEM格式的密钥和证书转换为PKCS#12只需要一个命令。以下示例将密钥(fd.key)、证书(fd.crt)和中间证书(fd-chain.crt)转换为等效的单个PKCS#12文件:

$ openssl pkcs12 -export -name "My Certificate" -out fd.p12 -inkey fd.key -in fd.crt -certfile fd-chain.crt

        反向转换则比较麻烦了。可以使用一个命令,首先得到一个包含全部内容的文件:

$ openssl pkcs12 -in fd.p12 -out fd.pem -nodes

然后我们需要手动打开fd.pem文件(比如可以通过gedit或者notepad++),将其拆分为单独的密钥、证书和中间证书文件,在每部分内容之前我们会看到一些额外的信息,比如像下面这样的:

Bag Attributes
    localKeyID: E3 11 E4 F1 2C ED 11 66 41 1B B8 83 35 D2 DD 07 FC DE 28 76
subject=/1.3.6.1.4.1.311.60.2.1.3=GB/2.5.4.15=Private Organization/serialNumber=06694169/C=GB/ST=London/L=London/O=Feisty Duck Ltd/CN=www.feistyduck.com
issuer=/C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./OU=http://certificates.starfieldtech.com/repository/CN=Starfield Secure Certification Authority
-----BEGIN CERTIFICATE-----
MIIF5zCCBM+gAwIBAgIHBG9JXlv9vTANBgkqhkiG9w0BAQUFADCB3DELMAkGA1UE
BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAj
[...]

这个额外的元数据对于快速识别证书非常方便。显然,我们应该确保主证书文件包含叶服务器证书,而不是其他内容。此外,还应确保以正确的顺序提供中间证书,并在已签名证书之后提供颁发证书。如果看到一个自签名的根证书,则应删除它或将其存储在其他地方,它不应该被包含进入证书链。(是不是很有挑战力度++)

        除了手动操作外,我们也可以利用openssl提供的命令来分离,下面的三行命令即分别分离出私钥文件fd.key、证书文件fd.crt、中间链证书fd-chain.crt:

$ openssl pkcs12 -in fd.p12 -nocerts -out fd.key -nodes
$ openssl pkcs12 -in fd.p12 -nokeys -clcerts -out fd.crt
$ openssl pkcs12 -in fd.p12 -nokeys -cacerts -out fd-chain.crt

        虽然通过命令可以比较方便的进行分离提取,但是我们还是要仔细检查每一份文件,如果有多余的元数据在里面(比如自签名证书),我们要当机立断删除它们。

PKCS #7

PEM->PKCS #7

$ openssl crl2pkcs7 -nocrl -out fd.p7b -certfile fd.crt -certfile fd-chain.crt

PKCS #7->PEM

$openssl pkcs7 -in fd.p7b -print_certs -out fd.pem

与PKCS #12 (PFX)的转换一样,我们还是需要手动检查fd.pem以剔除不需要的信息。

关于密钥和证书方面的内容,本篇大致陈述这么些。文章来源地址https://www.toymoban.com/news/detail-849451.html

到了这里,关于openssl密钥证书管理(Key and Certificate Management)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Java可执行命令】(十一)Java 密钥库和证书管理工具keytool:玩转密钥库和证书管理,深入解析keytool工具的应用与技巧~

    Java的 keytool 命令是用于管理和操作Java密钥库( KeyStore )的工具。它的设计目的是为了方便Java开发人员生成、管理和操作数字证书,以及实现对保护资源进行安全访问的加密和身份验证。 🔍 一些相关概念? 密钥库(KeyStore):它是存储密钥和证书的容器,可以包含私钥、公

    2024年02月12日
    浏览(45)
  • ZA303学习笔记六管理应用程序的安全(密钥保管库,托管标识,管理应用程序,CA证书)

    密钥保管库和 VM 必须位于同一 Azure 区域和订阅中。 Azure Key Vault是一个用于安全地存储和访问机密的工具。机密是你希望严格控制对其的访问的任何东西,例如API密钥、密码或证书。保管库是机密的逻辑组。 租户:租户是拥有和管理特定的Microsoft云服务实例的组织。它通常用

    2024年02月04日
    浏览(80)
  • 安全可信 | 天翼云自研密钥管理系统(KMS)获得《商用密码产品认证证书》!

    近日, 天翼云自研密钥管理系统( KMS ) 通过国家密码管理局安全性审查,符合 GM/T 0051 《密码设备管理 对称密钥管理技术规范》要求, 获得由国家密码管理局商用密码检测中心颁发的《商用密码产品认证证书》。 《商用密码产品认证证书》具有权威性及唯一性,该证书的

    2024年02月07日
    浏览(69)
  • 网安笔记 08 key management

    Key Management —— 不考 特点: 两个相邻点之间数据进行加密保护 不同节点对密码机和Key不一定同 中间节点上,先解密后加密 报文报头可一起加密 节点内部,消息以明文存在 密钥分配困难 保密及需求数量大 缺点: 加密机数量为 n 2 n^2 n 2 相关 相同点 中间节点对消息解密 ,

    2024年02月11日
    浏览(32)
  • Backtrader 文档学习-Order Management and Execution

    本章提供了关于order的详细功能测试用例,很好很重要。 最后的示例部分,详细分析总结了不同参数的效果和输出。 如果不能模拟订单交易回测就不会完整。为此,平台中提供了以下功能, 对于订单管理3个基本要素: buy sell cancel 对order执行逻辑,有以下类型: Market Close Li

    2024年01月24日
    浏览(35)
  • Git 本地配置SSH Key(密钥)

    Git配置 打开Git Bash 配置你的用户名和邮箱 git config --global user.name “zhangsan” git config --global user.email “zhangsan@xxxx.com” 生成SSH key ssh-keygen -t rsa -C “zhangsan@xxxx.com” 获取SSH Key 根据命令行提示,获取以ssh-rsa的字符串(包括ssh-rsa) 按键”回车键“ 生成了SSH Key(密钥)如下图所示

    2024年04月27日
    浏览(37)
  • curl请求https证书过期的问题:SSL certificate problem: certificate has expired

    写了两个系统,系统A使用 curl 去请求系统B,但是不知道为什么会报错 SSL certificate problem: certificate has expired 系统A使用了 https 但是系统B没有使用 https 系统A的SSL并未过期,而且在两个系统在同一台服务器时并未报错,所以不是SSL证书的问题 解决办法: 关闭curl对证书验证,可

    2024年02月16日
    浏览(46)
  • Web 安全之证书透明(Certificate Transparency)详解

    目录 证书透明性的概念 数字证书和颁发机构 证书透明的起源 证书透明的工作原理 证书透明的实现方法 证书透明的优点 浏览器和客户端对证书透明的支持情况 小结 证书透明(Certificate Transparency, CT)是网络安全领域中的一个重要概念,是一个针对数字证书的公开监督系统,

    2024年02月05日
    浏览(29)
  • 【阅读笔记】Blockchain management and ML adaptation for IoT environment in 5G and beyond ...

    本文是一篇CCF C类文章,作者来自印度旁遮普邦帕蒂拉塔帕工程技术学院计算机科学与工程系 🙋‍♂️张同学 📧zhangruiyuan@zju.edu.cn 有问题请联系我~ 5G 和 B5G有什么区别? 答:5G主要解决了我们熟悉的高清视频、传输速率等问题;而B5G(Beyond-5G)将解决一些应用场景与技术的完

    2023年04月09日
    浏览(50)
  • 如何使用Python获取SAP Temporary key 临时密钥

    SAP 临时密钥是用于激活 SAP 软件的一种许可证,只能在有限的时间内使用。这些密钥可用于评估目的或在系统迁移期间使用。它们是临时解决方案,通常在一定时间后过期。 临时密钥: 如果创建永久许可证密钥时出现任何错误,SAP支持门户网站提供临时的Business Objects许可证密

    2024年02月12日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包