https://tls.mbed.org/kb/cryptography/asn1-key-structures-in-der-and-pem
介绍
每个人都喜欢 PEM 和用于以可移植格式保存加密密钥和证书的文档化的 ASN.1 结构。好吧.. 如果他们真的被记录在案,每个人都会这样做。但是要找到每个 DER 或 PEM 格式文件中的结构是一项相当大的壮举。
由于我们需要这些信息,我们也会在这里分享,以帮助其他人寻求知识和理解;)
ASN.1 和 DER 编码
在 RSA、PKCS#1 和 SSL/TLS 社区中, ASN.1的可分辨编码规则 (DER)编码用于以可移植格式表示密钥、证书等。尽管 ASN.1 不是最容易理解的表示格式并且带来了很多复杂性,但它确实有其优点。证书或密钥信息存储在 ASN.1 的二进制 DER 中,提供 RSA、SSL 和 TLS 的应用程序应处理 DER 编码以读取信息。
PEM 文件
因为 DER 编码导致编码数据的真正二进制表示,所以设计了一种格式,能够以可打印字符的编码发送这些,因此您可以实际邮寄这些东西。我现在关注的格式是 PEM 格式。
我们将看到的大多数 PEM 格式文件都是由OpenSSL在生成或导出 RSA 私钥或公钥和 X509 证书时生成的。
本质上,PEM 文件只是 DER 编码数据的 base64 编码版本。为了从外部区分 DER 编码字符串中的数据类型,在数据周围存在页眉和页脚。PEM 编码文件的一个示例是:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMYfnvWtC8Id5bPKae5yXSxQTt
+Zpul6AnnZWfI2TtIarvjHBFUtXRo96y7hoL4VWOPKGCsRqMFDkrbeUjRrx8iL91
4/srnyf6sh9c8Zk04xEOpK1ypvBz+Ks4uZObtjnnitf0NBGdjMKxveTq+VE7BWUI
yQjtQ8mbDOsiLLvh7wIDAQAB
-----END PUBLIC KEY-----
第一行和最后一行表示内部应该预期的 DER 格式。里面的数据是 DER 编码信息的 base64 编码版本。
格式
所以这一切都很好。但是每个不同的文件中你应该期望的结构是什么?请参阅下面的不同格式的说明。
RSA 公钥文件 (PKCS#1)
RSA 公钥 PEM 文件特定于 RSA 密钥。
它以标签开头和结尾:
-----BEGIN RSA PUBLIC KEY-----
BASE64 ENCODED DATA
-----END RSA PUBLIC KEY-----
在 base64 编码数据中,存在以下 DER 结构:
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}
公钥文件 (PKCS#8)
由于 RSA 并非专门在 X509 和 SSL/TLS 内部使用,因此以 PKCS#8 的形式提供了一种更通用的密钥格式,它标识公钥的类型并包含相关数据。
它以标签开头和结尾:
-----BEGIN PUBLIC KEY-----
BASE64 ENCODED DATA
-----END PUBLIC KEY-----
在 base64 编码数据中,存在以下 DER 结构:
PublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
PublicKey BIT STRING
}
AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL
}
所以对于 RSA 公钥,OID 是 1.2.840.113549.1.1.1 并且有一个 RSAPublicKey 作为 PublicKey 密钥数据位串。
RSA 私钥文件 (PKCS#1)
RSA 私钥 PEM 文件特定于 RSA 密钥。
它以标签开头和结尾:
-----BEGIN RSA PRIVATE KEY-----
BASE64 ENCODED DATA
-----END RSA PRIVATE KEY-----
在 base64 编码数据中,存在以下 DER 结构:
RSAPrivateKey ::= SEQUENCE {
version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
}
私钥文件 (PKCS#8)
因为 RSA 并非专门用于 X509 和 SSL/TLS,所以以 PKCS#8 的形式提供了一种更通用的密钥格式,它标识了私钥的类型并包含相关数据。
未加密的 PKCS#8 编码数据以标签开头和结尾:
-----BEGIN PRIVATE KEY-----
BASE64 ENCODED DATA
-----END PRIVATE KEY-----
在 base64 编码数据中,存在以下 DER 结构:
PrivateKeyInfo ::= SEQUENCE {
version Version,
algorithm AlgorithmIdentifier,
PrivateKey OCTET STRING
}
AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL
}
因此,对于 RSA 私钥,OID 是 1.2.840.113549.1.1.1 并且有一个 RSAPrivateKey 作为 PrivateKey 密钥数据八位字节字符串。
加密的 PKCS#8 编码数据以标签开头和结尾:
-----BEGIN ENCRYPTED PRIVATE KEY-----
BASE64 ENCODED DATA
-----END ENCRYPTED PRIVATE KEY-----
在 base64 编码数据中,存在以下 DER 结构:
EncryptedPrivateKeyInfo ::= SEQUENCE {
encryptionAlgorithm EncryptionAlgorithmIdentifier,
encryptedData EncryptedData
}
EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
EncryptedData ::= OCTET STRING
EncryptedData OCTET STRING 是 PKCS#8 PrivateKeyInfo(见上文)。