RAS加密文件分析

对于 X.509 标准的证书有两种不同编码格式,一般采用 PEM 编码就以 .pem 作为文件扩展名,
若采用 DER 编码,就应以 .der 作为扩展名。但常见的证书扩展名还包括 .crt、.cer、.p12 等,
他们采用的编码格式可能不同,内容也有所差别,但大多数都能互相转换。

密钥格式及编码

x.509:公钥证书标准,就是一个整数里面要包含什么内容;
RSA:非对称加密算法,可以用于对文本加密,常用 1024 4086 位;
ASN.1:抽象语法标记,描述了一种对数据进行表示、编码、传输和解码的数据格式;
PKCS(The Public-Key Cryptography Standards):是一系列公钥密码学的相关标准;
PKCS#1(RSA Cryptography Standard):定义了RSA公钥和私钥的语法格式;
PKCS#8(Private-Key Information Syntax Standard):定义了一种私钥信息的语法,同时还提供一种加密密钥的语法;
DER编码:把符合ASN.1语法的密钥或证书文件输出为二进制文件;
PEM编码:把DER编码后的二进制数据用Base64进行编码,输出文本数据再加上开始和结束行,
如证书文件的"-----BEGIN CERTIFICATE-----“和”-----END CERTIFICATE-----";

证书的几种扩展名

.pem: 采用 PEM 编码格式的 X.509 证书的文件扩展名;
.der:采用 DER 编码格式的 X.509 证书的文件扩展名;
.crt(certificate):证书格式,常见于类 UNIX 系统,PEM 或 DER 编码,大多数采用 PEM 编码;
.cer(certificate):证书格式,常见于 Windows 系统,同样地,PEM 或 DER 编码,大多数采用 DER 编码;
.p12(.pfx):加密标准,PKCS #12,是公钥加密标准(Public Key Cryptography Standards,PKCS)系列的一种,
包含对应 X.509 证书和证书对应的私钥。简单理解:一份 .p12 文件 = X.509 证书+私钥;
.csr(Certificate Signing Request):证书签名请求,它并不是证书的格式,向CA申请证书用,
包含一个 RSA 公钥和其他附带信息,在生成这个 .csr 申请的时候,同时也会生成一个配对 RSA 私钥。
.key:通常用来存放一个 RSA 公钥或者私钥,它并非 X.509 证书格式,编码同样可能是 PEM,也可能是 DER,查看方式如下:

PEM 编码格式:openssl rsa -in xxx.key -text -noout 
DER 编码格式:openssl rsa -in xxx.key -text -noout -inform der

PKCS#1 格式

包含一系列数据,可以从从导出私钥和公钥,怎么生成我是看不懂的...

密钥

# PKCS#1 格式 密钥数据结构
RSAPrivateKey ::= SEQUENCE 
{ 
  version Version,    // 版本号,V2中这个版本号应该是0,但如果使用了多素数,则版本号应该是1
  modulus INTEGER, -- n     //RSA的模数 n
  publicExponent INTEGER, -- e    //RSA的公钥幂指数 e
  privateExponent INTEGER, -- d    //RSA的公钥幂指数 d
  prime1 INTEGER, -- p    //n的素因子 p
  prime2 INTEGER, -- q    //n的素因子 q
  exponent1 INTEGER, -- d mod (p-1) 
  exponent2 INTEGER, -- d mod (q-1) 
  coefficient INTEGER, -- (inverse of q) mod p,//代表CRT(中国剩余定理)系数
  otherPrimeInfos OtherPrimeInfos OPTIONAL    //如果version是0,则它被忽略;如果version是1,那么它至少应该包含一个OtherPrimeInfo实例
}

OtherPrimeInfo ::= SEQUENCE 
{ 
  prime INTEGER, -- ri 
  exponent INTEGER, -- di 
  coefficient INTEGER -- ti 
}

利用openssl生成,pkcs#1格式,pem编码的密钥文件 prikey.pkcs1.pem
openssl genrsa -out prikey.pkcs1.pem

# cat prikey.pkcs1.pem
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQC2FKCULiab15n1BD6QvFz382kt4GsDvuOM5tmYeZD7l8MucSyP
pPORFyaWGoKI+pTwAKKbDy2epqq7WtYxOfqA1AzU1mNsk6XRTBHa2XzuSF+/0rXY
...
j78p2hP4dnYPVbpCZCdrXNMWl+7hmrKfXNB7PvPAe0fQctUno7WElS37qwIDAQAB
-----END RSA PRIVATE KEY-----

文件是base64打码的,可以利用工具解码
openssl rsa -inform PEM -outform DER -in prikey.pkcs1.pem -out prikey.pkcs1.der
得到的.der文件就是按照pkcs#1格式的密钥的二进制输出

