X509PKCS文件格式介绍

15次阅读

共计 5524 个字符,预计需要花费 14 分钟才能阅读完成。

ASN.1 – 数据结构描述语言

引用自 Wiki:

ASN.1 is a standard interface description language for defining data structures that can be serialized and deserialized in a cross-platform way.

也就是说 ASN.1 是一种用来定义数据结构的接口描述语言,它不是二进制,也不是文件格式,看下面的例子你就会明白了:

FooQuestion ::= SEQUENCE {
    trackingNumber INTEGER,
    question       IA5String
}

这段代码定义了 FooQuestion 的数据结构,下面是 FooQuestion 这个数据接口的某个具体的数据:

myQuestion FooQuestion ::= SEQUENCE {
    trackingNumber     5,
    question           "Anybody there?"
}

ASN.1 用在很多地方比如下面要讲的 X.509 和 PKCS group of cryptography standards。

文件编码格式

DER 编码格式

引用自 Wiki:

ASN.1 is closely associated with a set of encoding rules that specify how to represent a data structure as a series of bytes

意思是 ASN.1 有一套关联的编码规则,这些编码规则用来规定如何用二进制来表示数据结构,DER 是其中一种。

把上面的 FooQuestion 的例子用 DER 编码则是(16 进制):

30 13 02 01 05 16 0e 41 6e 79 62 6f 64 79 20 74 68 65 72 65 3f

翻译过来就是:

30 — type tag indicating SEQUENCE
13 — length in octets of value that follows
  02 — type tag indicating INTEGER
  01 — length in octets of value that follows
    05 — value (5)
  16 — type tag indicating IA5String 
     (IA5 means the full 7-bit ISO 646 set, including variants, 
      but is generally US-ASCII)
  0e — length in octets of value that follows
    41 6e 79 62 6f 64 79 20 74 68 65 72 65 3f — value ("Anybody there?")

看到这里你应该对 DER 编码格式有一个比较好的认识了。

PEM 编码格式

引用自 Wiki:

Privacy-Enhanced Mail (PEM) is a de facto file format for storing and sending cryptographic keys, certificates, and other data, based on a set of 1993 IETF standards defining “privacy-enhanced mail.”

PEM 是一个用来存储和发送密码学 key、证书和其他数据的文件格式的事实标准。许多使用 ASN.1 的密码学标准(比如 X.509 和 PKCS)都使用 DER 编码,而 DER 编码的内容是二进制的,不适合与邮件传输(早期 Email 不能发送附件),因此使用 PEM 把二进制内容转换成 ASCII 码。文件内容的格式像下面这样:

-----BEGIN label-----
BASE64Encoded
-----END label-----

label 用来区分内容到底是什么类型,下面会讲。

和 PEM 相关的 RFC 有很多,与本文内容相关的则是 RFC7468,这里面规定了很多 label,不过要注意不是所有 label 都会有对应的 RFC 或 Specification,这些 label 只是一种约定俗成。

PEM 实际上就是把 DER 编码的文件的二进制内容用 base64 编码一下,然后加上 -----BEGIN label----- 这样的头和 -----END label----- 这样的尾,中间则是 DER 文件的 Base64 编码。

我们可以通过下面的方法验证这个结论,先生成一个 RSA Private Key,编码格式是 PEM 格式:

openssl genrsa -out key.pem

查看一下文件内容,可以看到 label 是RSA PRIVATE KEY

-----BEGIN RSA PRIVATE KEY-----
BASE64Encoded
-----END RSA PRIVATE KEY-----

然后我们把 PEM 格式转换成 DER 格式:

openssl rsa -in key.pem -outform der -out key.der

如果你这个时候看一下文件内容会发现都是二进制。然后我们把 DER 文件的内容 Base64 一下,会看到内容和 PEM 文件一样(忽略头尾和换行):

base64 -i key.der -o key.der.base64

证书、密码学 Key 格式

上面讲到的 PEM 是对证书、密码学 Key 文件的一种编码方式,下面举例这些证书、密码学 Key 文件格式:

X.509 证书

引用自 Wiki:

In cryptography, X.509 is a standard defining the format of public key certificates. X.509 certificates are used in many Internet protocols, including TLS/SSL, which is the basis for HTTPS, the secure protocol for browsing the web.

X.509 是一个 Public Key Certificates 的格式标准,TLS/SSL 使用它,TLS/SSL 是 HTTPS 的基础所以 HTTPS 也使用它。而所谓 Public Key Certificates 又被称为Digital CertificateIdentity Certificate

An X.509 certificate contains a public key and an identity (a hostname, or an organization, or an individual), and is either signed by a certificate authority or self-signed.

一个 X.509 Certificate 包含一个 Public Key 和一个身份信息,它要么是被 CA 签发的要么是自签发的。

下面这种张图就是一个 X.509 Certificate:

事实上 X.509 Certificate 这个名词通常指代的是 IETF 的 PKIX Certificate 和 CRL Profile,见 RFC5280。所以当你看到 PKIX Certificate 字样的时候可以认为就是 X.509 Certificate。

PKCS 系列

引用自 Wiki:

