2009-05-29 16 views
11

Ich bin auf der Suche nach einer Java-Bibliothek oder einem Code zum Generieren von Zertifikaten, öffentliche und private Schlüssel im laufenden Betrieb, ohne die Verwendung von Drittanbieter-Programmen (wie openssl).Erzeuge Zertifikate, öffentliche und private Schlüssel mit Java

denke ich, etwas, das doeing ist keytool + openssl aber von Java-Code.

Betrachten wir ein Java-Servlet-basierte Web-Anwendung mit SSL und Client-Authentifizierung gesichert. Ich möchte den Servlet-Container Client-Zertifikate (z. B. pkcs12-Format) auf Anfrage nur mit Java-Code generieren.

Danke, Peter.

+0

Alternativ Sun Java keytool Klasse und bieten Sie könnten die benötigten Parameter nur aufrufen, um die Zertifikate zu generieren. Aber diese Klassen sind im Paket com.sun * und werden sich möglicherweise ändern.Theoretisch ist alles in Java vorhanden, um eigene Zertifikate zu erzeugen, aber es ist nicht öffentlich verfügbar –

Antwort

9

Sie können Zertifikat in Java dynamisch generieren, indem ein Paar oder Tasten. (Öffentlicher Schlüssel, private Schlüssel). Rufen Sie diese Schlüssel als BigInteger-Format ab und überprüfen Sie den folgenden Code, um ein Zertifikat zu generieren.

RSAPrivateKeySpec serPrivateSpec = new RSAPrivateKeySpec(
    new BigInteger(val of pub key), new BigInteger(val of pri key)); 
fact = KeyFactory.getInstance("RSA"); 
PrivateKey serverPrivateKey = fact.generatePrivate(serPrivateSpec); 

RSAPublicKeySpec serPublicSpec = new RSAPublicKeySpec(
    new BigInteger(agentCL.getSerPubMod()), new BigInteger(agentCL.getSerPubExp())); 
PublicKey serverPublicKey = fact.generatePublic(serPublicSpec); 

keyStore = KeyStore.getInstance(IMXAgentCL.STORE_TYPE); 
keyStore.load(null, SOMEPWD.toCharArray()); 

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 

X509Certificate[] serverChain = new X509Certificate[1]; 
X509V3CertificateGenerator serverCertGen = new X509V3CertificateGenerator(); 
X500Principal serverSubjectName = new X500Principal("CN=OrganizationName"); 
serverCertGen.setSerialNumber(new BigInteger("123456789")); 
// X509Certificate caCert=null; 
serverCertGen.setIssuerDN(somename); 
serverCertGen.setNotBefore(new Date()); 
serverCertGen.setNotAfter(new Date()); 
serverCertGen.setSubjectDN(somename); 
serverCertGen.setPublicKey(serverPublicKey); 
serverCertGen.setSignatureAlgorithm("MD5WithRSA"); 
// certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false,new 
// AuthorityKeyIdentifierStructure(caCert)); 
serverCertGen.addExtension(X509Extensions.SubjectKeyIdentifier, false, 
    new SubjectKeyIdentifierStructure(serverPublicKey)); 
serverChain[0] = serverCertGen.generateX509Certificate(serverPrivateKey, "BC"); // note: private key of CA 

keyStore.setEntry("xyz", 
    new KeyStore.PrivateKeyEntry(serverPrivateKey, serverChain), 
    new KeyStore.PasswordProtection("".toCharArray())); 

Hoffe, das wird Ihnen helfen.

+1

Nur durch Hinzufügen der Bouncy Castle JSSE Provider, die Sie habe nicht in deiner Antwort erwähnt. – EJP

3

Legacy-Warnung Beginn:

  • Dieser Code setzt nur die Commonname/CN/Betreff.
  • Der richtige Ort, jetzt ist die SubjectAltName.

Von Chrome Deprecates Subject CN Matching:

Chrome 58 wird verlangen, dass Zertifikate den Hostnamen angeben (n), auf die sie im SubjectAltName Feld anzuwenden; Werte im Betreff-Feld wird ignoriert.“

Legacy-Warnung End

import java.io.FileOutputStream; 
import java.security.KeyStore; 
import java.security.PrivateKey; 
import java.security.cert.X509Certificate; 
import java.util.Date; 

import sun.security.x509.CertAndKeyGen; 
import sun.security.x509.X500Name; 

public class UseKeyTool { 

    private static final int keysize = 1024; 
    private static final String commonName = "www.test.de"; 
    private static final String organizationalUnit = "IT"; 
    private static final String organization = "test"; 
    private static final String city = "test"; 
    private static final String state = "test"; 
    private static final String country = "DE"; 
    private static final long validity = 1096; // 3 years 
    private static final String alias = "tomcat"; 
    private static final char[] keyPass = "changeit".toCharArray(); 

    // copied most ideas from sun.security.tools.KeyTool.java 

    @SuppressWarnings("restriction") 
    public static void main(String[] args) throws Exception { 

     KeyStore keyStore = KeyStore.getInstance("JKS"); 
     keyStore.load(null, null); 

     CertAndKeyGen keypair = new CertAndKeyGen("RSA", "SHA1WithRSA", null); 

     X500Name x500Name = new X500Name(commonName, organizationalUnit, organization, city, state, country); 

     keypair.generate(keysize); 
     PrivateKey privKey = keypair.getPrivateKey(); 

     X509Certificate[] chain = new X509Certificate[1]; 

     chain[0] = keypair.getSelfCertificate(x500Name, new Date(), (long) validity * 24 * 60 * 60); 

     keyStore.setKeyEntry(alias, privKey, keyPass, chain); 

     keyStore.store(new FileOutputStream(".keystore"), keyPass); 



    } 
} 
+1

DNS-Namen sind * nicht * in dem 'CommonName' (vorausgesetzt, dass es dort im obigen Code hinzugefügt werden soll). Diese Vorgehensweise wird sowohl vom IETF- als auch vom CA/Browser-Forum abgelehnt. DNS-Namen müssen in die 'subjectAltNames' gehen, aber der Code fehlt. – jww

+1

DigiCert scheint anderer Meinung zu sein: "Um https://www.example.com zu sichern, muss Ihr allgemeiner Name www.example.com oder * .example.com für ein Wildcard-Zertifikat sein." https://www.digicert.com/easy-csr/keytool.htm –

+0

Schauen Sie sich [RFC 6125] (http://tools.ietf.org/html/rfc6125), Abschnitt 6.4.4 oder die CA/Browser [ Grundlegende Sicherheitsanforderungen] (https://cabforum.org/wp-content/uploads/Baseline_Requirements_V1_1_9.pdf), Abschnitt 9.2.2. DidgiCert sollte es besser wissen, da sie [Mitglied der CA/B] sind (https://cabforum.org/members/). – jww

Verwandte Themen