诺亚方舟

沉淀

RSA非对称加密学习

对于RSA加密,我们利用openssl来生成我们需要的公钥私钥证书等等,在介绍openssl常见的几个功能前,我们先来了解几个术语,

1、私钥编码格式:指的是PKCS#系列的编码,私钥不同的编码会对应着不同的证书类型,但是对于公钥而言是没有编码区分的,不管密钥编码格式如何,对应的都是同一个公钥。

2、私钥加密格式:私钥加密格式指的是aes256之类的算法,还可以对密钥加入口令,这样每次私钥都需要输入这串口令确认才能使用。

3、什么是证书;这里我们的证书指的是数字证书,x509既是数字证书的规范,PKCS#1~PKCS#15是证书的具体实现形式,证书可以理解成公钥的一种封装,部分形式(P12)的证书还会包括有公钥私钥,我们可以在证书中提取出公钥,也可以用证书替代公钥参与签名、加密。证书中提取公钥命令:

1
openssl x509 -outform PEM -in xxx.crt -pubkey -out xxx.pubkey

一、密钥、证书请求、证书概要说明

在证书申请签发过程中,客户端涉及到密钥、证书请求、证书这几个概念,初学者可能会搞不清楚三者的关系,网上有的根据后缀名来区分三者,更让人一头雾水。我们以申请证书的流程说明三者的关系。客户端(相对于CA)在申请证书的时候,大体上有三个步骤:

第一步:生成客户端的密钥,即客户端的公私钥对,且要保证私钥只有客户端自己拥有。

第二步:以客户端的密钥和客户端自身的信息(国家、机构、域名、邮箱等)为输入,生成证书请求文件(csr文件)。其中客户端的公钥和客户端信息是明文保存在证书请求文件中的,而客户端私钥的作用是对客户端公钥及客户端信息做签名,自身是不包含在证书请求中的。然后把证书请求文件发送给CA机构。

第三步:CA机构接收到客户端的证书请求文件后,首先校验其签名,然后审核客户端的信息,最后CA机构使用自己的私钥为证书请求文件签名,生成证书文件,下发给客户端。此证书就是客户端的身份证,来表明用户的身份。

至此客户端申请证书流程结束,其中涉及到证书签发机构CA,CA是被绝对信任的机构。如果把客户端证书比作用户身份证,那么CA就是颁发身份证的机构,我们以https为例说明证书的用处。

为了数据传输安全,越来越多的网站启用https。在https握手阶段,服务器首先把自己的证书发送给用户(浏览器),浏览器查看证书中的发证机构,然后在机器内置的证书中(在PC或者手机上,内置了世界上著名的CA机构的证书)查找对应CA证书,然后使用内置的证书公钥校验服务器的证书真伪。如果校验失败,浏览器会提示服务器证书有问题,询问用户是否继续。

例如12306网站,它使用的自签名的证书,所以浏览器会提示证书有问题,在12306的网站上有提示下载安装根证书,其用户就是把自己的根证书安装到用户机器的内置证书中,这样浏览器就不会报证书错误。但是注意,除非特别相信某个机构,否则不要在机器上随便导入证书,很危险。

二、文件类型说明

后缀名 文件类型
pem  采用 PEM 编码格式的 X.509 证书的文件扩展名,ASCII编码,一般常见于自建证书文件后缀
der  采用 DER 编码格式的 X.509 证书的文件扩展名,二进制编码,一般常见于自建证书文件后缀
crt  certificate 的缩写,常见于类 UNIX 系统,有可能是 PEM 编码,也有可能是 DER 编码,但绝大多数情况下此格式证书都是采用 PEM 编码
cer 也是 certificate 的缩写,常见于 Windows 系统,同样地,可能是 PEM 编码,也可能是 DER 编码,但绝大多数情况下此格式证书都是采用 DER 编码;
csr   Certificate Signing Request 的缩写,即证书签名请求,它并不是证书的格式,而是用于向权威证书颁发机构(Certificate Authority, CA)获得签名证书的申请,其核心内容包含一个 RSA 公钥和其他附带信息
key  通常用来存放一个 RSA 公钥或者私钥,它并非 X.509 证书格式,编码同样可能是 PEM,也可能是 DER
p12  也写作 .pfx,全称:PKCS #12,是公钥加密标准(Public Key Cryptography Standards,PKCS)系列的一种,它定义了描述个人信息交换语法(Personal Information Exchange Syntax)的标准,可以用来将包含了公钥的 X.509 证书和证书对应的私钥以及其他相关信息打包,进行交换。简单理解:一份 .p12 文件 = X.509 证书+私钥
pem

