密码学基础之RSA私钥、公钥文件分析

公私钥文件格式

常见的pkcs#1和pkcs#8格式。
pkcs#1私钥文件格式

-----BEGIN RSA PRIVATE KEY-----

-----END RSA PRIVATE KEY-----

pkcs#1公钥文件格式

-----BEGIN RSA PUBLIC KEY-----

-----END RSA PUBLIC KEY-----

pkcs#8私钥文件格式

-----BEGIN PRIVATE KEY-----

-----END PRIVATE KEY-----

pkcs#8公钥文件格式

-----BEGIN PUBLIC KEY-----

-----END PUBLIC KEY-----

生成公私钥

用OpenSSL生成公私钥

# 生成私钥文件,pkcs#1格式
openssl genrsa -out private_key.pem 1024
# 从私钥到处公钥,pkcs#8格式
openssl rsa -in private_key.pem -pubout -out public_key.pem

有的应用可能需要,pkcs#8格式的私钥,可用下面命令生成

openssl pkcs8 -topk8 -inform PEM -in private_key.pem -outform PEM -nocrypt>pkcs8_private_key.pem

生成pkcs#1格式的公钥文件

openssl rsa -pubin -in public_key.pem -RSAPublicKey_out -out pkcs1_public_key.pem

private_key.pem

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQD1t3KRf4oS3sH8PbABbXL1KBYCnGq4C/yinpfQ2j2eUmZarHuw
IMT9y5ns1lpZZTktGnypvnQjF8c0Rr/cYU53DJjglAgVEb3el6iU+WZ7nwLub/BN
YS83zpzrhDE3Qy6qTM3evsUsekBR8x6f6Usl7KpEI/0b+EfRSpXDdvU64wIDAQAB
AoGBAJK0odHfPTgBCf8pcaGYkG9xLJsIeutCNOd/GxOWif2yIux2WS8SkasaWd+/
J5iCSD32t4G9dafSNZyvtTPGYUqll4aGXlFqNW8pm16HPQXWrhv1D5LVEEu3zbj+
iNG+gHwB4bISQAOJbnvB6GoFUbDf8VYwkGGlSLGw5D5tulhRAkEA/XBLTfj+5j40
QPfuRIhcBsgxynKJDcmV0sLAIOTBIfSKs5nuYHEVEOcGaxS+nPY3w1ffSUPUdxm0
7L2s+9c0SQJBAPgzLLFvUjM58J/AtklkGyJ3KK5W+jLi/N1PIw7CGYGM2yfFiQLR
ibtJVjTFhLKqDz/BK4lZ9ffU/VNHSApOncsCQQCRBzSgnw9GtGv0jaxUnW+EFgWg
IyDYufW5kOafLCh1BNpmYnztxWhXrsyWdF2Ltr48U8mbxGwN57EIFJar2v+5AkA7
GkSMRAv48tUf1Y4Sz+m+PU3Mph2SPIcmVA/vFb1pIheV0u4bY7Y+iOokStychu52
qhMp8+gkie2BBTpcafgdAkBw8bAzLgmCV8SZEN60x8c2M2Y95CoYOoMLjvQdEfen
IeDmun3DtAPBuStwYNfeQnAHCwvcOJsgDiRLzhys3056
-----END RSA PRIVATE KEY-----

public_key.pem

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD1t3KRf4oS3sH8PbABbXL1KBYC
nGq4C/yinpfQ2j2eUmZarHuwIMT9y5ns1lpZZTktGnypvnQjF8c0Rr/cYU53DJjg
lAgVEb3el6iU+WZ7nwLub/BNYS83zpzrhDE3Qy6qTM3evsUsekBR8x6f6Usl7KpE
I/0b+EfRSpXDdvU64wIDAQAB
-----END PUBLIC KEY-----

pkcs1_public_key.pem

-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAPW3cpF/ihLewfw9sAFtcvUoFgKcargL/KKel9DaPZ5SZlqse7AgxP3L
mezWWlllOS0afKm+dCMXxzRGv9xhTncMmOCUCBURvd6XqJT5ZnufAu5v8E1hLzfO
nOuEMTdDLqpMzd6+xSx6QFHzHp/pSyXsqkQj/Rv4R9FKlcN29TrjAgMBAAE=
-----END RSA PUBLIC KEY-----

用下面的命令把秘钥文件的首行和末行去除并转化成十六进制格式:

cat private_key.pem|sed '1d'|sed '$d'|base64 -d|xxd -p >private_key.txt
cat public_key.pem|sed '1d'|sed '$d'|base64 -d|xxd -p >public_key.txt
cat pkcs1_public_key.pem|sed '1d'|sed '$d'|base64 -d|xxd -p >pkcs1_public_key.txt

pkcs#1 私钥文件分析

我们先用下面命令输出密钥的各个参数值

openssl rsa -in private_key.pem -text -out private.txt

输出如下(省略部分内容):

