2017-05-10 1 views
3

여전히 암호화에 멍청한 사람입니다. 나는 매일 간단한 일을 당황하게됩니다. 그리고 오늘은 그 당시의 시대 중 하나입니다.엔드 엔티티의 루트 인증서와 중간 인증서를 얻는 것

jounessy 성 도서관으로 자바에서 smime 메시지를 확인하고 싶습니다. 거의 생각 났지만 지금은 PKIXparameters 객체를 만드는 것이 문제입니다. 나는 다음과 같은 구조의 최종 엔티티 X509Certificate에 있고, 이제 가정 해 봅시다 :

내가 먼저 신뢰의 체인을 구축해야합니다,하지만 난 루트 및 중간을 추출하는 방법을 알아낼 수 없습니다 메시지를 확인하기 위해
root certificate 
+->intermediate certificate 
    +->end-entity certificate 

최종 엔티티의 인증서. 난 그냥 단지 엔드 엔티티를 사용할 수

validation failed on certificate number -1, details: Trust anchor for certification path not found. 

그리고 BTW :

내가 루트로 엔드 엔티티를 사용하여 시도했지만 작동하지 않았다 :

InputStream isCert = GetFISCertificate(); 

List list = new ArrayList(); 
X509Certificate rootCert = (X509Certificate) certificateFactory.generateCertificate(isCert); 
list.add(rootCert); 
CollectionCertStoreParameters params = new CollectionCertStoreParameters(list); 
CertStore store = CertStore.getInstance("Collection", params, BC); 

//create cert path 
List certChain = new ArrayList(); 
certChain.add(rootCert); 
CertPath certPath = certificateFactory.generateCertPath(certChain); 
Set trust = Collections.singleton(new TrustAnchor(rootCert, null)); 

//validation 
CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX", BC); 
PKIXParameters pKIXParameters = new PKIXParameters(trust); 
pKIXParameters.addCertStore(store); 
pKIXParameters.setDate(new Date()); 
try { 
CertPathValidatorResult result = certPathValidator.validate(certPath, pKIXParameters); 
System.out.println("certificate path validated"); 

} catch (CertPathValidatorException e) { 
System.out.println("validation failed on certificate number " + e.getIndex() + ", details: " + e.getMessage()); 
} 

이 예외가있어 자체 서명 인증서 인 것처럼 메시지의 유효성을 검사하는 인증서?

답변

4

나는이 테스트에 BouncyCastle 1.56을 사용했습니다.

최종 엔티티에서 발급자의 인증서를 얻는 한 가지 방법은 Authority Information Access extension입니다.

이 확장 존재할 수 (의무화 아니다)과 은 발행자의 인증서 (발행는 현재 "위의"인증서입니다 얻을 수있는 URL을 포함 할 수 있으므로 최종 엔티티의 발행자가 중간입니다 , 중간 발행자가 루트 임).

당신은 BouncyCastle 함께이 확장 값을 얻을 수 있습니다 :

import java.security.cert.X509Certificate; 
import org.bouncycastle.asn1.x509.AccessDescription; 
import org.bouncycastle.asn1.x509.AuthorityInformationAccess; 
import org.bouncycastle.asn1.x509.Extension; 
import org.bouncycastle.asn1.x509.GeneralName; 
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; 
import org.bouncycastle.jce.provider.BouncyCastleProvider; 
import org.bouncycastle.x509.extension.X509ExtensionUtil; 

X509Certificate cert = // end entity certificate 

// get Authority Information Access extension (will be null if extension is not present) 
byte[] extVal = cert.getExtensionValue(Extension.authorityInfoAccess.getId()); 
AuthorityInformationAccess aia = AuthorityInformationAccess.getInstance(X509ExtensionUtil.fromExtensionValue(extVal)); 

// check if there is a URL to issuer's certificate 
AccessDescription[] descriptions = aia.getAccessDescriptions(); 
for (AccessDescription ad : descriptions) { 
    // check if it's a URL to issuer's certificate 
    if (ad.getAccessMethod().equals(X509ObjectIdentifiers.id_ad_caIssuers)) { 
     GeneralName location = ad.getAccessLocation(); 
     if (location.getTagNo() == GeneralName.uniformResourceIdentifier) { 
      String issuerUrl = location.getName().toString(); 
      // http URL to issuer (test in your browser to see if it's a valid certificate) 
      // you can use java.net.URL.openStream() to create a InputStream and create 
      // the certificate with your CertificateFactory 
      URL url = new URL(issuerUrl); 
      X509Certificate issuer = (X509Certificate) certificateFactory.generateCertificate(url.openStream()); 
     } 
    } 
} 

그래서 당신이 중간을 얻기 위해 최종 엔티티 인증서로이 코드를 사용할 수 있습니다. 그런 다음 중급과 함께 다시 사용하여 루트를 얻습니다.

그런 다음 루트TrustAnchor에 추가하면 유효성 검사가 작동합니다.


참고 : 내가 말했듯이는하지만,이 확장은 필수하지 않고 존재하지 않을 수 있습니다. 이 경우 getExtensionValuenull을 반환하며 Google에서 인증서를 검색하고 다운로드하는 것만 가능합니다 (해당 인증서 체인은 대개 공개되어 있지만 찾기가 어렵지 않음)

+1

준비가되어 있습니다. 그러나 나는 id-ad-caIssuers를 포함하는이 확장을 가진 인증서를 본 적이 없다고 생각합니다. 어쨌든, 좋은 대답. – Egl

+0

@Egl id-ad-caIssuers와 OCSP (google.com의 인증서 및 브라질의 PKI 엔드 엔티티 모두에 해당)의 인증서를 보았습니다. 나는 그 중 하나만 가지고도 인증서를 보았습니다. 불행히도 CA들 사이에는 표준이 없다. –

+0

답변 해 주셔서 감사합니다. 너 나 많이 도와 줬어! – revolt

1

btw 창문에 설치된 인증서, 모든 것이 훨씬 간단합니다 :

KeyStore ks = KeyStore.getInstance("Windows-MY"); 
ks.load(null, null); 
String alias = "your alias"; 
ArrayList<X509Certificate> certsChain = new ArrayList<>(); 
if (ks.isCertificateEntry(alias)) { 
    Certificate[] chain = ks.getCertificateChain(alias); 
    System.out.println("Chain length: " + chain.length); 
     for(Certificate c : chain) certsChain.add((X509Certificate)c); 
} 

Collections.reverse(certsChain); 
certsChain.forEach(MainClass::printDBG); 

붐, 전체 인증서 체인 확장 기관 정보 액세스가 OCSP 정보에 대한 매우 일반적인

관련 문제