2010-07-02 49 views
7

Cần trợ giúp về các thủ tục mã hóa trong Java.Xác minh chứng chỉ PKCS # 7 trong Java

Với chữ ký PKCS # 7, tôi muốn xác minh tất cả chứng chỉ có chứa một cửa hàng đáng tin cậy. Tôi giả định rằng tất cả các chứng chỉ có trong chữ ký đều đúng thứ tự để tạo đường dẫn chứng chỉ hợp lệ (hoặc chuỗi, bất kỳ thứ gì), sao cho

  • trên cùng (# 0) là chứng chỉ ký;
  • tiếp theo (# 1) là chứng chỉ trung gian, được sử dụng để ký # 0;
  • tiếp theo (# 2) là một chứng chỉ trung gian khác, được sử dụng để ký # 1;
  • v.v.

Chứng chỉ cuối cùng (#N) được ký bởi CA.

Đó là những gì tôi đã được quản lý để hack cho đến nay:

// Exception handling skipped for readability 

//byte[] signature = ... 
pkcs7 = new PKCS7(signature); // `sun.security.pkcs.PKCS7;` 

// *** Checking some PKCS#7 parameters here 

X509Certificate prevCert = null; // Previous certificate we've found 
X509Certificate[] certs = pkcs7.getCertificates(); // `java.security.cert.X509Certificate` 
for (int i = 0; i < certs.length; i++) { 
    // *** Checking certificate validity period here 

    if (cert != null) { 
     // Verify previous certificate in chain against this one 
     prevCert.verify(certs[i].getPublicKey()); 
    } 
    prevCert = certs[i]; 
} 

//String keyStorePath = ... 
KeyStore keyStore = KeyStore.getInstance("JKS"); // `java.security.KeyStore` 
keyStore.load(new FileInputStream(keyStorePath), null); 

// Get trusted VeriSign class 1 certificate 
Certificate caCert = keyStore.getCertificate("verisignclass1ca"); // `java.security.cert.Certificate` 

// Verify last certificate against trusted certificate 
cert.verify(caCert.getPublicKey()); 

Vậy câu hỏi được - cách này có thể được thực hiện bằng các lớp Java chuẩn như CertPath và bạn bè? Tôi có một cảm giác mạnh mẽ rằng tôi đang tái phát minh ra một chiếc xe đạp. Hoặc, nếu ai đó có một ví dụ với thư viện BouncyCastle, điều đó cũng sẽ ổn.

Câu hỏi thưởng: cách xác minh chứng chỉ đối với một cửa hàng đáng tin cậy để chứng chỉ gốc được chọn tự động?

+0

bạn biết bạn không được phép sử dụng các lớp học từ mặt trời. *, Phải không? –

+0

Yup. Tôi chỉ tìm thấy đây là cách dễ nhất để trích xuất chứng chỉ từ phong bì CMS. Nhưng tôi đoán tôi thực sự nên chuyển sang BouncyCastle, thậm chí xem xét một sự phụ thuộc thêm. – hudolejev

Trả lời

12

Tìm thấy giải pháp cho bản thân. Vì vậy, dưới đây là cách người ta có thể giải nén và kích hoạt một chuỗi chứng chỉ chống lại các cửa hàng tin cậy (xử lý ngoại lệ bỏ qua cho dễ đọc):

CertificateFactory cf = CertificateFactory.getInstance("X.509"); 

// Get ContentInfo 
//byte[] signature = ... // PKCS#7 signature bytes 
InputStream signatureIn = new ByteArrayInputStream(signature); 
DERObject obj = new ASN1InputStream(signatureIn).readObject(); 
ContentInfo contentInfo = ContentInfo.getInstance(obj); 

// Extract certificates 
SignedData signedData = SignedData.getInstance(contentInfo.getContent()); 
Enumeration certificates = signedData.getCertificates().getObjects(); 

// Build certificate path 
List certList = new ArrayList(); 
while (certificates.hasMoreElements()) { 
    DERObject certObj = (DERObject) certificates.nextElement(); 
    InputStream in = new ByteArrayInputStream(certObj.getDEREncoded()); 
    certList.add(cf.generateCertificate(in)); 
} 
CertPath certPath = cf.generateCertPath(certList); 

// Load key store 
//String keyStorePath = ... 
KeyStore keyStore = KeyStore.getInstance("JKS"); 
keyStore.load(new FileInputStream(keyStorePath), null); 

// Set validation parameters 
PKIXParameters params = new PKIXParameters(keyStore); 
params.setRevocationEnabled(false); // to avoid exception on empty CRL 

// Validate certificate path 
CertPathValidator validator = CertPathValidator.getInstance("PKIX"); 
CertPathValidatorResult result = validator.validate(certPath, params); 

validate() sẽ ném một ngoại lệ nếu xác nhận thất bại.

Tài liệu: ASN1Set, ContentInfo, SignedData. Tất cả các tên kỳ lạ và tài liệu có liên quan khác có thể được tìm thấy trong java.security.cert.

Không phụ thuộc vào SUN ở đây, chỉ cần BouncyCastle provider library.

This câu hỏi (và đặc biệt là câu trả lời) cũng có thể hữu ích.

+0

Rất, rất tốt! xin chúc mừng, bạn tình –

2

Bạn muốn CertificateFactory. Ví dụ cuối cùng trong javadocs thực hiện chính xác những gì bạn muốn.

+0

Không chính xác. Ví dụ cuối cùng xây dựng một danh sách các chứng chỉ từ blob được mã hóa chứa các chứng chỉ * only *. Những gì tôi có là một cấu trúc 'SignedData' chứa danh sách chứng chỉ * là một trong các trường * mà tôi phải trích xuất trước tiên. Dù sao, 'CertificateFactory.generateCertPath()' có vẻ là con đường để đi. Cảm ơn rất nhiều. – hudolejev

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