三、openssl创建密钥与自建证书

默认情况下,openssl 输出格式为 PKCS#1-PEM,注意,我们只要有私钥便可以生成所有内容,包括公钥、自建证书等文件,甚至是转换密钥格式。

生成RSA私钥(无加密)

1
openssl genrsa -out rsa_private.key 2048

生成RSA公钥

1
openssl rsa -in rsa_private.key -pubout -out rsa_public.key

生成RSA私钥(使用aes256加密)

1
openssl genrsa -aes256 -passout pass:111111 -out rsa_aes_private.key 2048

其中 passout 代替shell 进行密码输入,否则会提示输入密码;

生成加密后的内容如:

1
2
3
4
5
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,5584D000DDDD53DD5B12AE935F05A007
Base64 Encoded Data
-----END RSA PRIVATE KEY-----

此时若生成公钥,需要提供密码

1
openssl rsa -in rsa_aes_private.key -passin pass:111111 -pubout -out rsa_public.key

私钥转非加密

1
openssl rsa -in rsa_aes_private.key -passin pass:111111 -out rsa_private.key

私钥转加密

1
openssl rsa -in rsa_private.key -aes256 -passout pass:111111 -out rsa_aes_private.key

私钥PEM转DER

1
openssl rsa -in rsa_private.key -outform der-out rsa_aes_private.der

查看私钥明细(使用-pubin参数可查看公钥明细)

1
openssl rsa -in rsa_private.key -noout -text

私钥PKCS#1转PKCS#8

1
openssl pkcs8 -topk8 -in rsa_private.key -passout pass:111111 -out pkcs8_private.key

其中-passout指定了密码,输出的pkcs8格式密钥为加密形式,pkcs8默认采用des3 加密算法,内容如下:

1
2
3
-----BEGIN ENCRYPTED PRIVATE KEY-----
Base64 Encoded Data
-----END ENCRYPTED PRIVATE KEY-----

使用-nocrypt参数可以输出无加密的pkcs8密钥,如下:

1
2
3
-----BEGIN PRIVATE KEY-----
Base64 Encoded Data
-----END PRIVATE KEY-----

生成 RSA 私钥和自签名证书

1
openssl req -newkey rsa:2048 -nodes -keyout rsa_private.key -x509 -days 365 -out cert.crt

req是证书请求的子命令,-newkey rsa:2048 -keyout private_key.pem 表示生成私钥(PKCS8格式),-nodes 表示私钥不加密,若不带参数将提示输入密码;

-x509表示输出证书,-days365 为有效期,此后根据提示输入证书拥有者信息;

若执行自动输入,可使用-subj选项:

1
openssl req -newkey rsa:2048 -nodes -keyout rsa_private.key -x509 -days 365 -out cert.crt -subj "/C=CN/ST=GD/L=SZ/O=vihoo/OU=dev/CN=vivo.com/emailAddress=yy@vivo.com"

使用 已有RSA 私钥生成自签名证书

1
openssl req -new -x509 -days 365 -key rsa_private.key -out cert.crt

-new 指生成证书请求,加上-x509 表示直接输出证书,-key 指定私钥文件,其余选项与上述命令相同

使用 RSA私钥生成 CSR 签名请求

1
2
openssl genrsa -aes256 -passout pass:111111 -out server.key 2048
openssl req -new -key server.key -out server.csr

此后输入密码、server证书信息完成,也可以命令行指定各类参数,此时生成的 csr签名请求文件可提交至 CA进行签发

1
openssl req -new -key server.key -passin pass:111111 -out server.csr -subj "/C=CN/ST=GD/L=SZ/O=vihoo/OU=dev/CN=vivo.com/emailAddress=yy@vivo.com"

查看CSR 的细节

1
2
3
4
5
6
cat server.csr
-----BEGIN CERTIFICATE REQUEST-----
Base64EncodedData
-----END CERTIFICATE REQUEST-----
 
