2015-07-02 86 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