Richtiges Erstellen eines neuen Zertifikats mit einem Zwischenzertifikat unter Verwendung der Hüpfburg

Also ist mein Problem wie folgt:

Grundsätzlich möchte ich eine Zertifikatskette mit Hüpfburg (jdk16 Version 1.46) erstellen. Ich bin ziemlich neu in Hüpfburg und Java. Sicherheit im Allgemeinen, wenn mein Ansatz also völlig falsch sein könnte, aber auf jeden Fall ist es das, was ich getan habe:

Bisher kann ich ein selbstsigniertes Zertifikat erstellen, das ich als Stammzertifikat verwende. Dies geschieht mit folgendem Code:

//-----create CA certificate with key
KeyPair caPair = Signing.generateKeyPair("DSA", 1024, null, null);

Dadurch wird im Grunde das Schlüsselpaar erstellt. Die beiden Nulloptionen gelten für einen Anbieter und bei Bedarf für einen sicheren Zufallsgenerator.

Map<ASN1ObjectIdentifier, Entry<Boolean, DEREncodable>> caMap = new HashMap<ASN1ObjectIdentifier, Entry<Boolean, DEREncodable>>();
caMap.put(X509Extensions.BasicConstraints, new AbstractMap.SimpleEntry<Boolean, DEREncodable>(true, new BasicConstraints(true)));

//------this creates the self signed certificate        
X509Certificate caCert = X509CertificateGenerator.generateX509Certificate(serial, "CN=CA", "CN=CA", start, end, "SHA1withDSA", caPair.getPrivate(), caPair.getPublic(), null, caMap);

Dadurch wird ein Zertifikat mit den angegebenen Attributen erstellt.

serial = einfach die aktuelle Zeit in Millisekundenstart = im Grunde wie serial (kann 1 oder 2 Millisekunden Unterschied haben)Ende = Beginn + 2 Tage

Die Karte fügt einfach die grundlegende Einschränkung hinzu, um das Zertifikat als Zertifizierungsstelle festzulegen. Ich verwende hier eine Karte, da ich bei Bedarf zusätzliche X509-Erweiterungen hinzufügen möchte.

//-----save ca certificate in PEM format
X509CertificateGenerator.savePemX509Certificate(caCert, caPair.getPrivate(), caWriter);

Dadurch werden das Zertifikat und der private Schlüssel in einer PEM-Datei mit dem Bouncy-Caste-PEM-Writer gespeichert.

Danach wird die Datei generiert und ich kann die Datei auch installieren (ich verwende IE und installiere sie dann über die Internetoptionen als vertrauenswürdige Zertifizierungsstelle. Das Zertifikat wird auch als gültig angezeigt).

Danach erstelle ich das Zwischenzertifikat mit dem folgenden Code (beachten Sie, dass sich der obige Code im selben Bereich befindet, sodass diese Variablen ebenfalls verfügbar sind)

KeyPair intermediatePair = Signing.generateKeyPair("DSA", 1024, null, null);    

Map<ASN1ObjectIdentifier, Entry<Boolean, DEREncodable>> intermediateMap = new HashMap<ASN1ObjectIdentifier, Entry<Boolean, DEREncodable>>();
intermediateMap.put(X509Extensions.AuthorityKeyIdentifier, new AbstractMap.SimpleEntry<Boolean, DEREncodable>(false, new AuthorityKeyIdentifierStructure(caCert)));
intermediateMap.put(X509Extensions.SubjectKeyIdentifier, new AbstractMap.SimpleEntry<Boolean, DEREncodable>(false, new SubjectKeyIdentifierStructure(intermediatePair.getPublic())));

X509Certificate intermediateCert = X509CertificateGenerator.generateX509Certificate(serial.add(BigInteger.valueOf(1l)), "CN=intermediate", caCert.getSubjectX500Principal().toString(), start, end, "SHA1withDSA", caPair.getPrivate(), intermediatePair.getPublic(), null, intermediateMap);   

//-----save intermediate certificate in PEM format
X509CertificateGenerator.savePemX509Certificate(intermediateCert, intermediatePair.getPrivate(), intermediateWriter);

Die Vorgehensweise ist im Grunde die gleiche, ich füge jedoch zusätzliche X509-Erweiterungen hinzu:

X509Extensions.AuthorityKeyIdentifier = Legt das CA-Zertifikat als übergeordnetes Zwischenprodukt festX509Extensions.SubjectKeyIdentifier = Verwendet den generierten öffentlichen Schlüssel für das Zertifikat

