密钥/证书的编码

概述

参考:

当我们生成密钥后,是不易于保存的,比如我在 go 代码,使用 RSA 算法生成了这么一个密钥:

私钥中包含里 公钥、n、d、组件,公钥中包含 n、e。可以发现,这种数据是不便于保存与共享的。所以,一般情况是使用一种 Encoding(编码) 规则,对密钥进行处理后以生成某种格式的文件,以便保存。当需要使用密钥时,使用对应规则的来 Decoding(解码) 该文件以获得密钥,然后再开始使用。而现阶段最常用的文件就是,就是 PEM 文件格式

除了可以对密钥编码,还可以对证书进行编码,证书由于其复杂的格式,也不利于传输。

如果用 openssl 命令查看私钥,则是下面这种格式

root@desistdaydream:~/projects/DesistDaydream/GoLearning# openssl rsa -text -noout -in cryptography/private.pem
RSA Private-Key: (2048 bit, 2 primes)
modulus:
    00:d0:94:1c:6e:25:54:61:1d:34:23:1f:25:f7:a5:
    ......
publicExponent: 65537 (0x10001)
privateExponent:
    00:bb:fe:52:e5:9f:f5:be:96:30:d0:db:19:40:6d:
 ......
prime1:
    00:f3:06:5f:c4:e6:27:d2:1d:ba:d1:35:40:34:b1:
 ......
prime2:
    00:db:b6:ee:09:28:3c:53:f5:70:e7:9a:11:8b:55:
 ......
exponent1:
    3b:17:1e:ac:22:86:26:29:c2:65:e1:fb:c5:94:3e:
 ......
exponent2:
    00:a4:a5:5d:95:61:20:6c:2e:36:30:68:45:13:6b:
 ......
coefficient:
    00:e3:ed:7a:4a:2d:4c:ec:e0:0d:77:e8:4e:df:9b:
 ......

PEM 文件格式

参考:

Privacy-Enhanced Mail(增强隐私的邮件,简称 PEM) 是一种文件的格式(虽然曾经不止代表文件格式)。这种格式的文件用于存储 加密的密钥、证书 等数据。

PEM 起源于 1993 年 IETF 定义“隐私增强邮件”的一组标准,尽管这个标准未得到广泛采用,并已被 PGP 和 S/MIME 取代,但其中定义的各种文本编码格式却变得非常流行。所以,PEM 这种文件编码格式最终由 IETF 在 RFC7468 中正式定义。

PEM 格式

PEM 格式的内容由两部分组成

  • Type(类型) # 用来表示 Contents(内容) 是什么,是 密钥 还是 证书 等等,同时也用来定位 Contents(内容) 在 PEM 格式文件中的位置。
    • 类型以 -----BEGIN 标签-----作为开头第一行,并以----- END 标签 -----作为结尾最后一行。其中的标签用来确定编码消息的类型,也就是说,标签用来表示该 PEM 格式的文件的作用是什么。标签包括以下几种:
      • CERTIFICATE # 证书
      • CERTIFICATE REQUEST # 证书请求
      • PRIVATE KEY# 私钥
      • PUBLIC KEY # 公钥
      • X509 CRL #
      • 等等等等,很多
    • 标签中还可以添加其他标识符,只要保证标签中具有上述字符串即可。
  • Contents(内容) # 密钥或证书的具体内容。
    • Contents 是 密钥、证书等数据 转换为 Bytes(字节流) 后,使用 Base64 对这些 Bytes 进行编码 得到的结果。
    • 注意:现在这个时代(本文写于 2020 年)由于 PKCS 这种规范标准。一般情况下,Contents 必须符合 PKCS 这种标准,所以 密钥证书 并不会直接转换为 Bytes。一般情况下,是先使用 ASN.1 的 DER(或其他规则) 将 证书、密钥 等数据 编码为 Bytes 类型数据。然后再使用 Base64 对这些 Bytes 数据 进行编码得到字符串类型数据。
      • 也就是说 证书或密钥 转换为 PCKS#X 标准(X 是数字),然后使用 Base64 编码得到 Contents(内容)。而常用的 PCKS#X 标准一般都是用的 ASN.1 的 DER 规则进行编码。
        • 再深入一些的话,可以这么描述,Contents(内容) 可以是使用 Base64 对符合 PKCS#1 标准格式的数据进行编码后得到的字符串
          • 而 PKCS#1 标准实际上指的是使用 ASN.1 的 DER 编码规则对公钥和私钥编码。由于编码后通常是 Bytes 类型的数据,所以需要再使用 Base64 编码得到便于传递的字符串类型的数据。
        • 一般写为 PCKS#1, ASN.1 DERPCKS#8, ASN.1 DER 等等。逗号前面是标准名称,逗号后面是符合该标准的编码规则

