我很好奇,到目前为止我找不到解释。
在 RFC 5280 扩展中定义如下:
Extension ::= SEQUENCE {
extnID OBJECT IDENTIFIER,
critical BOOLEAN DEFAULT FALSE,
extnValue OCTET STRING
-- contains the DER encoding of an ASN.1 value
-- corresponding to the extension type identified
-- by extnID
}
为extnValue定义封装的OCTET_STRING,而不是直接将extnValue定义为“与extnID标识的扩展类型对应的ASN.1值的DER编码”的原因是什么?
谢谢。
不是权威答案,但我的想法是:这是因为扩展值可能有任意封闭标签,可以在外部模块中定义:
大多数扩展使用
SEQUENCE
,但有些不是,例如在给定的示例中,主题密钥标识符只是另一个OCTET_STRING
,密钥用法是一个BIT_STRING
。并且在基本类型定义中你必须使用固定标签来表示变量内容(ANY
)。
此外,解析器可能不知道如何解析特定的扩展,因此如果解析器不知道扩展类型,它们将其作为八位字节字符串读取,而不必深入挖掘。
更新 13.02.2023(基于评论):
关于类型/标签,根据我的理解,每个不同的类型都可以很容易地通过标签前导字节来识别,例如SEQUENCE=0x10,OCTET_STRING=0x04或BIT_STRING=0x03
你不能用变量标签定义字段,因为你引入了类型歧义。也就是说,
extnValue ANY
字段定义无效,因为它的类型是不确定的。当你定义一个类型时(在本例中,它是Extension
类型),所有字段都必须具有确定性标签。
extnValue 就是我们所说的规范孔。
它只是一个装任何东西的容器。
数据的接收者将不得不知道如何根据另一个规范来理解它(extnID 是找到这个规范的方法)
评论说它包含一个 ASN.1 值的 DER 编码......但它只是一个评论。
就我们而言,extnValue 只是字节,OCTET STRING 是承载字节(8 位)的最佳 ASN.1 类型。
过去,有一个名为 ANY 的(可怕的)类型就是这样做的:携带表示(未指定的)ASN.1 值的字节。但它在 1994 年被弃用,之后 x.509 v3 被考虑采用(1995 年)。
注:
使用 DER 转储器格式化数据(如 Crypt32 的回答)或使用 openssl 显示您的证书可以给您一种印象,即所有内容都已通过一次解码。
规范漏洞的工作方式,您的工具首先解码 Certificate 并获取每个扩展(漏洞)的字节。然后,一次一个,使用 extnID 指向的规范解码字节以获取扩展的值。