Außerdem wird die Zertifizierungsstelle als Aussteller und der private Schlüssel der Zertifizierungsstelle zum Erstellen des Zwischenzertifikats verwendet.

Dies funktioniert auch und ich kann das Zwischenzertifikat installieren (wieder mit IE). Außerdem wird angezeigt, dass das übergeordnete Zertifikat das generierte CA-Zertifikat ist und dass das Zertifikat gültig ist.

Jetzt kommt der schwierige Teil, an dem ich einen Fehler mache, denke ich. Ich erstelle jetzt ein neues Zertifikat mit dem Zwischenzertifikat unter Verwendung des folgenden Codes.

KeyPair endPair = Signing.generateKeyPair("DSA", 1024, null, null);

Map<ASN1ObjectIdentifier, Entry<Boolean, DEREncodable>> endMap = new HashMap<ASN1ObjectIdentifier, Entry<Boolean, DEREncodable>>();
endMap.put(X509Extensions.AuthorityKeyIdentifier, new AbstractMap.SimpleEntry<Boolean, DEREncodable>(false, new AuthorityKeyIdentifierStructure(intermediateCert)));
endMap.put(X509Extensions.SubjectKeyIdentifier, new AbstractMap.SimpleEntry<Boolean, DEREncodable>(false, new SubjectKeyIdentifierStructure(endPair.getPublic())));

X509Certificate endCert = X509CertificateGenerator.generateX509Certificate(serial.add(BigInteger.valueOf(1l)), "CN=end", intermediateCert.getSubjectX500Principal().toString(), start, end, "SHA1withDSA", intermediatePair.getPrivate(), endPair.getPublic(), null, endMap);

X509CertificateGenerator.savePemX509Certificate(endCert, endPair.getPrivate(), endWriter);

Im Wesentlichen ist es dasselbe wie das Erstellen des Zwischenzertifikats. Jetzt verwende ich jedoch die folgenden X509-Erweiterungseinstellungen:

X509Extensions.AuthorityKeyIdentifier = Legt das Zwischenzertifikat als übergeordnetes Zertifikat festX509Extensions.SubjectKeyIdentifier = Verwendet den generierten öffentlichen Schlüssel für das Zertifikat

Das Zwischenzertifikat wird auch als Aussteller verwendet, und sein privater Schlüssel wird zum Erstellen des Zertifikats verwendet.

Ich kann das neue Zertifikat auch installieren, aber wenn ich prüfe, ob (erneut IE), zeigt dies, dass das Zertifikat jedoch ungültig ist, weil "diese Zertifizierungsstelle entweder nicht berechtigt ist, Zertifikate auszustellen, oder das Zertifikat nicht als Endeinheit verwendet werden kann".

Ich muss also irgendwie das Zwischenzertifikat aktivieren, um auch neue Zertifikate erstellen zu können, indem ich einige von mir angenommene KeyUsages / ExtendedKeyUsage hinzufüge.

Weiß jemand, wie ich es dem Zwischenzertifikat ermögliche, das zu tun, wofür ich es benötige, oder ob ich im Allgemeinen etwas falsch mache?

EDIT 1:

Also okay, ich habe vergessen, den Code für die Methode anzugeben, mit der das Zertifikat erstellt wurde, und den Code, mit dem es im PEM - Format gespeichert wurde (ich habe es in umbenannt)savePemX509Certificate da der alte irreführend war).

Code für die Zertifikatserstellung:

public static X509Certificate generateX509Certificate(BigInteger serialnumber, String subject, String issuer, Date start , Date end, String signAlgorithm, PrivateKey privateKey, PublicKey publicKey, String provider, Map<ASN1ObjectIdentifier, Entry<Boolean, DEREncodable>> map) throws CertificateEncodingException, InvalidKeyException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException
{
    if(serialnumber!=null && subject!=null && issuer!=null && start!=null && end!=null && signAlgorithm !=null && privateKey!=null && publicKey!=null)
    {
        //-----GENERATE THE X509 CERTIFICATE
        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
        X509Principal dnSubject = new X509Principal(subject);
        X509Principal dnIssuer = new X509Principal(issuer);

        certGen.setSerialNumber(serialnumber);
        certGen.setSubjectDN(dnSubject);
        certGen.setIssuerDN(dnIssuer);
        certGen.setNotBefore(start);
        certGen.setNotAfter(end);
        certGen.setPublicKey(publicKey);
        certGen.setSignatureAlgorithm(signAlgorithm);

        //-----insert extension if needed
        if(map!=null)
            for(ASN1ObjectIdentifier extension : map.keySet())
                certGen.addExtension(extension, map.get(extension).getKey(), map.get(extension).getValue());

        return certGen.generate(privateKey, provider);  
    }
    return null;
}

