2015-07-02 20 views
6

Có ba chứng chỉ trong ví dụ của tôi, giả sử chúng tạo thành một chuỗi nhưng tôi vẫn chưa biết được trong số họ đã ký đó:Làm thế nào để biết được Giấy chứng nhận X509 Signed khác Certificate (Java)

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

tôi sẽ muốn biết chứng chỉ nào chịu trách nhiệm ký chứng chỉ khác.

Kế hoạch là lấy "AuthorityKeyIdentifier" và đối sánh nó với "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")); 

Im nhận được sau cho giấy chứng nhận (theo thứ tự của chuỗi): Tiêu đề/quyền cặp khóa ID

Giá trị của SubjectKeyIdentifier và AuthorityKeyIdentifier sau khi giải mã:

Certificate 1: (cuối của chuỗi)

#0416041482b7384a93aa9b10ef80bbd954e2f10ffb809cde 
#04183016801482b7384a93aa9b10ef80bbd954e2f10ffb809cde 

Certificate 2: Có chữ ký của Giấy chứng nhận 1

01.
#04160414ab8059c365836d1d7d13bd19c3ec1a8f0d476aa3 
#04183016801482b7384a93aa9b10ef80bbd954e2f10ffb809cde 

Giấy chứng nhận 3: Có chữ ký của Giấy chứng nhận 2

(no SubjectKeyIdentifier - null bytes) 
#041830168014ab8059c365836d1d7d13bd19c3ec1a8f0d476aa3 

định dạng và Aligned cho dễ đọc (Cùng một điều là một trong những ngày đầu)

------------------------------------------------------------------------------ 
     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 

tôi đã mong AuthorityKeyIdentifier c3 để tương đương với c) SubjectKeyIdentifier của c2. mà dường như không phải là trường hợp ở đây.

EDIT: một số phần của kết quả dường như khớp, tôi có một số ý tưởng về "SubjectKeyIdentifier" - nó luôn bắt đầu bằng '# 04' theo sau là độ dài của nội dung (tính bằng hex). Bây giờ tôi có một ý tưởng nhất định về cách giải mã "SubjectKeyIdentifier", nhưng "AuthorityKeyIdentifier" vẫn là một bí ẩn lớn đối với tôi.

liên quan SO post

Did tôi làm điều gì sai trái với việc giải mã? Tại sao AuthorityKeyIdentifier không khớp chính xác với SubjectKeyIdentifier của chứng chỉ đã ký?

+0

Bạn có thể tự đăng các chứng chỉ để chúng tôi phân tích không? – frasertweedale

Trả lời

4

Nếu bạn có một cái nhìn vào định nghĩa ASN.1 của SKI và AKI trong RFC5280 (theo các liên kết trong câu hỏi của bạn) Sự khác biệt trở nên rõ ràng:

SubjectKeyIdentifier ::= KeyIdentifier 

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

KeyIdentifier ::= OCTET STRING 

Vì vậy, AKI không phải là một STRING OCTET , nhưng SEQUENCE của ba yếu tố tùy chọn. Một trong những phần tử này là chuỗi octet có thể được so sánh với một SKI.

Các Distinguished Encoding Rules (DER) xác định biểu diễn byte của các cấu trúc ASN.1 này. Các byte riêng lẻ của một phần mở rộng AKI có ý nghĩa như sau (xem 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 

Hai byte đầu tiên (04 18) là một phần của cấu trúc mở rộng (như đã giải thích trong câu hỏi có liên quan Why doesn't my key identifier match?), thực tế AKI nội dung mở rộng bắt đầu tại "30 16".

Mã của bạn Java để giải mã các AKI sẽ giống như thế này (sử dụng Bouncy Castle):

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)); 

Và để giải mã 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)); 

Ngoài ra, cả hai phần mở rộng là không bắt buộc. Nếu mã của bạn nên làm việc với các chứng chỉ tùy ý, thì cơ chế dự phòng là cần thiết (như xác minh chữ ký).

+0

cảm ơn bạn đã trả lời rất chi tiết. một đồng đội đã tìm ra điều này ngày hôm qua, đây chính là lời giải thích mà tôi có. chấp nhận như là câu trả lời. Tôi vẫn còn mới với việc sử dụng các mô-đun mã hóa/bảo mật của java và nó bắt đầu có ý nghĩa bây giờ. – CobraEnergyDrink

+0

Không chỉ là dự phòng, bạn nên luôn kiểm tra child.Issuer bằng parent.Subject; hoạt động ngược trở lại v1 và không có phần mở rộng nào cả. AKI/SKI * nếu hiện tại * phải là một kiểm tra bổ sung và có thể giúp nơi một CA có nhiều hơn một chứng nhận (mặc dù thường là nhiều chứng chỉ cho một khóa, chứ không phải chứng chỉ cho nhiều khóa). –

0

Nếu bạn đang tìm kiếm một kiểm tra thực sự nhanh chóng, chỉ cần mở chứng chỉ trong cửa sổ và tìm một tab có tên "Đường dẫn chứng nhận". Nó cũng cho phép bạn dễ dàng duyệt qua chuỗi chứng chỉ nếu có. (Tôi đã đăng một bức ảnh, nhưng dường như chưa có đủ danh tiếng.)

+0

xin lỗi, nhưng tôi cần một cái gì đó trong mã. – CobraEnergyDrink

Các vấn đề liên quan