# SSL证书与私钥的编码格式和文件扩展名
Date: 2023-04-09


<!--more-->

#### **证书格式（certificates）**

X.509 使用一种称为抽象语法表示法 (ASN.1) 来表达证书的数据结构。

X.509 证书有不同的格式，例如 PEM、DER、PKCS#7 和 PKCS#12。 PEM 和 PKCS#7 格式使用 Base64 ASCII 编码，而 DER 和 PKCS#12 使用二进制编码。证书文件根据它们使用的格式和编码具有不同的扩展名。

不幸的是证书的扩展名并不能区分出证书使用的编码格式， 如以.cer为后缀的证书， 编码方式可能是Base64 ASCII 编码也可以是二进制编码。

![](https://garlicspace.com/wp-content/uploads/2023/04/ssl-certificate-format.png)

##### **PEM 格式：**

大多数 CA（证书颁发机构）在 **Base64 ASCII 编码**文件中提供 PEM 格式的证书。证书文件类型可以是 .pem、.crt、.cer 或 .key。

- .pem 文件可以在单个文件中包含服务器证书、中间证书和私钥。
- .crt 或 .cer 文件可以用于服务器证书和中间证书。
- .key 文件可用于私钥。

PEM 文件使用 ASCII 编码，因此您可以在任何文本编辑器（如记事本、MS word 等）中打开它们。

- PEM 文件中的每个**证书**都包含在 ---- BEGIN CERTIFICATE---- 和 ----END CERTIFICATE 之间----报表。
- **私钥 (PKCS#1 / PKCS#8)**包含在 RSA ---- BEGIN RSA PRIVATE KEY----- 和 -----END RSA PRIVATE KEY----- , ---- BEGIN EC PRIVATE KEY----- 和 -----END EC PRIVATE KEY----- , -----BEGIN SM2 PRIVATE KEY----- 和 -----END SM2 PRIVATE KEY-----语句之间。

- **CSR (PKCS+10)** 包含在 -----BEGIN CERTIFICATE REQUEST----- 和 -----END CERTIFICATE REQUEST----- 语句之间。

其中SM2的比较特殊：

openssl 3.0 版本

```
$ openssl ecparam -name SM2 -genkey -out sm2.key
$ openssl ec -in sm2.key -out sm2_1.key
read EC key
writing EC key
$ cat sm2.key
-----BEGIN SM2 PARAMETERS-----
BggqgRzPVQGCLQ==
-----END SM2 PARAMETERS-----
-----BEGIN PRIVATE KEY-----
MIGIAgEAMBQGCCqBHM9VAYItBggqgRzPVQGCLQRtMGsCAQEEIOwPify22mwkx8au
onuBd8lr8pZ1lu4VsBRQ1qKg3+ZSoUQDQgAEuSGYeABkTiBLw1OjvNRbbFJh03HL
bZvhhdiea4OOFm6FiDqx8u0ZeWmyEDSjfJRK04uJrArPMMEY8v5Dgs999Q==
-----END PRIVATE KEY-----
$ cat sm2_1.key
-----BEGIN SM2 PRIVATE KEY-----
MHcCAQEEIOwPify22mwkx8auonuBd8lr8pZ1lu4VsBRQ1qKg3+ZSoAoGCCqBHM9V
AYItoUQDQgAEuSGYeABkTiBLw1OjvNRbbFJh03HLbZvhhdiea4OOFm6FiDqx8u0Z
eWmyEDSjfJRK04uJrArPMMEY8v5Dgs999Q==
-----END SM2 PRIVATE KEY-----

```

openssl 1.1.1

生成的都为 EC

```
$ openssl ecparam -name SM2 -genkey  -out sm2.key
$ cat sm2.key
-----BEGIN EC PARAMETERS-----
BggqgRzPVQGCLQ==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIPtk3WLRBBQ9s29IOkZisJfZOkdtukSM8BcucGx5jpPMoAoGCCqBHM9V
AYItoUQDQgAEzAA69jGAaDZ2ZabQpGeSmtFsGoDf3rKJyE0oOfkjGoW8MWbXMEJi
YnDf8yEtHyvO3vAZEn4xKdl1dUKbWTeYFA==
-----END EC PRIVATE KEY-----
$ openssl ec -in sm2.key  -out sm2_1.key
read EC key
writing EC key
$ cat sm2_1.key
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIPtk3WLRBBQ9s29IOkZisJfZOkdtukSM8BcucGx5jpPMoAoGCCqBHM9V
AYItoUQDQgAEzAA69jGAaDZ2ZabQpGeSmtFsGoDf3rKJyE0oOfkjGoW8MWbXMEJi
YnDf8yEtHyvO3vAZEn4xKdl1dUKbWTeYFA==
-----END EC PRIVATE KEY-----
```

这个问题目前还未解决

https://github.com/openssl/openssl/issues/20420

 

##### **PKCS#7格式**

PKCS#7 证书使用 **Base64 ASCII 编码**，文件扩展名为 .p7b 或 .p7c。

这种格式只能存储**证书**，不能存储私钥。

P7B 证书包含在“-----BEGIN PKCS7-----”和“-----END PKCS7-----”语句之间。

##### **DER格式**

**证书或私钥**采用**二进制**形式，包含在 .der 或 .cer 文件中。

这些证书主要用于基于 Java 的 Web 服务器。

##### **PKCS#12格式**

##### PKCS#12 证书采用二进制形式，包含在 .pfx 或 .p12 文件中。 PKCS#12 可以将**服务器证书、中间证书和私钥存储**在一个带有密码保护的.pfx 文件中。 这些证书主要用于 Windows 平台。

#### **密钥格式（keys）**

 

##### **PKCS#1格式**

定义 RSA 密钥的传统格式

```
-----BEGIN RSA PRIVATE KEY-----
RSAPrivateKey
-----END RSA PRIVATE KEY-----

-----BEGIN RSA PUBLIC KEY-----
RSAPublicKey
-----END RSA PUBLIC KEY-----
```

```
openssl genrsa -out private.pem 2048
```

如果是openssl3.0

```
openssl genrsa -traditional -out private.pem 2048
```

 

##### **PKCS#8格式**

PKCS#8支持多种加密算法， 还可以支持密码加密。

```
-----BEGIN PRIVATE KEY-----
PrivateKeyInfo ::= OneAsymmetricKey
-----END PRIVATE KEY-----

-----BEGIN ENCRYPTED PRIVATE KEY-----
EncryptedPrivateKeyInfo
-----END ENCRYPTED PRIVATE KEY-----
```

PKCS#8 与 PKCS#1转换

```
###Convert PKCS #1 -> PKCS #8

openssl pkcs8 -in private-pkcs1.pem -topk8 -out private-pkcs8.pem -nocrypt
openssl pkcs8 -in private-pkcs1.pem -topk8 -out private-pkcs8-enc.pem

###Convert PKCS #8 -> PKCS #1

openssl rsa -in private-pkcs8.pem -out private-pkcs1.pem
```

 

看下内部结构, 使用 openssl asn1parse

PKCS#1

```
$ openssl asn1parse -in private.pem
    0:d=0  hl=4 l=1187 cons: SEQUENCE
    4:d=1  hl=2 l=   1 prim: INTEGER           :00
    7:d=1  hl=4 l= 257 prim: INTEGER           :CEFF7BCD4F9D478B7DC5C07D0C752082D28598FF61F8FD49736E357630116BF0175B06E193B168C8BA3648D97BE584D959ED2685C8163341B0CD81AFB2CF26588A0090FB73C32865A0B0EE60126CC477D998CDDF4052B39CD76DA0A5EEF044054670E298DC7DE9BD30DDBC33D5F5FA70E631D9C1899577F3D6F1D0E4031E103FBC96AD660F19D24AE23F1136AF1FE615CC8D3093975BD68528BDD2C3AD5E91DF3D9C9C16B7D5195AC887F6CE84722A2ADD52A9520D699CEBBDDE19E9EB9317707EED80346F47A2705BA372BAFC4A3C925E49E662EA8F25ABE50B840C75F07ADDC25AD23D051A81930F8CE4581CDE6D984E668DB12B37DB1663DBE5A86C6F836F
  268:d=1  hl=2 l=   3 prim: INTEGER           :010001
  273:d=1  hl=4 l= 256 prim: INTEGER           :46B521A283C00B68DC391923FE05E2699DA4F21AC66A2987160D7EE894C9D6AF8822D96A63AB75CA1F459CC3E19D08B0C0159093A141E81757E0131D23BCBBF2018DE8F863D635ADE5629AC2A9788AF20F9BB13342031E0484D81748A7225E71D8DA85A4C6A8A217B4A201804965813B607E85CE2503B01A54817CA3EE66AE10A23FB763A161B49DDE51511618EAB4C3A8008305D3930692B363F1DD8698E6F4B6A31068E8AEC9FAB70843AE75218738014E47F2F1FCA3DD639D52F971029F2FB85FFEC7B1E4F1E824C5B08EBD0F2BC6833E65943CC83729B6A37E561898528CD585F214AA9E2ED7C68AF020E5C7F3130A3BBBEFE24D0DB776F11CB83AE16A3D
  533:d=1  hl=3 l= 129 prim: INTEGER           :E98BE0C1D95856C0CDF5A94E019D183D7A0B3A5E7D41449D93FEFB01749073FBD222EC9B6AA5A27B4A637A770A59BBBCAF12A46A4462918FCBE0B4DC8C2F185767B8824F68FDD801881A6EE283CB5459A59082FF5B37F529E6AB1F054D9CF48FE0847CB7615FC6B04267646ACF2EB63526D450F4DA38CE0210B535FF46DC69BD
  665:d=1  hl=3 l= 129 prim: INTEGER           :E2E62FEA19B652533AD3EE33C640FABF78512D82DCAC9672974851286BCA7DB8D0E1C0DD25E29AD08BE4D6D56DE4DA7A5D681A6F90A1EF07080ECDE0CAA9063F3A2B207D8DF3861DCF49F1D5E6EF4BF71DB924F7866493484C5D316841BF8C4E59A62C243AE2954384A1BB8DA885206A9CD9A7CDF3EF69B362736D7F37AE569B
  797:d=1  hl=3 l= 129 prim: INTEGER           :8A07369DBAE3BFDA119FC8212748FE438F36C59784B5A764EE4BFB735FBDE41E8792467E902836806175ABB26136A98319818E14943821497838650C17F9D98C06EC007008604662995AEE0007DE8B0AB4945527B074C0FBB3AD9D16D849142D588754E258B56F4B4AE3AA7089E454A1D342165AB0027496B9E32F77A11CB18D
  929:d=1  hl=3 l= 128 prim: INTEGER           :603697AEBF046ED85823B1E846731B60C1963AA4390AFE28CD399F2072C4C496F00C2A8A1C1C80E559CCC9C46AFB1621B92601BFB926D182BBC9FB470CE8AB7B7820FD80000779A17E5AAEAFB36359650A378E135FEB9A00985114384F58F817E92FEB9BD9546752E014ECC0DEEAC49A30B4A2D15454FB0F53F9FA3E6DD0016D
 1060:d=1  hl=3 l= 128 prim: INTEGER           :7603381CFB4845A7CD70C96AA0595AABC06C8FA25D2F0D808E27FA7A4C695891CF24EAB0A8BCF92E3B9DA109CBE9F2FB9766E357D277972B217BC6129BC3CAF0E317F6C7106DAFD30AE3C4E58C6E1B734C4F7E6D6E36E498BE4BDFAD7C5A2B61D8E48CC267C65D0F13792138EE144CA73CD936F0BDDE7CC5BFC43BAE57A7BA41
```

PKCS#8

```
$ openssl asn1parse -in private-pkcs8.pem
    0:d=0  hl=4 l=1213 cons: SEQUENCE
    4:d=1  hl=2 l=   1 prim: INTEGER           :00
    7:d=1  hl=2 l=  13 cons: SEQUENCE
    9:d=2  hl=2 l=   9 prim: OBJECT            :rsaEncryption
   20:d=2  hl=2 l=   0 prim: NULL
   22:d=1  hl=4 l=1191 prim: OCTET STRING      [HEX DUMP]:308204A30201000282010100CEFF7BCD4F9D478B7DC5C07D0C752082D28598FF61F8FD49736E357630116BF0175B06E193B168C8BA3648D97BE584D959ED2685C8163341B0CD81AFB2CF26588A0090FB73C32865A0B0EE60126CC477D998CDDF4052B39CD76DA0A5EEF044054670E298DC7DE9BD30DDBC33D5F5FA70E631D9C1899577F3D6F1D0E4031E103FBC96AD660F19D24AE23F1136AF1FE615CC8D3093975BD68528BDD2C3AD5E91DF3D9C9C16B7D5195AC887F6CE84722A2ADD52A9520D699CEBBDDE19E9EB9317707EED80346F47A2705BA372BAFC4A3C925E49E662EA8F25ABE50B840C75F07ADDC25AD23D051A81930F8CE4581CDE6D984E668DB12B37DB1663DBE5A86C6F836F02030100010282010046B521A283C00B68DC391923FE05E2699DA4F21AC66A2987160D7EE894C9D6AF8822D96A63AB75CA1F459CC3E19D08B0C0159093A141E81757E0131D23BCBBF2018DE8F863D635ADE5629AC2A9788AF20F9BB13342031E0484D81748A7225E71D8DA85A4C6A8A217B4A201804965813B607E85CE2503B01A54817CA3EE66AE10A23FB763A161B49DDE51511618EAB4C3A8008305D3930692B363F1DD8698E6F4B6A31068E8AEC9FAB70843AE75218738014E47F2F1FCA3DD639D52F971029F2FB85FFEC7B1E4F1E824C5B08EBD0F2BC6833E65943CC83729B6A37E561898528CD585F214AA9E2ED7C68AF020E5C7F3130A3BBBEFE24D0DB776F11CB83AE16A3D02818100E98BE0C1D95856C0CDF5A94E019D183D7A0B3A5E7D41449D93FEFB01749073FBD222EC9B6AA5A27B4A637A770A59BBBCAF12A46A4462918FCBE0B4DC8C2F185767B8824F68FDD801881A6EE283CB5459A59082FF5B37F529E6AB1F054D9CF48FE0847CB7615FC6B04267646ACF2EB63526D450F4DA38CE0210B535FF46DC69BD02818100E2E62FEA19B652533AD3EE33C640FABF78512D82DCAC9672974851286BCA7DB8D0E1C0DD25E29AD08BE4D6D56DE4DA7A5D681A6F90A1EF07080ECDE0CAA9063F3A2B207D8DF3861DCF49F1D5E6EF4BF71DB924F7866493484C5D316841BF8C4E59A62C243AE2954384A1BB8DA885206A9CD9A7CDF3EF69B362736D7F37AE569B028181008A07369DBAE3BFDA119FC8212748FE438F36C59784B5A764EE4BFB735FBDE41E8792467E902836806175ABB26136A98319818E14943821497838650C17F9D98C06EC007008604662995AEE0007DE8B0AB4945527B074C0FBB3AD9D16D849142D588754E258B56F4B4AE3AA7089E454A1D342165AB0027496B9E32F77A11CB18D028180603697AEBF046ED85823B1E846731B60C1963AA4390AFE28CD399F2072C4C496F00C2A8A1C1C80E559CCC9C46AFB1621B92601BFB926D182BBC9FB470CE8AB7B7820FD80000779A17E5AAEAFB36359650A378E135FEB9A00985114384F58F817E92FEB9BD9546752E014ECC0DEEAC49A30B4A2D15454FB0F53F9FA3E6DD0016D0281807603381CFB4845A7CD70C96AA0595AABC06C8FA25D2F0D808E27FA7A4C695891CF24EAB0A8BCF92E3B9DA109CBE9F2FB9766E357D277972B217BC6129BC3CAF0E317F6C7106DAFD30AE3C4E58C6E1B734C4F7E6D6E36E498BE4BDFAD7C5A2B61D8E48CC267C65D0F13792138EE144CA73CD936F0BDDE7CC5BFC43BAE57A7BA41
```

可以看到PKCS#8 在 22 字节偏移位置就是PKCS#1的内容

```
$ openssl asn1parse -in private-pkcs8.pem -strparse 22
    0:d=0  hl=4 l=1187 cons: SEQUENCE
    4:d=1  hl=2 l=   1 prim: INTEGER           :00
    7:d=1  hl=4 l= 257 prim: INTEGER           :CEFF7BCD4F9D478B7DC5C07D0C752082D28598FF61F8FD49736E357630116BF0175B06E193B168C8BA3648D97BE584D959ED2685C8163341B0CD81AFB2CF26588A0090FB73C32865A0B0EE60126CC477D998CDDF4052B39CD76DA0A5EEF044054670E298DC7DE9BD30DDBC33D5F5FA70E631D9C1899577F3D6F1D0E4031E103FBC96AD660F19D24AE23F1136AF1FE615CC8D3093975BD68528BDD2C3AD5E91DF3D9C9C16B7D5195AC887F6CE84722A2ADD52A9520D699CEBBDDE19E9EB9317707EED80346F47A2705BA372BAFC4A3C925E49E662EA8F25ABE50B840C75F07ADDC25AD23D051A81930F8CE4581CDE6D984E668DB12B37DB1663DBE5A86C6F836F
  268:d=1  hl=2 l=   3 prim: INTEGER           :010001
  273:d=1  hl=4 l= 256 prim: INTEGER           :46B521A283C00B68DC391923FE05E2699DA4F21AC66A2987160D7EE894C9D6AF8822D96A63AB75CA1F459CC3E19D08B0C0159093A141E81757E0131D23BCBBF2018DE8F863D635ADE5629AC2A9788AF20F9BB13342031E0484D81748A7225E71D8DA85A4C6A8A217B4A201804965813B607E85CE2503B01A54817CA3EE66AE10A23FB763A161B49DDE51511618EAB4C3A8008305D3930692B363F1DD8698E6F4B6A31068E8AEC9FAB70843AE75218738014E47F2F1FCA3DD639D52F971029F2FB85FFEC7B1E4F1E824C5B08EBD0F2BC6833E65943CC83729B6A37E561898528CD585F214AA9E2ED7C68AF020E5C7F3130A3BBBEFE24D0DB776F11CB83AE16A3D
  533:d=1  hl=3 l= 129 prim: INTEGER           :E98BE0C1D95856C0CDF5A94E019D183D7A0B3A5E7D41449D93FEFB01749073FBD222EC9B6AA5A27B4A637A770A59BBBCAF12A46A4462918FCBE0B4DC8C2F185767B8824F68FDD801881A6EE283CB5459A59082FF5B37F529E6AB1F054D9CF48FE0847CB7615FC6B04267646ACF2EB63526D450F4DA38CE0210B535FF46DC69BD
  665:d=1  hl=3 l= 129 prim: INTEGER           :E2E62FEA19B652533AD3EE33C640FABF78512D82DCAC9672974851286BCA7DB8D0E1C0DD25E29AD08BE4D6D56DE4DA7A5D681A6F90A1EF07080ECDE0CAA9063F3A2B207D8DF3861DCF49F1D5E6EF4BF71DB924F7866493484C5D316841BF8C4E59A62C243AE2954384A1BB8DA885206A9CD9A7CDF3EF69B362736D7F37AE569B
  797:d=1  hl=3 l= 129 prim: INTEGER           :8A07369DBAE3BFDA119FC8212748FE438F36C59784B5A764EE4BFB735FBDE41E8792467E902836806175ABB26136A98319818E14943821497838650C17F9D98C06EC007008604662995AEE0007DE8B0AB4945527B074C0FBB3AD9D16D849142D588754E258B56F4B4AE3AA7089E454A1D342165AB0027496B9E32F77A11CB18D
  929:d=1  hl=3 l= 128 prim: INTEGER           :603697AEBF046ED85823B1E846731B60C1963AA4390AFE28CD399F2072C4C496F00C2A8A1C1C80E559CCC9C46AFB1621B92601BFB926D182BBC9FB470CE8AB7B7820FD80000779A17E5AAEAFB36359650A378E135FEB9A00985114384F58F817E92FEB9BD9546752E014ECC0DEEAC49A30B4A2D15454FB0F53F9FA3E6DD0016D
 1060:d=1  hl=3 l= 128 prim: INTEGER           :7603381CFB4845A7CD70C96AA0595AABC06C8FA25D2F0D808E27FA7A4C695891CF24EAB0A8BCF92E3B9DA109CBE9F2FB9766E357D277972B217BC6129BC3CAF0E317F6C7106DAFD30AE3C4E58C6E1B734C4F7E6D6E36E498BE4BDFAD7C5A2B61D8E48CC267C65D0F13792138EE144CA73CD936F0BDDE7CC5BFC43BAE57A7BA41
```

 

**ECC 相关操作** 　_https://www.scottbrady91.com/openssl/creating-elliptical-curve-keys-using-openssl_

**PKCS标准：**_https://en.wikipedia.org/wiki/PKC_S

**How to generate x509v3 Extensions in the End user certificate：**

_https://access.redhat.com/solutions/28965_

**x509v3\_config：**

_https://www.openssl.org/docs/manmaster/man5/x509v3\_config.html_

**How to add X.509 extensions to certificate OpenSSL**

_https://www.golinuxcloud.com/add-x509-extensions-to-certificate-openssl/_

**Adding AuthorityKeyIdentifier to a CertRequest**

_https://stackoverflow.com/questions/19163484/adding-authoritykeyidentifier-to-a-certrequest_

**Confusion over PKCS#1 and "traditional" options with OpenSSL**

_https://crypto.stackexchange.com/questions/103582/confusion-over-pkcs1-and-traditional-options-with-openssl_

**OpenSSL encrypt DER format private key**

_https://security.stackexchange.com/questions/244668/openssl-encrypt-der-format-private-key_

**Openssl ECDSA : private key passphrase**

_https://stackoverflow.com/questions/36968896/openssl-ecdsa-private-key-passphrase_

#### **参考及引用**

https://www.tutorialsteacher.com/https/ssl-certificate-format

https://blog.ndpar.com/2017/04/17/p1-p8/

图片 from [江金倫](https://www.facebook.com/groups/474930279315210/user/100005798739099/?__cft__[0]=AZUGIrMsG-O2TpATcdW60vnSb0XUbhhz2Ex9d56J3DfaCoJE8fJPdVktLfV95Kc5lK-_bYSy-1IMsFrUrDdNSRjUVubCVPPy06Ib27yz3x2k_66KB88yR5G4L4VBtgKU9yMqF0LWxqQTHJzuNA7m-PojkTX9K6vkTtpiS1J4Hs_N5OEJ_RfQ5OqmsVOLXRD9Pwg&__tn__=-UC*F)

