常见的PKI标准(X.509、PKCS)及证书相关介绍

目录

  • ASN.1 - 数据结构描述语言
  • 文件编码格式
    • DER编码格式
    • PEM编码格式
  • 证书、密码学Key格式标准
    • X.509标准
    • PKCS(公钥加密标准)系列(PKCS#1、PKCS#8、PKCS#12)
  • 常见的证书标准格式(PEM编码)
    • X.509 Certificate
    • X.509 Certificate Subject Public Key Info
    • PKCS #1 Private Key
    • PKCS #1 Public Key
    • PKCS #8 Unencrypted Private Key
    • PKCS #8 Encrypted Private Key
  • 常见的证书文件后缀(.pem .der .cer .crt .pfx .p12 .jks)
  • Private Key操作命令:生成、转换
  • Public Key操作命令:从PKCS #1/#8提取、从X.509证书提取、转换

# 前言

PKI标准可以分为第一代标准和第二代标准。
第一代PKI标准主要包括美国RSA公司的公钥加密标准(Public Key Cryptography Standards,PKCS)系列、国际电信联盟的ITU-T X.509、IETF组织的公钥基础设施X.509(Public Key Infrastructure X.509,PKIX)标准系列、无线应用协议(Wireless Application Protocol ,WAP)论坛的无线公钥基础设施(Wireless Public Key Infrastructure,WPKI)标准等。第一代PKI标准主要是基于抽象语法符号(Abstract Syntax Notation One,ASN.1)编码的,实现比较困难,这也在一定程度上影响了标准的推广。
第二代PKI标准,略。
CA中心普遍采用的规范是X.509系列和PKCS系列。

# 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.509PKCS 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.509PKCS)都使用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

在-----BEGIN-----与-----END-----之间内容的顶部,有时使用一些头定义对信息进行封装,这些头信息格式如下(不一定都需要,可选的):
Proc-Type,4:ENCRYPTED
DEK-Info: cipher-name, ivec
其中,第一个头信息标注了该文件是否进行了加密,该头信息可能的值包括ENCRYPTED(信息已经加密和签名)、MIC-ONLY(信息经过数字签名但没有加密)、MIC-CLEAR(信息经过数字签名但是没有加密、也没有进行编码,可使用非PEM格式阅读)以及CLEAR(信息没有签名和加密并且没有进行编码,该项好象是openssl自身的扩展,但是并没有真正实现);
第二个头信息标注了加密的算法以及使用的ivec参量,ivec其实在这儿提供的应该是一个随机产生的数据序列,与块加密算法中要使用到的初始化变量(IV)不一样。

# 证书、密码学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

详细的介绍了RSA算法的计算过程,包括:key的产生,key的结构,对数字加密/解密/签名/验证签名的过程、对应算法。

  1. key. 关于key,分别记录了private和public的详细结构,以及存储哪些内容。并且在附录里面推荐了ASN.1 Syntax中的存储结构。注:没有规定实际的物理文件存储结构,比如pem等。
  2. 加密/解密 详细描述了加密/解密的算法。包括,首先针对字符串,怎么转化成数字,之后,怎么根据数字进行加密。 这里可以看出,标准中没有对超长字符串处理的说明。而转化出的字符串的长度,全都是key的模长度k。
    在字符串转化成数字过程中,需要增加填充字符,所以,分成了两种不同算法:RSAES-OAEP(现有标准) RSAES-PKCS1-v1_5(兼容过去标准)。在实际加密过程中,就只有一种算法了
  3. 无论在加密还是签名过程中,都会进行hash操作,hash操作没有自己定义,而是从附录中可以选择需要的hash方式。
  4. PKCS1填充方式:在进行RSA运算时需要将源数据D转化为Encryption block(EB)。其中pkcs1padding V1.5的填充模式按照以下方式进行:
格式:加密块EB = 00 + 块类型BT + 填充字符PS + 00 + 数据D  //以下描述均以十六进制字符串来描述
    说明
      EB:为转化后Hex进制表示的数据块,长度为128个字节(密钥1024位的情况下)
      00:为了确保块转换为整数的时候 小于模数 
      BT(Block Type):
          用一个字节表示,在目前的版本上,有三个值00 01 02。如果使用公钥操作,BT永远为02,如果用私钥操作则可能为00或01。
          块类型为00,数据开头必须不能是00,因为填充的也是00,将无法解析。
          块类型为01或02,块可以被准确解析,因为不会是00来填充。
          如果是私钥操作,且明文数据是以00字节开头,那么建议把BT的值设置为01,否则,BT为00,PS为00,D开头为00,数据无法被分隔开
      PS(Padding String):
          为填充位,PS由k-3-D这么多个字节构成,k表示密钥的字节长度,如果我们用1024bit的RSA密钥,这个长度就是1024/8=128,D表示明文数据D的字节长度
          对于BT为00的,则这些字节全部为00
          对于BT为01的,这些值全部为FF
          对于BT为02的,这些字节的值随机产生但不能是0字节(非00)
          填充长度至少为8个字节
      00:用于分开 PS 和 D
      D:数据原文(HEX十六进制)
          PS至少为8个字节,所以D <= k-11
          当我们使用128字节密钥对数据进行加密时,明文数据的长度不能超过过128-11=117字节
          当RSA要加密数据大于 k-11字节时怎么办呢?把明文数据按照D的最大长度分块然后逐块加密,最后把密文拼起来就行。
注意:加密块EB长度 = RSA密钥key的长度。比如密钥1024bit,即128字节,加密块也会被填充为128字节
示例:下面的数据需要填充74个FF才够128个字节。
签名的时候:加密块 = 00 + 01 + FF(74个) + 00 + ">3031300d060960864801650304020105000420b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9(51字节)

此外还有其他标准里定义的填充方式,比如PKCS5Padding、PKCS7Padding,不再赘述

### 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-----

# 常见证书后缀

作为文件形式存在的证书一般有这几种后缀:(证书中包含公钥,以及公钥颁发机构、版本号、算法等信息,可以以X.509为例看一下证书内容)

1.带有私钥的证书:(一般都有密码保护,使用的是DER编码)

  • .pfx 常用于Windows上的 IIS服务器
  • .p12 常用于MAC OS、iOS中(PKCS#12由PFX进化而来的用于交换公共的和私有的对象的标准格式)
  • .jks Java Key Storage,这是Java的专利,JAVA的专属格式,一般用于 Tomcat 服务器。

2.不带私钥的证书:

  • .cer/crt 编码方式不一定,可能是DER也可能是PEM
  • .pem 都是PEM编码格式
  • .der 都是DER编码格式
  • .p7b 以树状展示证书链(certificate chain),同时也支持单个证书,不含私钥

3.补充

  • .der文件一般只放证书,不含私钥
  • .pem文件中可以放证书或者私钥,或者两者都有,pem如果只含私钥的话,一般用.key扩展名,而且可以有密码保护
  • .csr - Certificate Signing Request,即证书签名请求,这个并不是证书,而是向权威证书颁发机构获得签名证书的申请,其核心内容是一个公钥(当然还附带了一些别的信息),在生成这个申请的时候,同时也会生成一个私钥key,私钥要自己保管好。做过iOS APP的朋友都应该知道是怎么向苹果申请开发者证书的吧.

可以使用命令行工具、代码、在线网站等实现不同后缀格式、不同证书标准之间的转换,比如这个网站http://www.metools.info/

# 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

# 参考链接

  1. 很多的内容都来自这篇博客,增加了一些内容,并按照个人习惯整理了一下
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容