3

我正在使用:java.security.cert.X509Certificate包。和java.security.cert.X509CRL;

当我得到扩展值时,例如当 OID=2.5.29.14 (它是 SubjectKeyIdentifier) cert.getExtensionValue("2.5.29.14"); 我得到这个字节 [] 范围:

[4,22,4,20, 5,125,-118,106,-44,108,39,-74,-108,-20,-27,-32,-113,64,-69,125,-8,102,-52,-24 ]

当我在证书中看到时, SubjectKeyIdentifier从 5 开始

问题1:这个范围的开始是什么?它是 4 个字节。

当我在 X509CRL 中看到 AuthorityKeyIdentifier 时(如果 CRL 由该证书签名,则 CRL 的 AuthorityKeyIdentifier == SubjectKeyIdentifier Of certificate)有相同的:

[4,24,48,22,-128,20, 5,125,-118,106,-44,108,39,-74,-108,-20,-27,-32,-113,64,-69,125,-8,102, -52,-24 ] 但开头还有 6 个字节。

问题2:这个范围的开始是什么?它是 6 个字节。

还有一个问题:

问题 3:如何解析 ExtensionValue 以便仅获取 Identifier 值。这个 4 和 6 字节是固定的吗?解析的最佳方法是什么?

4

2 回答 2

8

问题 1 的答案:这些字节是ASN 1数据结构的二进制表示。ASN 1(Abstract Syntaxt Notation One)是由ITU定义的标准,通常用于 RFC/消息协议中以定义更高级别的数据结构(例如 X.509 证书)。

ASN 1 具有由三元组(标签类型、长度、值)组成的基本语法。一些 ASN 1 标签允许嵌套元素。在你的情况下,你有一个

ASN 1 OCTET STRING(标签类型 4),长度为 22,其中包含
  ASN 1 OCTET STRING(字节数组中的第二个 4),长度为 20。
    密钥标识符

对问题 2 的回答:AuthorityKeyIdentifier 的定义与 SubjectKeyIdentifier 不同(详情请查看 RFC 5280)。在你的情况下,它是一个

ASN 1 个字节长度为 24 的字符串,其中包含一个
  ASN 1 CONSTRUCTED SEQUENCE(标签类型 16 用于 ASN 1 SEQUENCE,标签类型 32 用于 ASN 1 CONSTRUCTED 逻辑上或'red -> 16 + 32 = 48),长度为 22,其中包含
    长度为 20 的 ASN 1 上下文特定数据(标签类型 128,将 -128 转换为字节)
      密钥标识符

数据结构与 SubjectKeyIdentifier 扩展不同,因为 AuthorityKeyIdentifier 扩展也可以由证书的颁发者和序列号组成,用于验证当前证书。

在您的情况下,两个键标识符(字节数组的最后 20 个字节)是相等的。因此,您可以使用第一个问题中提到的证书来验证第二个问题中提到的 CRL 的签名(验证防止 CRL 被操纵)。

对问题 3 的回答:我强烈建议不要自己实施 ASN 1。使用诸如 Bouncycastle 之类的库。要正确解析数据结构,您必须使用适当的类,尤其是对于 Bouncycastle,没有便利类可以通过尽力而为的方法确定 ASN 1 结构的类型。然而,这种方法几乎不可能实施。

例如,假设我们有字节数组 [4,4,67,68,45,53] 此数据(ASN 1 OCTET STRING)是否表示:

  • LDAP 消息或
  • JPEG 或
  • 人类可读的字符串或
  • ...?

由于在 ASN 1 上定义的协议数量众多,因此无法说数据应该代表哪个对象。此外假设所有列出的解释都是可能的(它们不是)应该由通用库选择哪一个?再次假设该数据将是有效的 JPEG 图像和有效的 LDAP 消息。JPEG 将具有透明度、rgb 颜色等内容。LDAP 消息有一个协议操作的 id(BIND 请求、BIND 响应、SEARCH 请求……)和其他一些东西。您想进行一些棘手的位操作以从一种转换为另一种吗?

此外,数据可能应该代表与我们奇妙的库所猜测的完全不同的东西。不幸的是,由于 TCP 包损坏,数据已损坏,... 现在我们的图书馆不能给我们类似的消息

"Bad LDAP message, syntax violated by ..."

因为它不小心将数据解析为完全合法的 JPEG。

要解析显示的数据,例如使用 Bouncycastle(假设版本 1.51):

//retrieve the certificate from somewhere
X509Certificate c = ...;
String oid = Extension.authorityKeyIdentifier.getId();
byte[] extensionValue = c.getExtensionValue(oid);
ASN1OctetString akiOc = ASN1OctetString.getInstance(extensionValue);
AuthorityKeyIdentifier aki = AuthorityKeyIdentifier.getInstance(akiOc.getOctets());

然后你可以调用

aki.getKeyIdentifier();
aki.getAuthorityCertIssuer();
aki.getAuthorityCertSerialNumber();

用于进一步处理。

于 2015-03-25T10:12:44.110 回答
1

cert.getExtensionValue("2.5.29.14") 的返回是 OCTET STRING 的编码。

在 Bouncy Castle 中,您可以获得实际的编码值

byte[] octets = ASN1OctetString.getInstance(cert.getExtensionValue("2.5.29.14")).getOctets();

对于 SubjectKeyIdentifier,此值将是另一个编码的 OCTET STRING,因此您可以重复该过程(如使用 ASN1OctetString)或使用 SubjectKeyIdentifier.getInstance(octets)。可以对 AuthorityKeyIdentifier 遵循相同的过程。

如果您正在做很多此类事情,您可能还想查看 bcpkix 发行版中 org.bouncycastle.cert 中的类。持有者类的设计目的是使这种分析和处理更容易进行。

于 2013-05-29T07:01:46.307 回答