如果颁发者名称的编码不同但密钥验证通过,那么 X509 证书验证失败是否正确?
Is it correct to fail validation of a X509 certificate if the issuer Name is encoded differently but the Key validates?
这件事困扰了我一段时间。
通常当您在信任库中搜索另一个证书的颁发者证书以验证签名时,第一个想到的算法是通过散列证书的主题行来索引您的信任库,这样您可以散列发行人并快速找到它的证书。然后通过对一个发行者的 ASN.1 和另一个的 ASN.1 主题执行 memcmp() 来处理冲突;在检查实际签名之前。
但是,如果要检查的两个证书都是由同一实体颁发的,那是可以的,但是如果颁发者证书用于使用另一个软件创建另一个证书,并且在这个过程中更改了其中一个字段,会发生什么情况在发行人上,从 - 让我们说 - IA5string (0x16) 到 Printable (0x13),验证失败是否是正确的行为?
我的意思是,OID 和值不会改变,只是 ASN.1 编码,但结果将是找不到证书(错误的哈希值)并且不会验证。
这种行为是否正确?
证书理论上是有效的,因为它已经用正确的密钥签名,所以它确实有效:(即你首先计算 'tbsCertificate' 的散列,使用 public 的密钥发行人从 'signatureValue' 获取哈希,比较它们并确实验证它们是否匹配)。
我不知道的地方 - 虽然我没有详尽搜索 - 发行人有义务在发行人名称上使用与在发行人证书的主题名称上使用的编码完全相同的编码。实际上,RFC-5280 在第 4.1.2.4 节(发行者)中这样说:
When CAs have previously issued certificates with issuer fields with
attributes encoded using TeletexString, BMPString, or
UniversalString, then the CA MAY continue to use these encodings of
the DirectoryString to preserve backward compatibility.
Note that the word 'MAY' is in capitals, highlighting a free choice.
所以我认为这种自由是 OpenSSL 想出单行的原因,在名称被解码后比较名称,从而避免在搜索名称时出现编码问题。
但即使这样做在技术上是正确的,恕我直言,修改 issuerName 是不正确的,即使它在解码后仍然正确,因为它引入了很多可能用于查找哈希冲突的可能性,并且避免这种情况应该成为验证的一部分。这就是我问这个问题的原因。
我不是问你怎么看,我是问更有经验的人告诉我对错。
在这种情况下失败是正确的行为吗?
中指定的规则比较 DN
7.1. Internationalized Names in Distinguished Names
Representation of internationalized names in distinguished names is
covered in Sections 4.1.2.4, Issuer Name, and 4.1.2.6, Subject Name.
Standard naming attributes, such as common name, employ the
DirectoryString type, which supports internationalized names through
a variety of language encodings. Conforming implementations MUST
support UTF8String and PrintableString. RFC 3280 required only
binary comparison of attribute values encoded in UTF8String, however,
this specification requires a more comprehensive handling of
comparison. Implementations may encounter certificates and CRLs with
names encoded using TeletexString, BMPString, or UniversalString, but
support for these is OPTIONAL.
RFC接着详细解释了比较算法,但从上面我们可以看出,虽然在比较之前必须对字符串进行解码(即它不是二进制比较),但对弃用编码的支持是OPTIONAL
。因此,在这种情况下验证失败是一种有效的行为 - 某些实现可能会处理此问题,而其他实现可能不会。
这件事困扰了我一段时间。
通常当您在信任库中搜索另一个证书的颁发者证书以验证签名时,第一个想到的算法是通过散列证书的主题行来索引您的信任库,这样您可以散列发行人并快速找到它的证书。然后通过对一个发行者的 ASN.1 和另一个的 ASN.1 主题执行 memcmp() 来处理冲突;在检查实际签名之前。
但是,如果要检查的两个证书都是由同一实体颁发的,那是可以的,但是如果颁发者证书用于使用另一个软件创建另一个证书,并且在这个过程中更改了其中一个字段,会发生什么情况在发行人上,从 - 让我们说 - IA5string (0x16) 到 Printable (0x13),验证失败是否是正确的行为?
我的意思是,OID 和值不会改变,只是 ASN.1 编码,但结果将是找不到证书(错误的哈希值)并且不会验证。
这种行为是否正确?
证书理论上是有效的,因为它已经用正确的密钥签名,所以它确实有效:(即你首先计算 'tbsCertificate' 的散列,使用 public 的密钥发行人从 'signatureValue' 获取哈希,比较它们并确实验证它们是否匹配)。
我不知道的地方 - 虽然我没有详尽搜索 - 发行人有义务在发行人名称上使用与在发行人证书的主题名称上使用的编码完全相同的编码。实际上,RFC-5280 在第 4.1.2.4 节(发行者)中这样说:
When CAs have previously issued certificates with issuer fields with
attributes encoded using TeletexString, BMPString, or
UniversalString, then the CA MAY continue to use these encodings of
the DirectoryString to preserve backward compatibility.
Note that the word 'MAY' is in capitals, highlighting a free choice.
所以我认为这种自由是 OpenSSL 想出单行的原因,在名称被解码后比较名称,从而避免在搜索名称时出现编码问题。
但即使这样做在技术上是正确的,恕我直言,修改 issuerName 是不正确的,即使它在解码后仍然正确,因为它引入了很多可能用于查找哈希冲突的可能性,并且避免这种情况应该成为验证的一部分。这就是我问这个问题的原因。
我不是问你怎么看,我是问更有经验的人告诉我对错。
在这种情况下失败是正确的行为吗?
7.1. Internationalized Names in Distinguished Names
Representation of internationalized names in distinguished names is
covered in Sections 4.1.2.4, Issuer Name, and 4.1.2.6, Subject Name.
Standard naming attributes, such as common name, employ the
DirectoryString type, which supports internationalized names through
a variety of language encodings. Conforming implementations MUST
support UTF8String and PrintableString. RFC 3280 required only
binary comparison of attribute values encoded in UTF8String, however,
this specification requires a more comprehensive handling of
comparison. Implementations may encounter certificates and CRLs with
names encoded using TeletexString, BMPString, or UniversalString, but
support for these is OPTIONAL.
RFC接着详细解释了比较算法,但从上面我们可以看出,虽然在比较之前必须对字符串进行解码(即它不是二进制比较),但对弃用编码的支持是OPTIONAL
。因此,在这种情况下验证失败是一种有效的行为 - 某些实现可能会处理此问题,而其他实现可能不会。