2013-09-05 12 views
6

Quindi il mio problema è il seguente,correttamente la creazione di un nuovo certificato con un certificato intermedio utilizzando bouny castello

Fondamentalmente voglio creare una catena di certificati utilizzando castello gonfiabile (jdk16 versione 1.46). Sono piuttosto nuovo a castello gonfiabile e java.security in generale quindi se il mio approccio potrebbe essere completamente sbagliato, ma comunque è quello che ho fatto:

Finora sono in grado di creare un certificato autofirmato che utilizzo come certificato di origine. Questo viene fatto utilizzando il seguente codice:

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

Questo crea fondamentalmente la coppia di chiavi, le due opzioni nulle sono per un provider e un caso sicuro, se necessario.

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

Questo creerà un certificato con gli attributi forniti.

  • = seriali semplicemente il tempo corrente in millisecondi
  • inizio = stessa serie fondamentalmente (può avere 1 o 2 millisecondi differenza)
  • finali = marcia + 2 giorni

La mappa semplicemente aggiunge il contraint di base per impostare il certificato come CA. Io uso una mappa qui poiché voglio essere in grado di aggiungere X509Extensions aggiuntive se necessario.

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

Questo memorizzerà il certificato e la chiave privata in un file PEM utilizzando il masterizzatore pem rimbalzante.

Successivamente il file viene generato e posso anche installare il file (utilizzo IE e quindi lo installo tramite le Opzioni Internet come una CA attendibile. Anche il certificato è valido).

Dopo che crea il certificato intermedio, utilizzando il codice seguente (nota del codice precedente è nello stesso ambito così queste variabili sono disponibili pure)

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

La procedura è bascially lo stesso, tuttavia mi aggiungi X509Extensions supplementari:

  • X509Extensions.AuthorityKeyIdentifier = imposta il certificato CA come il genitore intermedi
  • X509Extensions.SubjectKeyIdentifier = usa la genera publ ic chiave per il certificato

inoltre la CA viene utilizzata come emittente e la chiave privata CA viene utilizzata per creare il certificato intermedio.

Anche questo funziona e posso installare il certificato intermedio (utilizzando nuovamente IE), inoltre viene indicato che il certificato padre è il certificato CA generato e che il certificato è valido.

Ora arriva la parte difficile in cui sto facendo un errore, immagino. Ora creo un nuovo certificato utilizzando il certificato intermedio, utilizzando il seguente codice.

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

In sostanza equivale alla creazione del certificato intermedio. Tuttavia ora uso le seguenti impostazioni X509Extension:

  • X509Extensions.AuthorityKeyIdentifier = imposta il certificato intermedio come il genitore certificati
  • X509Extensions.SubjectKeyIdentifier = utilizza la genera chiave pubblica per il certificato

Anche il il certificato intermedio viene utilizzato come emittente e la sua chiave privata viene utilizzata per creare il certificato.

Posso anche installare il nuovo certificato ma quando esamino se (ancora IE), mostra che il certificato non è comunque valido perché "Questa CA non è autorizzata a emettere certificati o il certificato non può essere utilizzato come fine -entità."

Così ho in qualche modo bisogno di abilitare il certificato intermedio per poter creare anche nuovi certificati, aggiungendo alcuni KeyUsages/ExtendedKeyUsage presumo.

Qualcuno sa come abilito il certificato intermedio a fare ciò che mi serve o se faccio qualcosa di sbagliato in generale?

EDIT 1:

Così va bene mi sono dimenticato di fornire il codice per il metodo che ha creato il certificato e quello che ha salvato in formato PEM (ho rinominato a savePemX509Certificate dal momento che il vecchio è stato fuorviante) .

codice per la generazione del certificato:

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; 
} 

Codice in saveing ​​del certificato e della chiave:

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; 
} 

Come potete vedere ho praticamente messo il certificato e la chiave nel file, È tutto. Il risultato è il seguente e mi sembra buono.

-----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----- 

Così, dopo gtrig mi ha fornito il modo corretto per creare il certificato, ho finito per usare questo metodo per creare sia un normale o autonomo firmato (se la chiave privata è dalla stessa coppia di chiavi come la chiave pubblica che è) certificato

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; 
} 
+0

Che cosa è "entrata" nella tua casella ultimo codice? Perché non usare 'intermediateCert' invece di' entry.getKey() '. Da dove proviene 'X509CertificateGenerator'? – gtrig

+0

La voce è in realtà il certificato intermedio, ho appena visto che ho ancora un vecchio codice, che ha caricato il file PEM precedentemente memorizzato e lo ha inserito in una voce (in pratica una combinazione di un certificato e di KeyPair). Quindi Entry è in realtà il valore intermedio. – DokutoMekki

risposta

6

Qualcosa non va nel modo in cui si creano i file PEM. Stai utilizzando un metodo chiamato, generateSelfSignedPemX509Certificate, ma in realtà non vuoi un certificato autofirmato, vuoi un certificato finale firmato dalla chiave privata intermedia e desideri un certificato intermedio firmato dalla chiave privata CA.

Inoltre, sono necessarie le estensioni basic constraints e key usage sui certificati.

Per creare certificati firmati da altre entità (non autofirmati), utilizzo questi metodi da Bouncy Castle per creare un certificato di fine.

ASN1Sequence seq= 
    (ASN1Sequence) new ASN1InputStream(parentPubKey.getEncoded()).readObject(); 

    SubjectPublicKeyInfo parentPubKeyInfo = new SubjectPublicKeyInfo(seq); 

    ContentSigner signer = new JcaContentSignerBuilder(algorithm).build(parentPrivKey); 

    X509v3CertificateBuilder certBldr = 
    new JcaX509v3CertificateBuilder(
     parentCert, 
     serialNum, 
     startDate, 
     endDate, 
     distName, 
     pubKey) 
    .addExtension(
      new ASN1ObjectIdentifier("2.5.29.35"), 
      false, 
      new AuthorityKeyIdentifier(parentPubKeyInfo)) 
    .addExtension(
     new ASN1ObjectIdentifier("2.5.29.19"), 
     false, 
     new BasicConstraints(false)) // true if it is allowed to sign other certs 
    .addExtension(
     new ASN1ObjectIdentifier("2.5.29.15"), 
     true, 
     new X509KeyUsage(
      X509KeyUsage.digitalSignature | 
      X509KeyUsage.nonRepudiation | 
      X509KeyUsage.keyEncipherment | 
      X509KeyUsage.dataEncipherment)); 

    // Build/sign the certificate. 
    X509CertificateHolder certHolder = certBldr.build(signer); 

    X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC) 
    .getCertificate(certHolder); 

Per una CA o certificato intermedio, è necessario aggiungere un'estensione SubjectKeyIdentifier. Inoltre, dovrebbe essere BasicConstraintstrue, e KeyUsage dovrebbe essere:

 new X509KeyUsage(
      X509KeyUsage.keyCertSign| 
      X509KeyUsage.cRLSign)); 
+0

Mi dispiace per il nome del metodo errato, ho modificato il mio post e fornito codice aggiuntivo. – DokutoMekki

+0

Quindi, sembra che la risposta sia effettivamente corretta, avevo bisogno dell'estensione dei vincoli di base, che mancava nel certificato intermedio. Ora la catena di certificati funziona e sono stato anche in grado di utilizzare il modo non protetto per creare un certificato. Grazie – DokutoMekki

Problemi correlati