# xxd prike.pkcs#1.der
0000000: 3082 025b 0201 0002 8181 00f0 7f55 6009  0..[.........U`.
0000010: cd94 e296 4870 4ee1 f960 64bc 5379 7f52  ....HpN..`
0000020: 3521 5fb9 5a34 8d15 c416 aa08 cfdf 3835  5!_.Z4........
0000030: 499d 3ffb 31a2 b72e 8256 81f7 9eec cbc4  I.?.1....V......
...

直接二进制没啥用,用opnssl可以查看各字段信息
openssl asn1parse -i -in prikey.pkcs1.pem

# cat prikey.pkcs1.pem
  0:d=0  hl=4 l= 603 cons: SEQUENCE
  4:d=1  hl=2 l=   1 prim:  INTEGER :00
  7:d=1  hl=3 l= 129 prim:  INTEGER :B614A0942E269BD799F5043...07B47D072D527A3B584952DFBAB                                                                
139:d=1  hl=2 l=   3 prim:  INTEGER :010001
144:d=1  hl=3 l= 128 prim:  INTEGER :69132647DD0A32CD0CEFB46F...D2AC424E1E4064BCB85B3AAB9AE1AC1                                                                
275:d=1  hl=2 l=  65 prim:  INTEGER :D9232CD625CFF3512F2C26D2E9...68327792926561E64C600013781E5EC569
342:d=1  hl=2 l=  65 prim:  INTEGER :D6AB36F17373EF5B73229939DA11...6054E2E813FF00B                                                     
409:d=1  hl=2 l=  64 prim:  INTEGER :1EDA40A4ACFABF37E9DBFC283BC...C80E4DCC71258D2BC0FFFC7390B43864E1BF2105104BA701                                                                         
475:d=1  hl=2 l=  64 prim:  INTEGER :A1D672959574D1...62CFAFB6A7FE42C90DDBDBEE147D749445BA7EE5802B76E7C8A4B55D9FC181D62773                                                                           541:d=1  hl=2 l=  64 prim:  INTEGER :7AC9618673B62E277A8FB...D83C21460E2A6BEE

左半部分
0:d=0 hl=4 l= 603 cons: SEQUENCE
0 表示节点在整个文件中的偏移长度
d=0 表示节点深度
hl=4 表示节点头字节长度
l=603 表示节点数据字节长度
cons 表示该节点为结构节点,表示包含子节点或者子结构数据
prim 表示该节点为原始节点,包含数据
OCTET STRING      [HEX DUMP],就是加密后的私钥数据。
// SEQUENCE、OCTETSTRING等都是ASN.1中定义的数据类型,具体可以参考ASN.1格式说明。
右半部分
参照上两段的格式可以一一对应各字段的值,本文不涉及rsa编解码运算所以知道证书构成就好啦,毕竟俺也不会...
也有另一种查看方法
openssl rsa -text -noout -in prikey.pkcs1.pem

# cat prikey.pkcs1.pem
Private-Key: (1024 bit)
modulus:
    00:b6:14:a0:94:2e:26:9b:d7:99:f5:04:3e:90:bc:
    5c:f7:f3:69:2d:e0:6b:03:be:e3:8c:e6:d9:98:79:
    90:fb:97:c3:2e:71:2c:8f:a4:f3:91:17:26:96:1a:
    82:88:fa:94:f0:00:a2:9b:0f:2d:9e:a6:aa:bb:5a:
    d6:31:39:fa:80:d4:0c:d4:d6:63:6c:93:a5:d1:4c:
    11:da:d9:7c:ee:48:5f:bf:d2:b5:d8:8f:bf:29:da:
    13:f8:76:76:0f:55:ba:42:64:27:6b:5c:d3:16:97:
    ee:e1:9a:b2:9f:5c:d0:7b:3e:f3:c0:7b:47:d0:72:
    d5:27:a3:b5:84:95:2d:fb:ab
publicExponent: 65537 (0x10001)
privateExponent:
    69:13:26:47:dd:0a:32:cd:0c:ef:b4:6f:56:9f:1d:
    ...

大体上输出内容差不多。

公钥

# PKCS#1 公钥数据结构
RSAPublicKey ::= SEQUENCE 
{ 
  modulus INTEGER, -- n    //是RSA模数,是一个正整数 
  publicExponent INTEGER -- e    //是RSA公钥幂指数,是一个正整数
}

利用openssl从 pkcs1密钥 导出 pkcs1公钥钥
openssl rsa -in prikey.pkcs1.pem -RSAPublicKey_out -out pubkey.pkcs1.

# cat pubkey.pkcs1.pem
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBALYUoJQuJpvXmfUEPpC8XPfzaS3gawO+44zm2Zh5kPuXwy5xLI+k85EX
JpYagoj6lPAAopsPLZ6mqrta1jE5+oDUDNTWY2yTpdFMEdrZfO5IX7/StdiPvyna
Eh2dg9VukJkJ2tc0xaX7uGasp9c0Hs+88B7R9By1SejtYSVLfurAgMBAAE=
-----END RSA PUBLIC KEY-----

与私钥部分相识,查看各字段的值
openssl asn1parse -i -in pubkey.pkcs1.pem

# cat pubkey.pkcs1.pem
  0:d=0  hl=3 l= 137 cons: SEQUENCE
  3:d=1  hl=3 l= 129 prim:  INTEGER           :B614A0942E269BD799...D527A3B584952DFBA
135:d=1  hl=2 l=   3 prim:  INTEGER           :010001

PKCS#8 格式

操作及查看方法与上文相似,简单介绍他们的机构和生成方式

私钥

# PKCS#8 密钥 数据结构
PrivateKeyInfo ::= SEQUENCE 
{ 	
  verion               Version,    // 版本
  privateKeyAlgorithm		PrivateKeyAlgorithmIdentifier ::= SEQUENCE // 私钥算法
  privateKey				      PrivateKey ::= OCTET STRING ,    // 加密后私钥数据,最后一个OCTET STRING数据块 
  attributes           [0] IMPLICIT Attributes OPTIONAL ::= SET OF Attribute 
} 

把 pkcs1私钥 转换成 pkcs8私钥
openssl pkcs8 -topk8 -in prikey.pkcs1.pem -out prikey.pkcs8.pem -nocrypt
openssl asn1parse -i -in prikey.pkcs8.pem

# cat prikey.pkcs8.pem
# 要靠缩进开区分是哪一组信息,所以要排好看一点 
 0:d=0 hl=4 l= 710 cons: SEQUENCE 
 4:d=1 hl=2 l= 64  cons:  SEQUENCE  
 6:d=2 hl=2 l= 9   prim:   OBJECT :PBES2  
17:d=2 hl=2 l= 51  cons:  SEQUENCE    
19:d=3 hl=2 l= 27  cons:   SEQUENCE    
21:d=4 hl=2 l= 9   prim:    OBJECT :PBKDF2  
32:d=4 hl=2 l= 14  cons:    SEQUENCE    
34:d=5 hl=2 l= 8   prim:     OCTET STRING [HEX DUMP]:7A61B055165A89CA
44:d=5 hl=2 l= 2   prim:     INTEGER :0800  
48:d=3 hl=2 l= 20  cons:   SEQUENCE  
50:d=4 hl=2 l= 8   prim:    OBJECT :des-ede3-cbc  
60:d=4 hl=2 l= 8   prim:    OCTET STRING [HEX DUMP]:110E8A184EFEAB9C   
70:d=1 hl=4 l= 640 prim:  OCTET STRING [HEX DUMP]:  
C94F34F0CFF56B3E92D437C49559B1BD6 ... 87948FD5C7526D569BB8  

公钥

从 pkck1私钥 导出 pkcs8公钥
openssl rsa -in prikey.pkcs1.pem -pubout -out pubkey.pkcs8.pem
与私钥部分相识,查看各字段的值
openssl asn1parse -i -in pubkey.pkcs8.pem

# cat pubkey.pkcs8.pem 
-----BEGIN PUBLIC KEY----- 
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2FKCULiab15n1BD6QvFz382kt
4GsDvuOM5tmYeZD7l8MucSyPpPORFyaWGoKI+pTwAKKbDy2epqq7WtYxOfqA1AzU 
1mNsk6XRTBHa2XzuSF+/0rXYj78p2hP4dnYPVbpCZCdrXNMWl+7hmrKfXNB7PvPA 
e0fQctUno7WElS37qwIDAQAB
-----END PUBLIC KEY-----

openssl asn1parse -i -in pubkey.pkcs8.pem

# cat pubkey.pkcs8.pem
 0:d=0  hl=3 l= 159 cons: SEQUENCE 
 3:d=1  hl=2 l=  13 cons:  SEQUENCE 
 5:d=2  hl=2 l=   9 prim:   OBJECT            :rsaEncryption 
 6:d=2  hl=2 l=   0 prim:   NULL 
18:d=1  hl=3 l= 141 prim:  BIT STRING

PKCS#1/8 公私钥相互转换

# PKCS#1/8 公私钥相互转换
#生成   #1公:`openssl genrsa -out prikey.pkcs1.pem 1024`  

#1私 转 #8私:`openssl pkcs8 -in prikey.pkcs1.pem -out prikey.pkcs8.pem  -nocrypt `  
#8私 转 #1私:`openssl rsa   -in prikey.pkcs8.pem -out prikey.pkcs1.pem`  

#1私 转 #1公:`openssl rsa -in prikey.pkcs1.pem -out pubkey.pkcs1.pem -RSAPublicKey_out`
#8私 转 #8公:`openssl rsa -in prikey.pkcs8.pem -out pubkey.pkcs8.pem -pubout`

#1公 转 #8公:`openssl rsa -in pubkey.pkcs1.pem -out pubkey.pkcs8.pem -pubout -RSAPublicKey_in`
#8公 转 #1公:`openssl rsa -in pubkey.pkcs8.pem -out pubkey.pkcs1.pem -pubin  -RSAPublicKey_out`

#1私 转 #8公:`openssl rsa -in prikey.pkcs1.pem -out pubkey.pkcs8.pem -pubout`

参考

# 秘钥/证书/https握手/CA相关概念
# 使用openssl命令剖析RSA私钥文件格式
# RSA公私钥格式分析及其在Java和Openssl之间的转换方法
# RSA算法原理(一)
# openssl RSA密钥格式PKCS1和PKCS8相互转换

posted @ 2022-03-05 19:34  harmful  阅读(656)  评论(0编辑  收藏  举报