PEM 格式的数据文件通常以 .pem.cer.crt.key 结尾。其中 .ert 和 .crt 常用来表示证书、.key 常用来表示密钥(公钥或私钥)

PEM 文件中的标签比文件后缀更准确地表示数据类型,因为可以将许多不同类型的数据保存在 .pem 文件中。

PEM 格式文件示例

# 私钥
-----BEGIN RSA PRIVATE KEY-----
kXxvLDA91VHVdTmRCYPWDOlNCbUi6S42KHmN2RukRM/Y0wMxHvlN7hnYCTrv8nEk
KcKJ9XNJAlWxETUe6hYQbvU6JtgIwPav38ZF2IqqdJF/v5EsQd1mg8PI3dqaGFNn
wc2osmNP4FN4sz57P1ifsNWobVwvol0VLvuF5zfjvlNzr7YuNGxr/Uu/pQVukQFf
8u0mmi7AZdzjdfsphW0Zi4fil3hI5m8HbTsbhfT53TofKt4nRZA/DUCCu6+/NHEW
ntY5STMyU0DQW8hasD9DfF9RiSVKm4Unn8TQ6yMFNQXCX5Sg3vgduMz8TUkT1KM3
WnwX9X5IO5WeA72dsVOXgQ==
-----END RSA PRIVATE KEY-----
# 公钥
-----BEGIN RSA PUBLIC KEY-----
0JUbBOzKiYp/0MXhux8XH0SxWBfnzCATH4oGvDj5SD6H2z1m97mkpRhRMul4l8vM
Lhgf2rWHsVHq5FjMeRVigOIIlHyjOFurigZ7pcVqWzHYIck6cGsI4JtEBNuqQ9EM
NyMYGpcV+TV0bw9nTUK//Fst++dueWVLmqlKTCbFQRmo2lxwKzXqKjJkSgxge/gh
MvC4/xh1Keizzlm73pAnOVhTow+HW5Wgas+maPXMaNcpJ8RryFlG6ke3CBaNqrV8
iheO4riYPZQWQkl8NGLlJyXeq/awl6ovbshyZcO45faoDMxl/J93+sczW1ZlF/1B
QKUvQGEsNFsT7YAejZvh7w==
-----END RSA PUBLIC KEY-----

DER 编码规则

参考:

Distinguished Encoding Rules(专用编码规则,简称 DER) 是 BER 的一种受限制变体,用于为 ASN.1 所描述的数据结构生成明确的传输语法。像 CER 一样,DER 编码是有效的 BER 编码。 DER 与 BER 相同,只是删除了一个发送者的所有选项。

用白话说: DER 是一种以二进制形式编码 ASN.1 语法的方法

DER,是对 ASN.1 这种语言进行编码的一种规则,也是最常用的一种。所谓对某种语言编码,就是类似编译器的效果。所以也可以称为 ASN.1 的 DER 规则

X.690 标准

是 ITU-T 标准,指定了几种 ASN.1 编码格式

ASN.1 与 PEM 的关系

参考:

PEM 编码 与 ASN.1 及其 编码/解码器 完全无关。但是由于编码后的 ASN.1 数据通常是二进制的,也就是 Bytes(字节流) 类型的数据,所以经常使用 PEM 对这些编码后的 ASN.1 数据再次进行编码,以获得人类可读的字符串类型数据。这可以帮助再文本编码敏感的媒体(比如 SMTP 服务)上进行传输以及复制和粘贴。

PKCS(非对称加密标准)

参考:

