2015-07-02 112 views
6

有在我的例子三个证,假设它们形成一个链条,但我还不知道他们签署了:如何知道哪些X509证书签名的另一个证书(JAVA)

X509Certificate c1 = .... 
X509Certificate c2 = .... 
X509Certificate c2 = .... 

我会喜欢知道哪个证书负责签署其他证书。

该计划是要获得“AuthorityKeyIdentifier”并将其与“SubjectKeyIdentifier”匹配。

import org.bouncycastle.asn1. DEROctetString; 

private static String decodeKey(byte[] e) { 
    DEROctetString octet = new DEROctetString(e); 
    return octet.toString(); 
} 

String subjectKeyId = decodeKey(c.getExtensionValue("2.5.29.14")); 
String authorityKeyId = decodeKey(c.getExtensionValue("2.5.29.35")); 

即时得到的证书以下(在链中的顺序):主体/权限密钥ID对

的执行subjectKeyIdentifier和执行authorityKeyIdentifier的值进行解码后:

证书1:(端链

#0416041482b7384a93aa9b10ef80bbd954e2f10ffb809cde 
#04183016801482b7384a93aa9b10ef80bbd954e2f10ffb809cde 

的)证书2:由证书1

签名
#04160414ab8059c365836d1d7d13bd19c3ec1a8f0d476aa3 
#04183016801482b7384a93aa9b10ef80bbd954e2f10ffb809cde 

证书3:证书2

(no SubjectKeyIdentifier - null bytes) 
#041830168014ab8059c365836d1d7d13bd19c3ec1a8f0d476aa3 

格式化并对齐,方便阅读(同样的事情,在顶部的一个)

------------------------------------------------------------------------------ 
     01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 
------------------------------------------------------------------------------ 
Certificate 1 
#04 16 04 14  82 b7 38 4a 93 aa 9b 10 ef 80 bb d9 54 e2 f1 0f fb 80 9c de 
#04 18 30 16 80 14 82 b7 38 4a 93 aa 9b 10 ef 80 bb d9 54 e2 f1 0f fb 80 9c de 

Certificate 2 
#04 16 04 14  ab 80 59 c3 65 83 6d 1d 7d 13 bd 19 c3 ec 1a 8f 0d 47 6a a3 
#04 18 30 16 80 14 82 b7 38 4a 93 aa 9b 10 ef 80 bb d9 54 e2 f1 0f fb 80 9c de 

Certificate 3 
=== == == == == == == == == == == NO DATA == == == == == == == == == == == == 
#04 18 30 16 80 14 ab 80 59 c3 65 83 6d 1d 7d 13 bd 19 c3 ec 1a 8f 0d 47 6a a3 

签名我期待C3的执行authorityKeyIdentifier等同于c2的SubjectKeyIdentifier。这似乎并非如此。编辑:结果的某些部分似乎匹配,我对“SubjectKeyIdentifier”有一些想法 - 它始终以'#04'开始,后面跟着内容的长度(以十六进制表示)。我现在对如何解码“SubjectKeyIdentifier”有一定的想法,但“AuthorityKeyIdentifier”对我来说仍然是一个很大的谜团。

相关 SO post

难道我做错任何事与解码? AuthorityKeyIdentifier为什么与对其签名的证书的SubjectKeyIdentifier不正确匹配?

+0

您可以发布证书本身供我们分析吗? – frasertweedale

回答

4

如果你看一看SKI和AKI的RFC5280的ASN.1定义(以下在你的问题中的链接)的差异变得明显:

SubjectKeyIdentifier ::= KeyIdentifier 

AuthorityKeyIdentifier ::= SEQUENCE { 
    keyIdentifier    [0] KeyIdentifier   OPTIONAL, 
    authorityCertIssuer  [1] GeneralNames   OPTIONAL, 
    authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } 

KeyIdentifier ::= OCTET STRING 

所以,AKI不是字节串,而是三个可选元素的序列。其中一个元素是可以与SKI进行比较的八位组串。

Distinguished Encoding Rules (DER)确定这些ASN.1结构的字节表示形式。的AKI延伸的各个字节的含义如下(见A Layman's Guide to a Subset of ASN.1, BER, and DER):

04 18 30 16 80 14 82 b7 38 4a 93 aa 9b 10 ef 80 bb d9 54 e2 f1 0f fb 80 9c de 

04 OCTET STRING 
18 LENGTH 
30 SEQUENCE 
16 LENGTH 
80 CONTEXT-SPECIFIC PRIMITIVE TAG 0 
14 LENGTH 
.. DATA 

的前两个字节(04 18)的扩展的结构(如在相关的问题Why doesn't my key identifier match?解释)的一部分,实际AKI扩展内容以“30 16”开头。用于解码AKI应该是这样的(使用充气城堡)

Java代码:

byte[] extensionValue = cert.getExtensionValue("2.5.29.35"); 
byte[] octets = DEROctetString.getInstance(extensionValue).getOctets(); 
AuthorityKeyIdentifier authorityKeyIdentifier = AuthorityKeyIdentifier.getInstance(octets); 
byte[] keyIdentifier = authorityKeyIdentifier.getKeyIdentifier(); 
String keyIdentifierHex = new String(Hex.encode(keyIdentifier)); 

而对于解码SKI:

extensionValue = cert.getExtensionValue("2.5.29.14"); 
octets = DEROctetString.getInstance(extensionValue).getOctets(); 
SubjectKeyIdentifier subjectKeyIdentifier = SubjectKeyIdentifier.getInstance(octets); 
keyIdentifier = subjectKeyIdentifier.getKeyIdentifier(); 
keyIdentifierHex = new String(Hex.encode(keyIdentifier)); 

而且,这两个扩展是可选的。如果您的代码可以使用任意证书,则需要回退机制(如验证签名)。

+0

谢谢你的非常详细的答案。一个队友昨天就明白了这一点,这正是我得到的解释。被接受为答案。我仍然使用Java的加密/安全模块,并且现在开始有意义。 – CobraEnergyDrink

+0

不只是作为后备,你应该经常检查child.Issuer等于parent.Subject;可以回到v1​​,完全没有扩展。 AKI/SKI *如果存在的话*应该是额外的检查,并且可以帮助一个CA拥有多个证书(尽管这通常是针对一个密钥的多个证书,而不是针对多个密钥的证书)。 –

0

如果您正在寻找一个非常快速的检查,只需在Windows中打开证书并寻找一个名为“认证路径”的选项卡。它还可以让您轻松遍历证书链(如果适用)。 (我会张贴一张图片,但显然还没有足够的声望。)

+0

对不起,但我需要代码。 – CobraEnergyDrink