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下颁发的证书就可以通过。
六、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 ] )
七、文章参考来源
nginx反向代理自动urldecode问题(转) rsa加解密的内容超长的问题解决(转)