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;
}
Che cosa è "entrata" nella tua casella ultimo codice? Perché non usare 'intermediateCert' invece di' entry.getKey() '. Da dove proviene 'X509CertificateGenerator'? – gtrig
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