openssl req -noout -text -in server.csr

使用 CA 证书及CA密钥 对请求签发证书进行签发,生成 x509证书

1
openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -passin pass:111111 -CAcreateserial -out server.crt

查看证书细节

1
openssl x509 -in cert.crt -noout -text

转换证书编码格式

1
openssl x509 -in cert.cer -inform DER -outform PEM -out cert.pem

将 pem 证书和私钥转 pkcs#12 证书,其中-export指导出pkcs#12 证书,-inkey 指定了私钥文件,-passin 为私钥(文件)密码(nodes为无加密),-password 指定 p12文件的密码(导入导出)

1
openssl pkcs12 -export -in server.crt -inkey server.key -passin pass:111111 -password pass:111111 -out server.p12

将 pem 证书和私钥/CA 证书 合成pkcs#12 证书,其中-chain指示同时添加证书链,-CAfile 指定了CA证书,导出的p12文件将包含多个证书。(其他选项:-name可用于指定server证书别名;-caname用于指定ca证书别名)

1
2
openssl pkcs12 -export -in server.crt -inkey server.key -passin pass:111111 \
    -chain -CAfile ca.crt -password pass:111111 -out server-all.p12

pcks#12 提取PEM文件(含私钥),其中-password 指定 p12文件的密码(导入导出),-passout指输出私钥的加密密码(nodes为无加密)

导出的文件为pem格式,同时包含证书和私钥(pkcs#8):

1
openssl pkcs12 -in server.p12 -password pass:111111 -passout pass:111111 -out out/server.pem
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Bag Attributes
    localKeyID: 97 DD 46 3D 1E 91 EF 01 3B 2E 4A 75 81 4F 11 A6 E7 1F 79 40 
subject=/C=CN/ST=GD/L=SZ/O=vihoo/OU=dev/CN=vihoo.com/emailAddress=yy@vihoo.com
issuer=/C=CN/ST=GD/L=SZ/O=viroot/OU=dev/CN=viroot.com/emailAddress=yy@viroot.com
-----BEGIN CERTIFICATE-----
MIIDazCCAlMCCQCIOlA9/dcfEjANBgkqhkiG9w0BAQUFADB5MQswCQYDVQQGEwJD
1LpQCA+2B6dn4scZwaCD
-----END CERTIFICATE-----
Bag Attributes
    localKeyID: 97 DD 46 3D 1E 91 EF 01 3B 2E 4A 75 81 4F 11 A6 E7 1F 79 40 
Key Attributes: <No Attributes>
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDC/6rAc1YaPRNf
K9ZLHbyBTKVaxehjxzJHHw==
-----END ENCRYPTED PRIVATE KEY-----

仅提取私钥

1
openssl pkcs12 -in server.p12 -password pass:111111 -passout pass:111111 -nocerts -out out/key.pem

仅提取证书(所有证书)

1
 openssl pkcs12 -in server.p12 -password pass:111111 -nokeys -out out/key.pem

仅提取ca证书

1
openssl pkcs12 -in server-all.p12 -password pass:111111 -nokeys -cacerts -out out/cacert.pem

仅提取server证书

1
openssl pkcs12 -in server-all.p12 -password pass:111111 -nokeys -clcerts -out out/cert.pem

openssl命令参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
1. openssl list-standard-commands(标准命令)
    1) asn1parse: asn1parse用于解释用ANS.1语法书写的语句(ASN一般用于定义语法的构成) 
    2) ca: ca用于CA的管理 
    openssl ca [options]:
        2.1) -selfsign
        使用对证书请求进行签名的密钥对来签发证书。即"自签名",这种情况发生在生成证书的客户端、签发证书的CA都是同一台机器(也是我们大多数实验中的情况),我们可以使用同一个