Code zum Speichern des Zertifikats und des Schlüssels:

public static boolean savePemX509Certificate(X509Certificate cert, PrivateKey key, Writer writer) throws NoSuchAlgorithmException, NoSuchProviderException, CertificateEncodingException, SignatureException, InvalidKeyException, IOException 
{       
    if(cert!=null && key!=null && writer!=null)
    {               
        PEMWriter pemWriter = new PEMWriter(writer);
        pemWriter.writeObject(cert);
        pemWriter.flush();

        if(key!=null)
        {
            pemWriter.writeObject(key);
            pemWriter.flush();
        }
        pemWriter.close();
        return true;
        }
    return false;
}

Wie Sie sehen, habe ich im Grunde genommen das Zertifikat und den Schlüssel in die Datei geschrieben, das ist alles. Das Ergebnis ist das Folgende und scheint mir gut zu sein.

-----BEGIN CERTIFICATE-----
MIICdjCCAjagAwIBAgIGAUDuXLRLMAkGByqGSM44BAMwDTELMAkGA1UEAwwCQ0Ew
HhcNMTMwOTA1MTM0MzA3WhcNMTMwOTA3MTM0MzA3WjANMQswCQYDVQQDDAJDQTCC
AbcwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADD
Hj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gE
exAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/Ii
Axmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4
V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozI
puE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4Vrl
nwaSi2ZegHtVJWQBTDv+z0kqA4GEAAKBgAeFoGATLbIr8+QNuxcbYJ7RhbefKWSC
Br67Pp4Ynikxx8FZN4kCjGX7pwT1KffN3gta7jxIXNM5G3IFbs4XnYljh5TbdnjP
9Ge3kxpwncsbMQfCqIwHh8T5gh55KaxH7yYV2mrtEEqj7NBL4thQhJe2WGwgkB9U
NxNmLoMq3m4poyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAJ
BgcqhkjOOAQDAy8AMCwCFFm5ybLY09y8y2uGsEnpceffy2KaAhQIyshgy3ohCLxQ
q3CmnvC+cfT2VQ==
-----END CERTIFICATE-----
-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR
+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb
+DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdg
UI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlX
TAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCj
rh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQB
TDv+z0kqAoGAB4WgYBMtsivz5A27FxtgntGFt58pZIIGvrs+nhieKTHHwVk3iQKM
ZfunBPUp983eC1ruPEhc0zkbcgVuzhediWOHlNt2eM/0Z7eTGnCdyxsxB8KojAeH
xPmCHnkprEfvJhXaau0QSqPs0Evi2FCEl7ZYbCCQH1Q3E2YugyrebikCFDJCJHtt
NWB4LWYc4y4QvJ/l46ap
-----END DSA PRIVATE KEY-----

Nachdem mir gtrig die richtige Methode zum Erstellen des Zertifikats zur Verfügung gestellt hatte, erstellte ich mit dieser Methode entweder ein normales oder ein selbstsigniertes Zertifikat (wenn der private Schlüssel von demselben keyPair stammt wie der öffentliche Schlüssel)

public static X509Certificate createX509V3Certificate(X500Principal name, BigInteger serial, Date start, Date end, PublicKey pubKey, String algorithm, PrivateKey privateKey, Map<ASN1ObjectIdentifier, Entry<Boolean, ASN1Object>> map, X509Certificate parentCert) throws IOException, OperatorCreationException, CertificateException
{
    if(serial!=null && start!=null && end!=null && name!=null && pubKey!=null && algorithm!=null && privateKey!=null)
    {
        ContentSigner signer = new JcaContentSignerBuilder(algorithm).build(privateKey);
        X509v3CertificateBuilder certBldr = null;
        if(parentCert==null)
            certBldr = new JcaX509v3CertificateBuilder(name, serial, start, end, name, pubKey);
        else
            certBldr = new JcaX509v3CertificateBuilder(parentCert, serial, start, end, name, pubKey);

        if(map!=null)
            for(ASN1ObjectIdentifier extension : map.keySet())
                certBldr.addExtension(extension, map.get(extension).getKey(), map.get(extension).getValue());

        return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certBldr.build(signer));  
    }
    return null;
}

Antworten auf die Frage(1)

Ihre Antwort auf die Frage