SKID 是什么 #
1999 的 RFC 2459 Internet X.509 Public Key Infrastructure Certificate and CRL Profile 中定义了 2 个 X509 v3 证书的扩展概念:
Authority Key Identifier
,简称AKI
/AKID
Subject Key Identifier
,简称SKI
/SKID
简单来说,它们是一种标识,对应的意义分别是:
- AKID,用来识别 被特定私钥签发的证书 – 应使用签发者(issuer)的公钥进行生成
- SKID,用来识别 包含特定公钥的证书 – 应使用证书中的公钥进行生成
所要确保的就是,证书 Y
中的 AKID,必然是签发证书 Y
的 CA 证书 X
的 SKID。
以上图 1 的证书路径/链条构造为例,Root CA 证书 1 的 SKID 就是 CA 证书 2 的 AKID,而 CA 证书 2 的 SKID 又是 CA 证书 3 中的 AKID。
RFC 明确要求所有被 CA 签发的下级证书都必须存在 AKID,只有 “自签发” 的证书才可以作为特例而省略填充这个字段。而 SKID 则是要求必须出现在 CA 证书中。
这两个扩展设计出来的意义主要是为了更方便的进行证书路径/链条的构建,通俗点说的话,就是给定一个被签发的证书 X
,可以通过其 AKID 快速的在 CA Pool 中找到签发它的 “Parent"。
这只是用来进行对象的快速查找,具体找到的关联对象是不是真的 “Parent” 还需要进行校验签名的判断。
想要用 SKID 查询证书的话可以去这里:crt.sh
具体 SKID 应该如何生成,标准中定义了两种 “常用方法”:
OpenSSL 在这个对文档进行补充的 提交 中专门说明了生成 SKID 的实现方法是按照 RFC 5280 的
4.2.1.2. (1)
,其实也就是 RFC 2459 的4.2.1.2. (1)
. 因为虽然 RFC 2459 逐步被新发布的 3280、5280 所淘汰,但是新 RFC 中关于 AKID、SKID 的这部分没什么变更。虽然没有去看具体的 C 代码,但我想既然是专门在文档补充这个细节,大概率表示 OpenSSL 应该一直都是使用这个方法进行 SKID 的生成。
其实标准中在 “常用方法” 的定义下紧接着说到 Other methods of generating unique numbers are also acceptable.
,但我不禁怀疑是否真的有使用自定义方法进行实现的软件。直到我偶然了解到 Go 中 SKID 的故事。
Go 中的故事 #
在 Golang 1.15 之前,标准库 x509
中的 CreateCertificate
方法不会对 CA 类型的证书自动的添加上 SKID
,这个行为明显是违反了 RFC 的要求。这个情况是在 2018 年被发现的:crypto/X509: add SubjectKeyId automatically when IsCA is true。按这个 issue 中的讨论看,Go 团队认为将其在 1.14 中修复是赶不上了,于是直到 2020 年 4 月才有了修复的提交。
然而,这个提交的代码实现是有点。。。 特别的。 作者选择直接将 SPKI 整个结构体 marshal 出的 bytes 进行 hash,并不是上面章节中提到的 RFC 定义的两种常用方法的任意一种。
虽然按 RFC 的意思,你搞自定义的也不是不可以。但要真按这个思路生成出来的证书,在与其他使用 RFC 的「常用方法」进行 SKID 生成的实现(比如 OpenSSL)进行交互时就很难说会不会产生意料之外的兼容性问题。
好在这个情况仅仅过了 2 个月就被发现:crypto/X509: SKID generation is over full spki,rather than just the subjectPublicKey,也赶在 1.15 正式发布前完成了修复。
可以看见最终是选择了第一种方法,对公钥的 bytes 做 SHA-1 的 HASH。
吐槽 #
比较难以想象,这是一个 2020 年 6 月 9 号才修复的问题,并且正式的 1.15 版本是 2020 年 8 月 11 号才发布的。
RFC 2459 是 1999 年的东西了。就算以 2008 年的 RFC 5280 做标准,在随后漫长的互联网产业扩张并「造福世界」的过程中,各大证书厂商/开源工具等对于 SKID 这个东西的操作可以说应该是已经相当成熟。
虽然 Golang 是一个比较年轻的语言,这也只是实现 RFC 标准的过程中出现的小瑕疵,不是什么很致命/关键的错误,但联想到之前的 OpenSSL Heartbleed 事件,是真的越是底层的基础设施就越是这样得不到该有的关注和投入,还是我太想当然了呢?