2009-05-29 17 views
11

Sto cercando una libreria o codice Java per generare certificati, chiavi pubbliche e private al volo senza utilizzare programmi di terze parti (come openssl).Genera certificati, chiavi pubbliche e private con Java

Penso che qualcosa stia facendo keytool + openssl ma dal codice Java.

Considerare un'applicazione web basata su servlet java protetta con autenticazione ssl e client. Desidero che il contenitore servlet generi certificati client (ad esempio il formato pkcs12) su richiesta solo con codice Java.

Grazie, Peter.

+0

In alternativa si può solo richiamare la classe java keytool SUN e fornire i parametri necessari per generare i certificati. Ma queste classi sono nel pacchetto com.sun * e potenzialmente cambieranno In teoria tutto è presente in Java per generare i propri certificati, ma non è disponibile pubblicamente. –

risposta

9

È possibile generare certificato in java in modo dinamico, utilizzando una coppia o chiavi. (Chiave pubblica, chiavi private). Ottieni queste chiavi come formato BigInteger e verifica il seguente codice per generare un certificato.

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())); 

Spero che questo ti possa aiutare.

+1

Solo aggiungendo il provider JSSE di Bouncy Castle, che tu non ho menzionato nella tua risposta. – EJP

3

Legacy Attenzione Begin:

  • Questo codice imposta solo il CommonName/CN/Soggetto.
  • Il posto corretto ora è SubjectAltName.

Da Chrome Deprecates Subject CN Matching:

Chrome 58 sarà necessario che i certificati di specificare il nome host (s) a cui si applicano nel settore SubjectAltName; valori nel campo Oggetto saranno ignorati."

Legacy Attenzione Fine

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

I nomi DNS * non * dovrebbero essere nel 'commonName' (supponendo che sia dove dovrebbe essere aggiunto nel codice sopra). La pratica è deprecata dai forum IETF e CA/Browser. I nomi DNS devono andare nel 'subjectAltNames', ma il codice non ce l'ha. – jww

+1

DigiCert sembra in disaccordo: "Per proteggere https://www.example.com, il tuo nome comune deve essere www.example.com o * .example.com per un certificato con caratteri jolly." https://www.digicert.com/easy-csr/keytool.htm –

+0

Scopri [RFC 6125] (http://tools.ietf.org/html/rfc6125), Sezione 6.4.4 o CA/Browser [ Requisiti di sicurezza di base] (https://cabforum.org/wp-content/uploads/Baseline_Requirements_V1_1_9.pdf), Sezione 9.2.2. DidgiCert dovrebbe conoscere meglio dato che sono un [membro del CA/B] (https://cabforum.org/members/). – jww

Problemi correlati