密钥对来进行"自签名"
        2.2) -in file
        需要进行处理的PEM格式的证书
        2.3) -out file
        处理结束后输出的证书文件
        2.4) -cert file
        用于签发的根CA证书
        2.5) -days arg 
        指定签发的证书的有效时间
        2.6) -keyfile arg   
        CA的私钥证书文件
        2.7) -keyform arg
        CA的根私钥证书文件格式:
            2.7.1) PEM
            2.7.2) ENGINE 
        2.8) -key arg   
        CA的根私钥证书文件的解密密码(如果加密了的话)
        2.9) -config file    
        配置文件
    example1: 利用CA证书签署请求证书
    openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key  
 
    3) req: X.509证书签发请求(CSR)管理
    openssl req [options] outfile
        3.1) -inform arg
        输入文件格式
            3.1.1) DER
            3.1.2) PEM
        3.2) -outform arg   
        输出文件格式
            3.2.1) DER
            3.2.2) PEM
        3.3) -in arg
        待处理文件
        3.4) -out arg
        待输出文件
        3.5) -passin        
        用于签名待生成的请求证书的私钥文件的解密密码
        3.6) -key file
        用于签名待生成的请求证书的私钥文件
        3.7) -keyform arg  
            3.7.1) DER
            3.7.2) NET
            3.7.3) PEM
        3.8) -new
        新的请求
        3.9) -x509          
        输出一个X509格式的证书 
        3.10) -days
        X509证书的有效时间  
        3.11) -newkey rsa:bits 
        生成一个bits长度的RSA私钥文件,用于签发  
        3.12) -[digest]
        HASH算法
            3.12.1) md5
            3.12.2) sha1
            3.12.3) md2
            3.12.4) mdc2
            3.12.5) md4
        3.13) -config file   
        指定openssl配置文件
        3.14) -text: text显示格式
    example1: 利用CA的RSA密钥创建一个自签署的CA证书(X.509结构) 
    openssl req -new -x509 -days 3650 -key server.key -out ca.crt 
    example2: 用server.key生成证书签署请求CSR(这个CSR用于之外发送待CA中心等待签发)
    openssl req -new -key server.key -out server.csr
    example3: 查看CSR的细节
    openssl req -noout -text -in server.csr
 
    4) genrsa: 生成RSA参数
    openssl genrsa [args] [numbits]
        [args]
        4.1) 对生成的私钥文件是否要使用加密算法进行对称加密:
            4.1.1) -des: CBC模式的DES加密
            4.1.2) -des3: CBC模式的DES加密
            4.1.3) -aes128: CBC模式的AES128加密
            4.1.4) -aes192: CBC模式的AES192加密
            4.1.5) -aes256: CBC模式的AES256加密
        4.2) -passout arg: arg为对称加密(des、des、aes)的密码(使用这个参数就省去了console交互提示输入密码的环节)
        4.3) -out file: 输出证书私钥文件
        [numbits]: 密钥长度
    example: 生成一个1024位的RSA私钥,并用DES加密(密码为1111),保存为server.key文件
    openssl genrsa -out server.key -passout pass:1111 -des3 1024 
 
    5) rsa: RSA数据管理
    openssl rsa [options] outfile
        5.1) -inform arg
        输入密钥文件格式:
            5.1.1) DER(ASN1)
            5.1.2) NET
            5.1.3) PEM(base64编码格式)
         5.2) -outform arg
         输出密钥文件格式
            5.2.1) DER
            5.2.2) NET
            5.2.3) PEM
        5.3) -in arg
        待处理密钥文件 
        5.4) -passin arg
        输入这个加密密钥文件的解密密钥(如果在生成这个密钥文件的时候,选择了加密算法了的话)
        5.5) -out arg
        待输出密钥文件
        5.6) -passout arg  
        如果希望输出的密钥文件继续使用加密算法的话则指定密码 
        5.7) -des: CBC模式的DES加密
        5.8) -des3: CBC模式的DES加密
        5.9) -aes128: CBC模式的AES128加密
        5.10) -aes192: CBC模式的AES192加密
        5.11) -aes256: CBC模式的AES256加密
        5.12) -text: 以text形式打印密钥key数据 
        5.13) -noout: 不打印密钥key数据 
        5.14) -pubin: 检查待处理文件是否为公钥文件
        5.15) -pubout: 输出公钥文件
    example1: 对私钥文件进行解密
    openssl rsa -in server.key -passin pass:111 -out server_nopass.key
    example:2: 利用私钥文件生成对应的公钥文件
    openssl rsa -in server.key -passin pass:111 -pubout -out server_public.key
 
    6) x509:
    本指令是一个功能很丰富的证书处理工具。可以用来显示证书的内容,转换其格式,给CSR签名等X.509证书的管理工作
    openssl x509 [args]    
        6.1) -inform arg
        待处理X509证书文件格式
            6.1.1) DER
            6.1.2) NET
            6.1.3) PEM
        6.2) -outform arg   
        待输出X509证书文件格式
            6.2.1) DER
            6.2.2) NET
            6.2.3) PEM
        6.3) -in arg 
        待处理X509证书文件
        6.4) -out arg       
        待输出X509证书文件
        6.5) -req            
        表明输入文件是一个"请求签发证书文件(CSR)",等待进行签发 
        6.6) -days arg       
        表明将要签发的证书的有效时间 
        6.7) -CA arg 
        指定用于签发请求证书的根CA证书 
        6.8) -CAform arg     
        根CA证书格式(默认是PEM) 
        6.9) -CAkey arg      
        指定用于签发请求证书的CA私钥证书文件,如果这个option没有参数输入,那么缺省认为私有密钥在CA证书文件里有
        6.10) -CAkeyform arg  
        指定根CA私钥证书文件格式(默认为PEM格式)
        6.11) -CAserial arg   
        指定序列号文件(serial number file)
        6.12) -CAcreateserial 
        如果序列号文件(serial number file)没有指定,则自动创建它     
    example1: 转换DER证书为PEM格式
    openssl x509 -in cert.cer -inform DER -outform PEM -out cert.pem
    example2: 使用根CA证书对"请求签发证书"进行签发,生成x509格式证书
    openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
    example3: 打印出证书的内容
    openssl x509 -in server.crt -noout -text 
 
    7) crl: crl是用于管理CRL列表 
    openssl crl [args]
        7.1) -inform arg
        输入文件的格式
            7.1.1) DER(DER编码的CRL对象)
            7.1.2) PEM(默认的格式)(base64编码的CRL对象)
        7.2) -outform arg
        指定文件的输出格式 
            7.2.1) DER(DER编码的CRL对象)
            7.2.2) PEM(默认的格式)(base64编码的CRL对象)
        7.3) -text: 
        以文本格式来打印CRL信息值。
        7.4) -in filename
        指定的输入文件名。默认为标准输入。
        7.5) -out filename
        指定的输出文件名。默认为标准输出。
        7.6) -hash
        输出颁发者信息值的哈希值。这一项可用于在文件中根据颁发者信息值的哈希值来查询CRL对象。
        7.7) -fingerprint
        打印CRL对象的标识。
        7.8) -issuer
        输出颁发者的信息值。
        7.9) -lastupdate
        输出上一次更新的时间。
        7.10) -nextupdate
        打印出下一次更新的时间。 
        7.11) -CAfile file
        指定CA文件,用来验证该CRL对象是否合法。 
        7.12) -verify
        是否验证证书。        
    example1: 输出CRL文件,包括(颁发者信息HASH值、上一次更新的时间、下一次更新的时间)
    openssl crl -in crl.crl -text -issuer -hash -lastupdate –nextupdate 
    example2: 将PEM格式的CRL文件转换为DER格式
    openssl crl -in crl.pem -outform DER -out crl.der  
 
    8) crl2pkcs7: 用于CRL和PKCS#7之间的转换 
    openssl crl2pkcs7 [options] outfile
    转换pem到spc
    openssl crl2pkcs7 -nocrl -certfile venus.pem -outform DER -out venus.spc
    https://www.openssl.org/docs/apps/crl2pkcs7.html
 
    9) pkcs12: PKCS#12数据的管理
    pkcs12文件工具,能生成和分析pkcs12文件。PKCS#12文件可以被用于多个项目,例如包含Netscape、 MSIE 和 MS Outlook
    openssl pkcs12 [options] 
    http://blog.csdn.net/as3luyuan123/article/details/16105475
    https://www.openssl.org/docs/apps/pkcs12.html
 
    10) pkcs7: PCKS#7数据的管理 
    用于处理DER或者PEM格式的pkcs#7文件
    openssl pkcs7 [options] outfile
    http://blog.csdn.net/as3luyuan123/article/details/16105407
    https://www.openssl.org/docs/apps/pkcs7.html
 
