RSA 私钥的 PKCS#1 和 PKCS#8 格式

PKCS#1 and PKCS#8 format for RSA private key

谁能帮我理解 RSA 密钥是如何以这些格式存储的?我想知道 PKCS 格式与编码(DER、PEM)之间的区别。据我了解,PEM 更易于阅读。 keys/certs 的 PEM/DER 与字符的 UTF-8/16 相似吗? DER/PEM有什么意义?抱歉问题太多,但受够了谷歌搜索和模糊的答案。谢谢。

PKCS#1 和 PKCS#8(Public-Key 加密标准)是管理特定加密原语、填充等的使用的标准。两者都定义了用于存储密钥、证书和其他相关信息。

PEM (Privacy-Enhanced Mail) 和 DER (Distinguished Encoding Rules) 更有趣一点。 DER 是密钥和证书等的 ASN.1 编码,您将能够 Google 了解很多。私钥和证书使用DER编码,可以直接这样保存。但是,这些文件是二进制文件,无法轻松复制和粘贴,因此许多(如果不是大多数?)实现也接受 PEM 编码文件。 PEM 基本上是 base64 编码的 DER:我们添加一个 header、可选的 meta-data 和 base64 编码的 DER 数据,我们有一个 PEM 文件。

(扩展超出了我认为适合编辑的范围。)

PKCS1,有多个版本,如 rfcs 2313 2437 3447 和 8017, is primarily about using the RSA algorithm for cryptography including encrypting decrypting signing and verifying. But since crypto is often used between systems or at least programs it is convenient to have a defined, interoperable format for keys, and PKCS1 defines fairly minimal formats for RSA public and private keys in appendix A.1. As Luke implied this uses ASN.1 conventionally encoded as DER,它是几乎任何类型数据的互操作编码标准。

另一方面,