In cryptography, PKCS stands for “Public Key Cryptography Standards”

前面提到的 X.509 是定义 Public Key Certificates 的格式的标准,看上去和 PKCS 有点像,但实际上不同,PKCS 是 Public Key 密码学标准。此外 Public-Key Cryptography 虽然名字看上去只涉及 Public Key,实际上也涉及 Priviate Key,因此 PKCS 也涉及 Private Key。

PKCS 一共有 15 个标准编号从 1 到 15,这里只挑讲 PKCS #1、PKCS #8、PKCS #12。

PKCS #1

PKCS #1,RSA Cryptography Standard,定义了 RSA Public Key 和 Private Key 数学属性和格式,详见 RFC8017。

PKCS #8

PKCS #8,Private-Key Information Syntax Standard,用于加密或非加密地存储 Private Certificate Keypairs(不限于 RSA),详见 RFC5858。

PKCS #12

PKCS #12 定义了通常用来存储 Private Keys 和 Public Key Certificates(例如前面提到的 X.509)的文件格式,使用基于密码的对称密钥进行保护。注意上述 Private Keys 和 Public Key Certificates 是复数形式,这意味着 PKCS #12 文件实际上是一个 Keystore,PKCS #12 文件可以被用做 Java Key Store(JKS),详见 RFC7292。

如果你用自己的 CA 所签发了一个证书,运行下列命令可以生成 PKCS #12 keystore:

openssl pkcs12 -export \
  -in <cert> \
  -inkey <private-key> \
  -name my-cert \
  -caname my-ca-root \
  -CAfile <ca-cert> \
  -chain
  -out <pkcs-file>

PKCS #12 一般不导出 PEM 编码格式。

PEM 格式速查

当你不知道你的 PEM 文件内容是什么格式的可以根据下面查询。

X.509 Certificate

RFC7468 – Textual Encoding of Certificates

-----BEGIN CERTIFICATE-----
BASE64Encoded
-----END CERTIFICATE-----

X.509 Certificate Subject Public Key Info

RFC7468 – Textual Encoding of Subject Public Key Info

-----BEGIN PUBLIC KEY-----
BASE64Encoded
-----END PUBLIC KEY-----

PKCS #1 Private Key

没有 RFC 或权威 Specification,该格式有时候被称为 traditional format、SSLeay format(见 SO)

-----BEGIN RSA PRIVATE KEY-----
BASE64Encoded
-----END RSA PRIVATE KEY-----

PKCS #1 Public Key

同上没有 RFC 或权威 Specification

-----BEGIN RSA PUBLIC KEY-----
BASE64Encoded
-----END RSA PUBLIC KEY-----

PKCS #8 Unencrypted Private Key

RFC7468 – One Asymmetric Key and the Textual Encoding of PKCS #8 Private Key Info

-----BEGIN PRIVATE KEY-----
BASE64Encoded
-----END PRIVATE KEY-----

PKCS #8 Encrypted Private Key

RFC7468 – Textual Encoding of PKCS #8 Encrypted Private Key Info

-----BEGIN ENCRYPTED PRIVATE KEY-----
BASE64Encoded
-----END ENCRYPTED PRIVATE KEY-----

Private Key 操作命令

生成

生成 PKCS #1 格式的 RSA Private Key

openssl genrsa -out private-key.p1.pem 2048

转换

PKCS #1 -> Unencrypted PKCS #8

openssl pkcs8 -topk8 -in private-key.p1.pem -out private-key.p8.pem -nocrypt

PKCS #1 -> Encrypted PKCS #8

openssl pkcs8 -topk8 -in private-key.p1.pem -out private-key.p8.pem

过程中会让你输入密码,你至少得输入 4 位,所以 PKCS #8 相比 PKCS #1 更安全。

PKCS #8 -> PKCS #1

openssl rsa -in private-key.p8.pem -out private-key.p1.pem

如果这个 PKCS #8 是加密的,那么你得输入密码。

Public Key 操作命令

从 PKCS #1/#8 提取

提取指的是从 Private Key 中提取 Public Key,openssl rsa同时支持 PKCS #1 和 PKCS #8 的 RSA Private Key,唯一的区别是如果 PKCS #8 是加密的,会要求你输入密码。

提取 X.509 格式 RSA Public Key

openssl rsa -in private-key.pem -pubout -out public-key.x509.pem

提取 PKCS #1 格式 RSA Public Key

openssl rsa -in private-key.pem -out public-key.p1.pem -RSAPublicKey_out

从 X.509 证书提取

openssl x509 -in cert.pem -pubkey -noout > public-key.x509.pem

转换

X.509 RSA Public Key -> PKCS #1 RSA Public Key

openssl rsa -pubin -in public-key.x509.pem -RSAPublicKey_out -out public-key.p1.pem

PKCS #1 RSA Public Key -> X.509 RSA Public Key

openssl rsa -RSAPublicKey_in -in public-key.p1.pem -pubout -out public-key.x509.pem

参考资料

  • OpenSSL Cookbook,一本免费介绍 OpenSSL 的电子书
  • PKCS #1, PKCS #8, X.509,提供了很多格式转换的例子

正文完
 0