2. openssl list-message-digest-commands(消息摘要命令)
    1) dgst: dgst用于计算消息摘要 
    openssl dgst [args]
        1.1) -hex           
        以16进制形式输出摘要
        1.2) -binary        
        以二进制形式输出摘要
        1.3) -sign file    
        以私钥文件对生成的摘要进行签名
        1.4) -verify file    
        使用公钥文件对私钥签名过的摘要文件进行验证 
        1.5) -prverify file  
        以私钥文件对公钥签名过的摘要文件进行验证
        verify a signature using private key in file
        1.6) 加密处理
            1.6.1) -md5: MD5 
            1.6.2) -md4: MD4         
            1.6.3) -sha1: SHA1 
            1.6.4) -ripemd160
    example1: 用SHA1算法计算文件file.txt的哈西值,输出到stdout
    openssl dgst -sha1 file.txt
    example2: 用dss1算法验证file.txt的数字签名dsasign.bin,验证的private key为DSA算法产生的文件dsakey.pem
    openssl dgst -dss1 -prverify dsakey.pem -signature dsasign.bin file.txt
 
    2) sha1: 用于进行RSA处理
    openssl sha1 [args] 
        2.1) -sign file
        用于RSA算法的私钥文件 
        2.2) -out file
        输出文件爱你
        2.3) -hex   
        以16进制形式输出
        2.4) -binary
        以二进制形式输出  
    example1: 用SHA1算法计算文件file.txt的HASH值,输出到文件digest.txt
    openssl sha1 -out digest.txt file.txt
    example2: 用sha1算法为文件file.txt签名,输出到文件rsasign.bin,签名的private key为RSA算法产生的文件rsaprivate.pem
    openssl sha1 -sign rsaprivate.pem -out rsasign.bin file.txt
 
