2 java bouncycastle certificate ssl-certificate x509certificate
我正在使用:java.security.cert.X509Certificate程序包。和java.security.cert.X509CRL;
当我获得扩展值时,例如当OID = 2.5.29.14(它是SubjectKeyIdentifier)时, cert.getExtensionValue(“ 2.5.29.14”); 我得到此byte []范围:
[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的AuthorityKeyIdentifier ==证书的SubjectKeyIdentifier时,如果CRL是由此证书签名的),则是相同的:
[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个字节固定吗?解析的最佳方法是什么?
问题1的答案:这些字节是ASN 1数据结构的二进制表示。ASN 1(抽象语法表示法一)是ITU定义的标准,通常用于RFC /消息协议中以定义更高级别的数据结构(例如X.509证书)。
ASN 1具有由三元组(标签类型,长度,值)组成的基本语法。一些ASN 1标签允许元素嵌套。您的情况是
ASN 1 OCTET STRING(标签类型4),长度为22,其中包含一个
长度为20的ASN 1 OCTET STRING(字节数组中的第二个4)。
密钥标识符
问题2的答案:AuthorityKeyIdentifier的定义不同于SubjectKeyIdentifier(有关详细信息,请参阅RFC 5280)。在您的情况下,
长度为24的ASN 1 OCTET STRING,其中包含一个
长度为22的ASN 1构成的序列(ASN 1 SEQUENCE的标记类型为16,ASN 1构成为逻辑的标记类型32或“ red-> 16 + 32 = 48”)包含长度22
ASN 1上下文特定数据(标记类型128,导致-128转换为字节),长度为20
密钥标识符
数据结构不同于SubjectKeyIdentifier扩展,因为AuthorityKeyIdentifier扩展可以由证书的发行者和序列号组成,以用于验证当前证书。
在您的情况下,两个键标识符(字节数组的最后20个字节)相等。因此,您可以使用第一个问题中提到的证书来验证第二个问题中提到的CRL的签名(验证可以防止操纵的CRL)。
对问题3的回答:我强烈建议不要自己实施ASN 1。使用诸如Bouncycastle之类的库。为了正确地解析数据结构,您必须使用适当的类,尤其是对于Bouncycastle,没有便利类可以通过尽力而为的方法来确定ASN 1结构的类型。但是,这种方法几乎是不可能实现的。
例如,假设我们有字节数组[4,4,67,68,45,53]此数据(ASN 1 OCTET STRING)是否表示:
由于在ASN 1上定义的协议数量众多,因此不能说数据应该代表哪个对象。此外,假设所有列出的解释都是可能的(不是),通用库应该选择哪一种?再次假设此数据将是有效的JPEG图像和有效的LDAP消息。JPEG将具有诸如透明度,RGB颜色等等之类的东西。LDAP消息具有用于协议操作(BIND请求,BIND响应,SEARCH请求等)的ID,以及其他内容。您是否想进行一些棘手的操作,以从一种转换为另一种?
此外,数据可能表示的东西与我们奇妙的图书馆所猜测的完全不同。不幸的是,数据由于损坏的TCP包而损坏了,...。现在我们的图书馆无法给我们类似的信息
"Bad LDAP message, syntax violated by ..."
Run Code Online (Sandbox Code Playgroud)
因为它不小心将数据解析为完全合法的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());
Run Code Online (Sandbox Code Playgroud)
然后您可以调用
aki.getKeyIdentifier();
aki.getAuthorityCertIssuer();
aki.getAuthorityCertSerialNumber();
Run Code Online (Sandbox Code Playgroud)
进行进一步处理。