Public Key Cryptography Standards(非对称加密标准,简称 PKCS)。在密码学中,PKCS代表“公钥密码学标准”。这些是 RSA Security LLC 从 1990 年代初开始设计和发布的一组 公开密钥加密密钥加密 标准。该公司发布了这些标准,以促进他们拥有专利的加密技术的使用,例如 RSA 算法,Schnorr 签名算法以及其他几种。尽管不是行业标准(因为公司保留了对它们的控制权),但近年来有些标准[何时?]已开始进入“标准轨道”相关标准组织的流程,例如 IETF 和 PKIX 工作组。

注意:很多标准已经被废弃,所以下文看到的标准的编号不是连续的,比如 2、4、13、14 等等标准,就没有了,现在最常用的是 1、8 号标准

PKCS 的起源

X.509 只是一种常用的证书格式,但有人觉得这种格式能装的信息不够多,因此 又定义了一些比 X.509 更大的数据结构(但仍然用 ASN.1), 能将证书、秘钥以及其他东西封装(打包)到一起。因此,有时说我需要“一个证书”时,其 实真正说的是包(package)中包含的那个“证书”(a certificate in one of these envelopes),而不是这个包本身。

PKCS#1 - RSA 密码学标准

参见 RFC 8017。该标准定义了 RSA 公钥和私钥的数学属性和格式(这个密钥对是使用 ASN.1 的编码规则编码后的结果)。此外,还定义了执行 RSA 加密、解密、签名、验签的基本算法。

PKCS#3 - Diffie-Hellman 密钥协商标准

一种加密协议,允许彼此不具有先验知识的两个方通过不安全的通信通道共同建立共享的秘密密钥。

PKCS#5 - 基于密码的加密标准

参见 RFC 8018 和 PBKDF2。

PKCS#7 - 加密消息语法标准

参见 RFC 2315。用于在 PKI 下对消息进行签名和/或加密。也用于证书分发(例如,作为对 PKCS#10 消息的响应)。形成了 S / MIME 的基础,S / MIME 于 2010 年基于 RFC 5652(一种更新的加密消息语法标准(CMS))建立。通常用于单点登录。

PKCS#8 - 私钥内容的标准语法

注意:

  • 该标准仅定义了私钥的标准,一般情况下,对应的公钥标准一般是 PKIX。
  • 该标准不仅定义了 RSA 算法的密钥的标准,还定义了其他算法的标准。而 PKCS#1 仅定义了 RSA 算法密钥的标准。

参见 RFC 5958。用于携带私有证书密钥对(加密或未加密)。

PKCS#9 - 所选属性类型

参见 RFC 2985。

定义用于 PKCS#6 扩展证书,PKCS#7 数字签名消息,PKCS#8 私钥信息和 PKCS#10 证书签名请求中使用的所选属性类型。

PKCS#10 - 认证请求标准(证书请求 CSR 的标准)

参见 RFC 2986。发送到 CA 以请求公钥认证的消息格式。请参阅证书签名请求。

PKCS#11 - 加密令牌接口

也称为“ Cryptoki”。一个 API,用于定义加密令牌的通用接口(另请参阅硬件安全模块)。常用于单点登录,公共密钥加密和磁盘加密[10]系统。

RSA Security 已将 PKCS#11 标准的进一步开发移交给了 OASIS PKCS 11 技术委员会。

PKCS#12 - 个人信息交换语法标准

参见 RFC 7292。定义一种文件格式,通常用于存储私有密钥以及随附的公共密钥证书,并使用基于密码的对称密钥进行保护。

PFX 是 PKCS#12 的前身。

此容器格式可以包含多个嵌入式对象,例如多个证书。通常使用密码进行保护/加密。可用作 Java 密钥库的格式,并在 Mozilla Firefox 中建立客户端身份验证证书。可用于 Apache Tomcat。

PKCS#15 - 密码令牌信息格式标准

定义一个标准,允许加密令牌的用户向应用程序标识自己,而与应用程序的 Cryptoki 实现(PKCS#11)或其他 API 无关。RSA 放弃了本标准中与 IC 卡相关的部分,使其符合 ISO / IEC 7816-15。[14]


最后修改 May 13, 2024: tailscale, jq, clearup (4e49da16)