3. openssl list-cipher-commands (Cipher命令的列表)
    1) aes-128-cbc
    2) aes-128-ecb
    3) aes-192-cbc
    4) aes-192-ecb
    5) aes-256-cbc
    6) aes-256-ecb
    7) base64
    8) bf
    9) bf-cbc
    10) bf-cfb
    11) bf-ecb
    12) bf-ofb
    13) cast
    14) cast-cbc
    15) cast5-cbc
    16) cast5-cfb
    17) cast5-ecb
    18) cast5-ofb
    19) des
    20) des-cbc
    21) des-cfb
    22) des-ecb
    23) des-ede
    24) des-ede-cbc
    25) des-ede-cfb
    26) des-ede-ofb
    27) des-ede3
    28) des-ede3-cbc
    29) des-ede3-cfb
    30) des-ede3-ofb
    31) des-ofb
    32) des3
    33) desx
    34) rc2
    35) rc2-40-cbc
    36) rc2-64-cbc
    37) rc2-cbc
    38) rc2-cfb
    39) rc2-ecb
    40) rc2-ofb
    41) rc4
    42) rc4-40

四、x.509、PCKS与编码的关系

x.509是国际电联ITU-T的标准,用于规范基于公钥密码体系PKI(public key infrastructure)体系的数字证书管理。其标准主要由RFC5280[1]描述,现在常用的数字证书正是基于X.509标准的。PCKS系列是指生成证书的格式(虽然公钥是没有所谓格式的,但是私钥有呀,别忘了我们的公钥也是来自于私钥,自建证书的创建也离不开私钥),不同格式的证书适用于不同场合,可以理解为PCKS就是X.509标准的具体实现方式。而我们说的编码,则是指PEM和DER两种形式不同,不管是证书还是密钥,都存在这两种格式,PEM是ASCII格式,DER是二进制格式,只是编码格式不同,适用环境不同,当然也是可以互相转换的。

顺便附上X.509的证书结构格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Certificate
    Version #版本号,区分不同的X.509版本     
    Serial Number #序列号,CA分配给证书的唯一编号
    #签名算法,CA签发证书时使用的公开密钥算法和摘要算法,比如PKCS #1 SHA-1 With RSA Encryption
    Certificate Signature Algorithm 
    Issuer #证书签发机构
    Validity #有效期限
        Not Before #起始日期
        Not After #终止日期
    Subject #证书主体信息,证书主体即证书的持有人
    Subject Public Key Info #证书主体的公钥信息
        Public Key Algorithm #证书主体使用的公钥算法
        Subject Public Key #证书主体的公钥
    Issuer Unique Identifier (optional) #证书签发者唯一标识符
    Subject Unique Identifier (optional) #证书主体唯一标识符
    Extensions (optional) #扩展
        ...