PKCS8 可用作 rfc5208 是处理所有算法私钥的标准,而不仅仅是 RSA。它还使用 ASN.1 DER,并通过简单地组合一个 AlgorithmIdentifier,一个由 X.509 定义的 ASN.1 结构(第一个)开始,它并不非常令人惊讶地识别一个算法,一个 OCTET STRING 包含根据算法以某种方式表示密钥。对于算法 RSA,由包含 OID 的 AlgorithmIdentifier 标识,这意味着 rsaEncryption,OCTET STRING 包含 PKCS1 私钥编码。 PKCS8 还允许添加任意 'attributes' ,但这很少使用。 (例如 Unable to convert .jks to .pkcs12: excess private key

PKCS8 还提供了一个选项来加密私钥,使用 password-based 加密(在实践中虽然没有明确要求)。这很常见,尤其是当 PKCS8 用作 PKCS12/PFX 的私钥部分时,尽管不是通用的。

由于当今大多数系统需要支持多种算法,并希望能够在开发时适应新算法,因此首选 PKCS8 作为私钥,以及 X.509 定义的类似 any-algorithm 方案对于公钥。尽管 PKCS12/PFX 通常优于两者。

这些都与证书或其他 PKI objects(如 CSR、CRL、OCSP、SCT 等)没有任何关系。这些由其他标准定义,包括 PKCS 系列的其他一些成员 --尽管他们可能会使用这些标准定义的

正如 Luke 所说,

PEM 格式 是一种以更方便的方式格式化或(超级)编码(几乎任何)binary/DER 数据的方式。它源自 1990 年代对名为 Privacy-Enhanced Mail 的安全电子邮件的尝试,因此是 PEM。在那些日子里,电子邮件系统通常只能传输或至少可靠地传输具有有限字符集的可打印文本,并且通常只有有限的行长度,因此 PEM 将二进制数据编码为 base64,行长度为 64。PEM 方案本身不是很好成功并已被 PGP 和 S/MIME 等其他格式所取代,但它定义的格式仍在使用。如今的电子邮件系统通常可以传输二进制数据,但正如卢克所说copy-and-paste通常只能处理显示的字符,因此 PEM 仍然有用,而且更容易被人类识别。

更确切地说,PEM 对一些数据进行编码,例如但不限于 PKCS1 或 PKCS8 密钥证书、CSR 等,如:

  • 一行由 5 个连字符、单词 BEGIN、一个或几个 (space-separated) 个定义数据类型的词和 5 个连字符组成

  • 一个可选的(和罕见的)rfc822 风格 header,由一个空行终止

  • base64 数据,分成 64 个字符的行(最后一行除外);一些程序改为使用(稍新的)76 个字符的 MIME 限制

  • 一行类似于 BEGIN 行,但用 END 代替

有些读者 check/enforce 行长度和 END 行,有些则没有,所以如果你弄错了,你可能会创建有时有效有时无效的文件,这对调试来说很烦人。

因此,例如 PEM 中的 PKCS1 私钥(未加密)如下所示:

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCjcGqTkOq0CR3rTx0ZSQSIdTrDrFAYl29611xN8aVgMQIWtDB/
lD0W5TpKPuU9iaiG/sSn/VYt6EzN7Sr332jj7cyl2WrrHI6ujRswNy4HojMuqtfa
b5FFDpRmCuvl35fge18OvoQTJELhhJ1EvJ5KUeZiuJ3u3YyMnxxXzLuKbQIDAQAB
AoGAPrNDz7TKtaLBvaIuMaMXgBopHyQd3jFKbT/tg2Fu5kYm3PrnmCoQfZYXFKCo
ZUFIS/G1FBVWWGpD/MQ9tbYZkKpwuH+t2rGndMnLXiTC296/s9uix7gsjnT4Naci
5N6EN9pVUBwQmGrYUTHFc58ThtelSiPARX7LSU2ibtJSv8ECQQDWBRrrAYmbCUN7
ra0DFT6SppaDtvvuKtb+mUeKbg0B8U4y4wCIK5GH8EyQSwUWcXnNBO05rlUPbifs
DLv/u82lAkEAw39sTJ0KmJJyaChqvqAJ8guulKlgucQJ0Et9ppZyet9iVwNKX/aW
9UlwGBMQdafQ36nd1QMEA8AbAw4D+hw/KQJBANJbHDUGQtk2hrSmZNoV5HXB9Uiq
7v4N71k5ER8XwgM5yVGs2tX8dMM3RhnBEtQXXs9LW1uJZSOQcv7JGXNnhN0CQBZe
nzrJAWxh3XtznHtBfsHWelyCYRIAj4rpCHCmaGUM6IjCVKFUawOYKp5mmAyObkUZ
f8ue87emJLEdynC1CLkCQHduNjP1hemAGWrd6v8BHhE3kKtcK6KHsPvJR5dOfzbd
HAqVePERhISfN6cwZt5p8B3/JUwSR8el66DF7Jm57BM=
-----END RSA PRIVATE KEY-----

未加密的 PKCS8 中的相同密钥:

-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKNwapOQ6rQJHetP
HRlJBIh1OsOsUBiXb3rXXE3xpWAxAha0MH+UPRblOko+5T2JqIb+xKf9Vi3oTM3t
KvffaOPtzKXZauscjq6NGzA3LgeiMy6q19pvkUUOlGYK6+Xfl+B7Xw6+hBMkQuGE
nUS8nkpR5mK4ne7djIyfHFfMu4ptAgMBAAECgYA+s0PPtMq1osG9oi4xoxeAGikf
JB3eMUptP+2DYW7mRibc+ueYKhB9lhcUoKhlQUhL8bUUFVZYakP8xD21thmQqnC4
f63asad0ycteJMLb3r+z26LHuCyOdPg1pyLk3oQ32lVQHBCYathRMcVznxOG16VK
I8BFfstJTaJu0lK/wQJBANYFGusBiZsJQ3utrQMVPpKmloO2++4q1v6ZR4puDQHx
TjLjAIgrkYfwTJBLBRZxec0E7TmuVQ9uJ+wMu/+7zaUCQQDDf2xMnQqYknJoKGq+
oAnyC66UqWC5xAnQS32mlnJ632JXA0pf9pb1SXAYExB1p9Dfqd3VAwQDwBsDDgP6
HD8pAkEA0lscNQZC2TaGtKZk2hXkdcH1SKru/g3vWTkRHxfCAznJUaza1fx0wzdG
GcES1Bdez0tbW4llI5By/skZc2eE3QJAFl6fOskBbGHde3Oce0F+wdZ6XIJhEgCP
iukIcKZoZQzoiMJUoVRrA5gqnmaYDI5uRRl/y57zt6YksR3KcLUIuQJAd242M/WF
6YAZat3q/wEeETeQq1wrooew+8lHl05/Nt0cCpV48RGEhJ83pzBm3mnwHf8lTBJH
x6XroMXsmbnsEw==
-----END PRIVATE KEY-----

和 PKCS8 加密:

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIC3TBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIkErtXjGCalMCAggA
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBApOUG3MKrBC/5bDBH/s5VfBIIC
gN5o1aJxvJYbp2oA/quz+BnCFn8ts3wPPOcqarHddy0L/VH3BdqFNbnPZEaDnvDl
kqChRsti4AAeX18ItMeAyNLNFv0J4mfI8Q5E7iEnPp+dTsZqNfVIJe2NGxOS7zp2
oQQIZVgjW0akDehv6ZDN796qDBlMY2g80wbBrzVgMJu/byG9IQQjngUE9QNGwrsj
7lYSprxjfTZOk1aGBD0d/HsmetIJvCeJ2i/5xAiGgZRrSWMC6aN7Zlra3eIvHQTB
aKZ8/0IT3iKSr6FpkEopOQae8biiTEVGw9D339P3qOSs2ChWWF+OV2sEA67w6q5j
pz6Poc5jgq4FOcf06GdcVa4tst2uykNJCW0wHpcUR1Tr9ILLhrZPYBYVQWW53Eee
o4+mqW2YORdG3a/jLHpEjL0Vdg95QNpdZoMv8plotN1MUBLebd05aCe5hJUb/x74
3GTwmRGmKoHOhOO3hhUaMCmZIg1xPlNT3jqxrZDoATBeONbaFP8OOkeucVYHbdUO
Ad7z6J8XuZDoxM0BVrGykEiQL2nAOccdsGoC33C9hjkqgU8G9jWElbynJlVqv+1a
lFHWjX5lB6ueiY/rClpVlLmXGB83OVPlo70FV0B9rhRChyB1IJJRYPFDJHSHJNu+
Pqay8zw82Gh/G+TWH/JCLm5YjX55ZSFMUmvwOLaxyQpmAGNH6dIBTAaSctVA7UrV
jm7m+5T7seiNYNEi19vDJipgr0GbX8+np47VrsJDxsS20wTeA/9ltD0xXwNrEKHd
2Nv/1OaCgnBQHIGULgEn9pT3/vU87bBHYjVdrWoUmqd9zFYtdImQE9u8IKTxTe4R
UPRGHqltz4uOjbD1epkSGe0=
-----END ENCRYPTED PRIVATE KEY-----

观察每个文件(或其他数据单元)中的数据类型很容易从 BEGIN/END 行中识别出来。如果没有工具,数据中的实际密钥值是不容易读取的,尽管实际上只有第三个需要秘密信息(用于加密的密码)。