Private-Key: (1024 bit)
modulus:
    00:f5:b7:72:91:7f:8a:12:de:c1:fc:3d:b0:01:6d:(该部分只保留第一行,后面内容省略)
publicExponent: 65537 (0x10001)
privateExponent:
    00:92:b4:a1:d1:df:3d:38:01:09:ff:29:71:a1:98:(该部分只保留第一行,后面内容省略)
prime1:
    00:fd:70:4b:4d:f8:fe:e6:3e:34:40:f7:ee:44:88:(该部分只保留第一行,后面内容省略)
prime2:
    00:f8:33:2c:b1:6f:52:33:39:f0:9f:c0:b6:49:64:(该部分只保留第一行,后面内容省略)
exponent1:
    00:91:07:34:a0:9f:0f:46:b4:6b:f4:8d:ac:54:9d:(该部分只保留第一行,后面内容省略)
exponent2:
    3b:1a:44:8c:44:0b:f8:f2:d5:1f:d5:8e:12:cf:e9:(该部分只保留第一行,后面内容省略)
coefficient:
    70:f1:b0:33:2e:09:82:57:c4:99:10:de:b4:c7:c7:(该部分只保留第一行,后面内容省略)
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQD1t3KRf4oS3sH8PbABbXL1KBYCnGq4C/yinpfQ2j2eUmZarHuw
IMT9y5ns1lpZZTktGnypvnQjF8c0Rr/cYU53DJjglAgVEb3el6iU+WZ7nwLub/BN
YS83zpzrhDE3Qy6qTM3evsUsekBR8x6f6Usl7KpEI/0b+EfRSpXDdvU64wIDAQAB
AoGBAJK0odHfPTgBCf8pcaGYkG9xLJsIeutCNOd/GxOWif2yIux2WS8SkasaWd+/
J5iCSD32t4G9dafSNZyvtTPGYUqll4aGXlFqNW8pm16HPQXWrhv1D5LVEEu3zbj+
iNG+gHwB4bISQAOJbnvB6GoFUbDf8VYwkGGlSLGw5D5tulhRAkEA/XBLTfj+5j40
QPfuRIhcBsgxynKJDcmV0sLAIOTBIfSKs5nuYHEVEOcGaxS+nPY3w1ffSUPUdxm0
7L2s+9c0SQJBAPgzLLFvUjM58J/AtklkGyJ3KK5W+jLi/N1PIw7CGYGM2yfFiQLR
ibtJVjTFhLKqDz/BK4lZ9ffU/VNHSApOncsCQQCRBzSgnw9GtGv0jaxUnW+EFgWg
IyDYufW5kOafLCh1BNpmYnztxWhXrsyWdF2Ltr48U8mbxGwN57EIFJar2v+5AkA7
GkSMRAv48tUf1Y4Sz+m+PU3Mph2SPIcmVA/vFb1pIheV0u4bY7Y+iOokStychu52
qhMp8+gkie2BBTpcafgdAkBw8bAzLgmCV8SZEN60x8c2M2Y95CoYOoMLjvQdEfen
IeDmun3DtAPBuStwYNfeQnAHCwvcOJsgDiRLzhys3056
-----END RSA PRIVATE KEY-----

第一个字节为30,该节点为结构节点,表示包含子节点或者子结构数据
第二个字节为82或者81、或者其它值

  • 82表示接下来会用两个字节来表示长度
  • 81表示接下来会用两个字节来表示长度
  • 其它值表示长度,长度值不会大于0x80
00000000: 3082 025d 0201 0002 8181 00f5 b772 917f
            82                               82表示后面两个字节表示长度
               025c                          整个私钥后面长度为0x25c(605)
                    0201                          内容为:version,后面有1个字节表示version
                         00                  version的值为00
                           02 81                  内容为:n,81表示后面一个字节表示长度
                                81           n占用0x81个字节
00000010: 8a12 dec1 fc3d b001 6d72 f528 1602 9c6a
00000020: b80b fca2 9e97 d0da 3d9e 5266 5aac 7bb0
00000030: 20c4 fdcb 99ec d65a 5965 392d 1a7c a9be
00000040: 7423 17c7 3446 bfdc 614e 770c 98e0 9408
00000050: 1511 bdde 97a8 94f9 667b 9f02 ee6f f04d
00000060: 612f 37ce 9ceb 8431 3743 2eaa 4ccd debe
00000070: c52c 7a40 51f3 1e9f e94b 25ec aa44 23fd
00000080: 1bf8 47d1 4a95 c376 f53a e302 0301 0001
                                     02 03        内容为:e,占用3个字节
00000090: 0281 8100 92b4 a1d1 df3d 3801 09ff 2971
          0281 81                                 内容为:d,占用0x81个字节