Certificate Signature Algorithm #证书签名算法,比如PKCS #1 SHA-1 With RSA Encryption
Certificate Signature #证书的数字签名
Fingerprints #指纹
    SHA-256 Fingerprint #
    SHA-1 Fingerprint #

五、nginx配置自建证书

这部分的内容没有去实践,这里就直接贴网上的两篇实战例子了,需要注意的是,以为一直觉得使用自建证书来搭建https,需要在客户端浏览器同时安装自建CA根证书和网站数字证书,但是现在看来貌似不用,只要安装了网站数字证书并信任,就可以完成自建https,12306的方式则是提供根证书,相当于浏览器增加CA,那么以后只要是该CA下颁发的证书就可以通过。

基于OpenSSL自建CA和颁发SSL证书

为nginx配置https并自签名证书

六、PHP利用RSA实现加密与签名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$private_key = "-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCpS7mxdU6svbDcs10qbq9f9t5D4yfqC1jLmZD3GDD4D/8TbNkf
vcYDvde6nyPRSxrnzl9YmZhJKlP2iCIwdwwmW6yulXZyvPurfN/1AJt4JYDxnN/q
u1bSG5DZMribLsR2dlfA5J0D6lQ7g40eSgp4D6UWy8ezLy6UWFQCrnUHEQIDAQAB
AoGAQCQeoKtvOWdNIPEb9T2mWFdx8oqXzsapx8nQ8K1LsFBvNe7hfHMsGLLOjzhI
G7223eiEm07mMaJF2XvOaEpSYX/qQ1LZRSdBrzCec1lcDbB95dcRg9NmgBuCpUxE
3SGYm3VB8rurfsrRUUYoIbjWz8qyuIGdMbaNkHG/CpnUYpkCQQDfWYDYtQ3DxCt+
JBoLfuCykk8+nIV12CIYb023naoR2s/aQQRk9BkGCkDrdOAgZAN3BGOHYseKAfTP
nARDzfiDAkEAwgtYfgCDTOfW5/kJK1lZO21CdCCZnePwGYmWDLPzNiJIn8k0U6Ig
9GmxG+0GKzY71XO8W3Nh18ilZbX9dYel2wJASQ+AJGNlc0pyZ7rrgiMo4YEWxwZw
adIfpRqTs6KxhVGseFqYU2W94cns3pjG0BGnSIF5BUp8t1pYeKkyg/OWfQJBAK1w
mq41IycQaoR5kfqPKDT32dgWc3gvDqKk2duM1KzkQ+meXAkM90u/VLDTURo6pYyK
oCdVoHTRQRUCcAQnNNUCQQCO/zDRaY+5ssjPqj77eJqWfAhtbSDRRw+NurmUSas1
FT1cD5nil+uT48bIRoC5nk/XWfvAvMg/Yw5bslGUNx7f
-----END RSA PRIVATE KEY-----";
 
$public_key = "-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpS7mxdU6svbDcs10qbq9f9t5D
4yfqC1jLmZD3GDD4D/8TbNkfvcYDvde6nyPRSxrnzl9YmZhJKlP2iCIwdwwmW6yu
lXZyvPurfN/1AJt4JYDxnN/qu1bSG5DZMribLsR2dlfA5J0D6lQ7g40eSgp4D6UW
y8ezLy6UWFQCrnUHEQIDAQAB
-----END PUBLIC KEY-----";
 
/**
 * RSA私钥加密公钥解密
 */
$data="hello,i am js";
openssl_private_encrypt($data, $crypted, $private_key);
 
