2012-11-03 16 views
20

Der folgende Code:Speicher von Zertifikatskette in einem pkcs12 Schlüsselspeicher

//used Bouncy Castle provider for keyStore 
keyStore.setKeyEntry(alias, (Key)keyPair.getPrivate(), pwd, certChain); 

wo certChain das End-Zertifikat und das Ausstellerzertifikat hält (dh zwei Zertifikate),
nicht das Aussteller-Zertifikat im Rahmen der speichern Die Keystore-Datei wird in der Datei gespeichert, wenn der Schlüsselspeicher eine Instanz von PKCS12 ist.

Es speichert beide Zertifikate, wenn der Keystore-Typ PKCS12-3DES-3DES ist. Warum ist das? Nimmt ein PKCS12 nicht an, dass beide Zertifikate Teil der Kette sind?

EDIT: Hier ist ein SSCCE. Dies funktioniert gut mit "JKS", schlägt mit "PKCS12": Nur das erste Zertifikat in der Kette ist über getCertificateChain(String) zugänglich. Die gespeicherte Datei kann mit openssl pkcs12 geöffnet werden, wobei beide Zertifikate angezeigt werden.

public void testKeyStore() { 
    try { 
     KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); 
     keyPairGenerator.initialize(1024); 
     KeyPair keyPair = keyPairGenerator.generateKeyPair(); 
     PublicKey publicKey = keyPair.getPublic(); 
     PrivateKey privateKey = keyPair.getPrivate(); 
     Certificate[] outChain = { createCertificate("CN=CA", publicKey, privateKey), createCertificate("CN=Client", publicKey, privateKey) }; 

     KeyStore outStore = KeyStore.getInstance("PKCS12"); 
     outStore.load(null, "secret".toCharArray()); 
     outStore.setKeyEntry("mykey", privateKey, "secret".toCharArray(), outChain);    
     OutputStream outputStream = new FileOutputStream("c:/outstore.pkcs12"); 
     outStore.store(outputStream, "secret".toCharArray()); 
     outputStream.flush(); 
     outputStream.close(); 

     KeyStore inStore = KeyStore.getInstance("PKCS12");  
     inStore.load(new FileInputStream("c:/outstore.pkcs12"), "secret".toCharArray()); 
     Key key = outStore.getKey("myKey", "secret".toCharArray()); 
     assertEquals(privateKey, key); 

     Certificate[] inChain = outStore.getCertificateChain("mykey"); 
     assertNotNull(inChain); 
     assertEquals(outChain.length, inChain.length); 
    } catch (Exception e) { 
     e.printStackTrace(); 
     fail(e.getMessage()); 
    } 
} 

private static X509Certificate createCertificate(String dn, PublicKey publicKey, PrivateKey privateKey) throws Exception { 
    X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator(); 
    certGenerator.setSerialNumber(new BigInteger("1")); 
    certGenerator.setIssuerDN(new X509Name(dn)); 
    certGenerator.setSubjectDN(new X509Name(dn)); 
    certGenerator.setNotBefore(Calendar.getInstance().getTime()); 
    certGenerator.setNotAfter(Calendar.getInstance().getTime()); 
    certGenerator.setPublicKey(publicKey); 
    certGenerator.setSignatureAlgorithm("SHA1withRSA"); 
    X509Certificate certificate = (X509Certificate)certGenerator.generate(privateKey, "BC"); 
    return certificate; 
} 
+0

OOI, zeigt der PKCS12-Keystore-Typ von Oracle (SunJSSE-Anbieter) die gleichen Symptome? Wenn nicht, dann könnte dies eine gute Frage für die BC-Mailingliste sein. –

+0

@DuncanJones: Ich fragte diese in BC Mailing-Liste und erhielt keine Antwort für mehr als eine Woche – Cratylus

+0

PKCS # 12 nimmt nichts an, da es ein Container für eine beliebige Anzahl von Zertifikaten und ihre privaten Schlüssel ist. Es ist also implementierungsspezifisch, was in den PKCS # 12-Container gestellt wird. –

Antwort

0

Je nachdem, welches JDK Sie verwenden, gibt es verschiedene Möglichkeiten, Ihre Anwendung zu packen. Es passiert uns, wenn einige Leute mit Linux und OpenJDK und einige andere unter Windows mit SunJDK (Oracle) arbeiten.

