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

70

有人能帮我理解RSA密钥是如何以这些格式存储的吗?我想知道PKCS格式与编码(DER、PEM)之间的区别。据我所知,PEM更易读懂。PEM/DER对于密钥/证书是否类似于UTF-8/16对于字符?DER/PEM的重要性是什么?抱歉问题太多,但已经厌倦了搜索到模糊的答案。谢谢。


请查看我之前回答类似问题的答案,以获得更直观的解释。 - jariq
2个回答

174

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

PKCS1,以rfcs 2313、2437、3447和8017等多个版本提供,主要涉及使用RSA算法进行加密、解密、签名和验证。但由于加密技术通常用于系统之间或至少是程序之间,因此具有定义明确、可互操作的密钥格式非常方便,PKCS1在附录A.1中定义了RSA公钥和私钥的相当简单的格式。正如卢克所暗示的,这使用DER编码的ASN.1,它是一种用于互操作地编码几乎任何类型数据的标准。

PKCS8则作为rfc5208提供,是处理所有算法的私钥的标准,而不仅限于RSA。它也使用ASN.1 DER,并从简单地将AlgorithmIdentifierOCTET STRING组合开始,其中AlgorithmIdentifier是X.509首先定义的ASN.1结构,其预测性地标识了一个算法,并且OCTET STRING包含表示密钥的编码方式,这取决于算法。对于RSA算法,通过包含意味着rsaEncryption的OID的AlgorithmIdentifier进行标识,OCTET STRING包含PKCS1私钥编码。PKCS8还允许添加任意“属性”,但很少使用。(例如:无法将.jks转换为.pkcs12:超出私钥)

PKCS8还提供了加密私钥的选项,使用基于密码的加密(尽管没有明确要求)。这很常见,特别是当PKCS8用作PKCS12/PFX的私钥部分时,尽管不是普遍适用的。由于大多数系统今天需要支持多种算法,并希望能够适应开发出的新算法,因此PKCS8被优先用于私钥,而X.509定义了类似的任意算法方案用于公钥。虽然PKCS12/PFX通常比两者都更受欢迎。

这两个标准都与证书或其他PKI对象如CSR、CRL、OCSP、SCT等无关。它们由其他标准定义,包括PKCS系列的其他成员——尽管它们可能使用这些标准定义的密钥

PEM格式(正如Luke所说)是一种编码方式,可以使得几乎任何二进制/DER数据更加方便地进行编码。它源于上个世纪90年代的一次安全电子邮件尝试,名为Privacy-Enhanced Mail (PEM)。在那个时候,电子邮件系统通常只能传输或至少可靠地传输可打印的文本,并且通常只有有限的字符集和有限的行长度,因此PEM将二进制数据编码为行长为64的base64格式。PEM本身并不十分成功,已被PGP和S/MIME等其他格式取代,但其定义的格式仍然在使用中。现在的电子邮件系统通常可以传输二进制数据,但是像Luke所说的那样,复制和粘贴通常只能处理显示字符,所以PEM仍然有用,并且更容易被人类识别。

更确切地说,PEM将某些数据编码为例如PKCS1或PKCS8密钥、证书、CSR等形式:

  • 由5个连字符、单词BEGIN、一个或几个(以空格分隔的)单词定义数据类型和5个连字符组成的行

  • 一个可选的(很少见到的)rfc822风格的头,以空行结尾

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

  • 类似于BEGIN行但带有END而不是BEGIN的行

有些阅读器检查/强制执行行长度和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行中轻松识别每个文件(或其他数据单元)中数据类型。虽然只有第三个需要加密的密码,但数据中实际的关键值在没有工具的情况下不容易阅读。


在PKCS8加密私钥中,我读到它通常是AES-256-CBC加密的。IV位于哪里?我问这个问题是因为我有一个需要以编程方式解密的加密密钥。 - DevilCode
@DevilCode:PKCS8的(外部)结构定义在我提供的RFC中,加密形式通常使用RFC2898中定义的PKCS5,附录A中定义了参数语法。对于PBES1方案,IV是通过PBKDF1和密钥一起派生出来的;一些PBES2方案在附录B.2中,而你使用的(aes-256-cbc)就是其明显的扩展。但实际上,你并不需要IV,因为JDK或Bouncy会像我在你之前的问题 https://stackoverflow.com/questions/66286457/ 上所解释的那样为你处理它。 - dave_thompson_085
1
@PatS:不会的,除非 aliens 在我睡觉时占据了我的身体。 - dave_thompson_085

41

PKCS#1和PKCS#8(公钥密码学标准)是规范,用于管理特定的加密原语、填充等。两者都定义了用于存储密钥、证书和其他相关信息的文件格式。

PEM(隐私增强电子邮件)和DER(专有编码规则)更有趣一些。DER是用于键和证书等的ASN.1编码,您可以在Google上找到很多相关信息。私钥和证书使用DER编码并可以直接保存。然而,这些文件是二进制的,不易复制和粘贴,因此许多(如果不是大多数)实现也接受PEM编码的文件。PEM基本上是base64编码的DER:我们添加一个标题、可选的元数据和base64编码的DER数据,就得到了一个PEM文件。


46
“which you'll be able to Google plenty about” 是我在 StackOverflow 的答案中最喜欢看到的短语之一,现在已成为谷歌搜索结果中排名靠前的答案之一。 - JamesTheAwesomeDude

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接