// 由于php 进行openssl_public_encrypt 加密后返回的是二进制数据,需要对其返回的加密后的数据进行二进制16进制编码base64_encode才可以显示,$crypted为加密后的串 
$crypted=base64_encode($crypted); 
echo "私钥加密后的结果为:".$crypted."\n";
//相应的:加密后生产的16进制加密字符串需要进行base64_decode进行解密后在进行openssl_private_decrypt 
$crypted=base64_decode($crypted); 
openssl_public_decrypt($crypted, $decrypted , $public_key); 
echo "用公钥解密的结果为:".($decrypted)."\n";
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
 * RSA公钥加密私钥解密
 */
openssl_public_encrypt($data, $crypted, $public_key);
 
// 由于php 进行openssl_public_encrypt 加密后返回的是二进制数据,需要对其返回的加密后的数据进行二进制16进制编码base64_encode才可以显示,$crypted为加密后的串
$crypted=base64_encode($crypted);
 
echo "公钥加密后的结果为:".$crypted."\n";
 
//相应的:加密后生产的16进制加密字符串需要进行base64_decode进行解密后在进行openssl_private_decrypt
$crypted=base64_decode($crypted);
 
openssl_private_decrypt($crypted, $decrypted , $private_key);
 
echo "用私钥解密的结果为".($decrypted)."\n";
 
//输出内容为:
私钥加密后的结果为:HHe2EVmlZdBVCx90hjW3hNiM6bBJiUKkRNajSlem5Cwir4/cjqJRIzOCr1L2IYlpIvSZjyFAmVkBo6w6Db7gZGBNpRD49F5UQ0JrnT6rSBfd8A3sKEK+BTb30y+DsHTMxjfCnXT+/bqAnkD66vMfgS8pazy1O5h73abgwIR1yCc=
用公钥解密的结果为:hello,i am js
公钥加密后的结果为:TSB2IiINN9xUmmfMjOyWC4Q48fMqX99T/vWvflDG0GK2JqOXrKjX6rrCdPCV+ZQYAAliH+pVNujUa6Hhjn2gWDKIWCp21SE4o0AKoQ2eDSUY9swlu2cpbyEN8GZtxfVu26s/3msH1expz1vvULHKaFZMW1SK3BOibGJYTpkUAOM=
用私钥解密的结果为hello,i am js

注意,公钥和私钥都是可以用来加密的,对应的密钥用来解密,只是使用哪种密钥加密决定于不同场合,另外,用公钥加密出来的字符串每次都是变动的,用私钥加密出来的字符串每次都是固定的。

除了加解密外,RSA还提供了校验的功能,利用上面的密钥对,我们写个demo。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * RSA校验
 */
$data = "goodbye";
$pkeyid  = openssl_get_privatekey($private_key);
openssl_sign($data, $signature, $pkeyid);
openssl_free_key($pkeyid);
echo "签名串:".($sign_str = base64_encode($signature))."\n";
 
$public_key_handle  = openssl_pkey_get_public($public_key);
$res = openssl_verify($data, base64_decode($sign_str), $public_key_handle, OPENSSL_ALGO_SHA1);
openssl_free_key($public_key_handle);
var_dump($res);
 
//输出
签名串:mbSJ4W008JmnD1wRyWAcxKtzhdkT7RnVXYu8rbnWjrNFOhvY+AB9G9BqMAnq0C05nEwYYjOFurfB8Kw1SBLfiP+ZZq+Q1IdvTrV8HUhcAtqZq2XoIUSuqSgy6qhimPDlnB25dhf/hrJZvNUejKF9sZPW5E0vIEvW1gNZ5qf2MTA=
int(1)

我们一般的操作是公钥加密,私钥解密(只有有钥匙的人才能开锁),或者是私钥签名,公钥验签(数字签名,客户端验证服务端返回的数据是完整的)。加密还有padding没讲到,具体可以参看手册bool openssl_private_encrypt ( string $data , string &$crypted , mixed $key [, int $padding = OPENSSL_PKCS1_PADDING ] )第四个参数的定义,验证还区分有算法,默认的是OPENSSL_ALGO_SHA1,具体可以参见手册bool openssl_sign ( string $data , string &$signature , mixed $priv_key_id [, int $signature_alg = OPENSSL_ALGO_SHA1 ] )

七、文章参考来源

使用 openssl 生成证书

SSL 数字证书的标准、编码以及文件扩展名

RSA之格式转换

PHP通过OpenSSL生成证书、密钥并且加密解密数据

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>