000000a0: a198 906f 712c 9b08 7aeb 4234 e77f 1b13
000000b0: 9689 fdb2 22ec 7659 2f12 91ab 1a59 dfbf
000000c0: 2798 8248 3df6 b781 bd75 a7d2 359c afb5
000000d0: 33c6 614a a597 8686 5e51 6a35 6f29 9b5e
000000e0: 873d 05d6 ae1b f50f 92d5 104b b7cd b8fe
000000f0: 88d1 be80 7c01 e1b2 1240 0389 6e7b c1e8
00000100: 6a05 51b0 dff1 5630 9061 a548 b1b0 e43e
00000110: 6dba 5851 0241 00fd 704b 4df8 fee6 3e34
                    0241                          内容为:p,占用0x41个字节
00000120: 40f7 ee44 885c 06c8 31ca 7289 0dc9 95d2
00000130: c2c0 20e4 c121 f48a b399 ee60 7115 10e7
00000140: 066b 14be 9cf6 37c3 57df 4943 d477 19b4
00000150: ecbd acfb d734 4902 4100 f833 2cb1 6f52
                           02 41                  内容为:q,占用0x41个字节
00000160: 3339 f09f c0b6 4964 1b22 7728 ae56 fa32
00000170: e2fc dd4f 230e c219 818c db27 c589 02d1
00000180: 89bb 4956 34c5 84b2 aa0f 3fc1 2b89 59f5
00000190: f7d4 fd53 4748 0a4e 9dcb 0241 0091 0734
                                   0241           内容为:d mod (p - 1),占用0x41个字节
000001a0: a09f 0f46 b46b f48d ac54 9d6f 8416 05a0
000001b0: 2320 d8b9 f5b9 90e6 9f2c 2875 04da 6662
000001c0: 7ced c568 57ae cc96 745d 8bb6 be3c 53c9
000001d0: 9bc4 6c0d e7b1 0814 96ab daff b902 403b
                                          02 40   内容为:d mod (q - 1),占用0x40个字节
000001e0: 1a44 8c44 0bf8 f2d5 1fd5 8e12 cfe9 be3d
000001f0: 4dcc a61d 923c 8726 540f ef15 bd69 2217
00000200: 95d2 ee1b 63b6 3e88 ea24 4adc 9c86 ee76
00000210: aa13 29f3 e824 89ed 8105 3a5c 69f8 1d02
                                               02 内容为:(inverse of q) mod p,占用0x40个字节
00000220: 4070 f1b0 332e 0982 57c4 9910 deb4 c7c7
          40      
00000230: 3633 663d e42a 183a 830b 8ef4 1d11 f7a7
00000240: 21e0 e6ba 7dc3 b403 c1b9 2b70 60d7 de42
00000250: 7007 0b0b dc38 9b20 0e24 4bce 1cac df4e
00000260: 7a 

pkcs#8 公钥文件分析

00000000: 3081 9f30 0d06 092a 8648 86f7 0d01 0101
          30                                 该节点为结构节点
            81                               81表示后面一个字节表示长度
               9f                            整个私钥后面长度为0x9f(159)
                 30                          该节点为结构节点
                    0d                       长度为0x0d个字节
                      06                     节点类型为06,OBJECT IDENTIFIER
                         09                  长度为0x09
                           2a 8648 86f7 0d01 表示是RSA加密
00000010: 0500 0381 8d00 3081 8902 8181 00f5 b772
          05                                 节点类型为05,表示NULL节点
            00                               长度为0
               03                            该节点为二进制串
                 81                          后面1个字节表示长度
                    8d                       节点长度为0x8d
                      00                     RSA描述头结束,该字节必须为0
                         30                  该节点为结构节点
                              89             节点长度为0x89
                                02 8181           内容为:n,占用0x81个字节
00000020: 917f 8a12 dec1 fc3d b001 6d72 f528 1602
00000030: 9c6a b80b fca2 9e97 d0da 3d9e 5266 5aac
00000040: 7bb0 20c4 fdcb 99ec d65a 5965 392d 1a7c
00000050: a9be 7423 17c7 3446 bfdc 614e 770c 98e0
00000060: 9408 1511 bdde 97a8 94f9 667b 9f02 ee6f
00000070: f04d 612f 37ce 9ceb 8431 3743 2eaa 4ccd
00000080: debe c52c 7a40 51f3 1e9f e94b 25ec aa44
00000090: 23fd 1bf8 47d1 4a95 c376 f53a e302 0301
                                          02 03   内容为:e,占用3个字节
000000a0: 0001

pkcs#1 公钥文件分析

看起来pkcs#8公钥文件二进制内容一致,只是少了前面22个字节。但是肉眼看怎么知道不会看错呢,我们用下面命令验证一下:

cat public_key.pem|sed '1d'|sed '$d'|base64 -d|xxd -p -seek 22>file1
cat pkcs1_public_key.pem|sed '1d'|sed '$d'|base64 -d|xxd -p >file2
diff file1 file2; echo $?

diff 输出为0,表明我们的判断是正确的。

相关文章

密码学基础之RSA与不对称秘钥
密码学基础系列

你可能感兴趣的:(密码学基础之RSA私钥、公钥文件分析)