Die neuesten haben einige zusätzliche Konfiguration zu tun, um die stärksten Algorithmen verwenden zu können. This article kann Ihnen helfen, wenn Ihr Problem mit der JCE-Richtlinie zusammenhängt.

+0

Ich glaube nicht, dass dies ein politisches Problem ist. Das OP verwendet Bouncy Castle, nicht SunJSSE. – martijno

+1

BouncyCastle ist eine Implementierung von JCE, wir haben unser Problem mit dem angegebenen Link gelöst, sogar wenn wir nur BouncyCastle-Klassen in unserem Projekt verwendet haben. Aber du hast recht, meine Antwort könnte die Lösung für Cratylus sein oder nicht. –

+0

Danke. Werde trotzdem prüfen ob das hilft! – martijno

13

Ihr Code hat zwei Fehler:

zuerst: Sie nicht Issuer-Set für Zertifikat (Client-Zertifikat sollte von CA ausgestellt wurde gültige Kette zu machen).

Sekunde: Sie verwenden falsche Reihenfolge beim Zertifikatskette erstellen (sollte Client ferts sein, CA zuletzt) ​​

hier SSCCE überarbeitet, und es funktioniert ohne Fehler.

@Test 
public void testKeyStore() throws Exception{ 
     try { 
     String storeName = "/home/grigory/outstore.pkcs12"; 
     KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); 
     keyPairGenerator.initialize(1024); 
     KeyPair keyPair = keyPairGenerator.generateKeyPair(); 
     PublicKey publicKey = keyPair.getPublic(); 
     PrivateKey privateKey = keyPair.getPrivate(); 
     Certificate trustCert = createCertificate("CN=CA", "CN=CA", publicKey, privateKey); 
     Certificate[] outChain = { createCertificate("CN=Client", "CN=CA", publicKey, privateKey), trustCert }; 

     KeyStore outStore = KeyStore.getInstance("PKCS12"); 
     outStore.load(null, "secret".toCharArray()); 
     outStore.setKeyEntry("mykey", privateKey, "secret".toCharArray(), outChain); 
     OutputStream outputStream = new FileOutputStream(storeName); 
     outStore.store(outputStream, "secret".toCharArray()); 
     outputStream.flush(); 
     outputStream.close(); 

     KeyStore inStore = KeyStore.getInstance("PKCS12"); 
     inStore.load(new FileInputStream(storeName), "secret".toCharArray()); 
     Key key = outStore.getKey("myKey", "secret".toCharArray()); 
     Assert.assertEquals(privateKey, key); 

     Certificate[] inChain = outStore.getCertificateChain("mykey"); 
     Assert.assertNotNull(inChain); 
     Assert.assertEquals(outChain.length, inChain.length); 
    } catch (Exception e) { 
     e.printStackTrace(); 
     throw new AssertionError(e.getMessage()); 
    } 
    } 
    private static X509Certificate createCertificate(String dn, String issuer, PublicKey publicKey, PrivateKey privateKey) throws Exception { 
     X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator(); 
     certGenerator.setSerialNumber(BigInteger.valueOf(Math.abs(new Random().nextLong()))); 
     certGenerator.setIssuerDN(new X509Name(dn)); 
     certGenerator.setSubjectDN(new X509Name(dn)); 
     certGenerator.setIssuerDN(new X509Name(issuer)); // Set issuer! 
     certGenerator.setNotBefore(Calendar.getInstance().getTime()); 
     certGenerator.setNotAfter(Calendar.getInstance().getTime()); 
     certGenerator.setPublicKey(publicKey); 
     certGenerator.setSignatureAlgorithm("SHA1withRSA"); 
     X509Certificate certificate = (X509Certificate)certGenerator.generate(privateKey, "BC"); 
     return certificate; 
    } 
+0

Ja, du hast es behoben. Gut gemacht! Ich weiß, dass ich dort keine gültige Kette generiert habe. In einem anderen Test dachte ich, ich wäre (mit dem gleichen Fehler), also dachte ich, das sei egal, zumal es für 'JKS' funktionierte. Es stellte sich heraus, dass es die Bestellung war! Die Reihenfolge ist also: endpointtrust Anker last. – martijno

+0

@Cratylus, löst das dein Problem? Ich stimme für die Annahme dieser Antwort. – martijno

Verwandte Themen