Java: formato de almacén de claves no válido, cuando se genera mediante código
-
08-07-2019 - |
Pregunta
Esto se ha pedido un par de veces, pero ninguno proporciona casos de prueba codificados. Aquí les doy un ejemplo del problema:
- generación programática de un Keystore (funciona)
- creación de certificado dentro de esa tienda (funciona)
- guardar el almacén de claves en el disco (funciona)
- listado de almacén de claves con keytool (funciona)
- cargar el almacén de claves mediante programación (falla con IOException: InvalidKeystoreFormat)
Lo que no obtengo es que, tanto en guardar como en cargar, uso KeyStore.getInstance (" JKS ") , pero falla. Cualquier sugerencia bienvenida!
Salida en tiempo de ejecución:
Creating private keystore at 'private.keystore'. Created keystore, now created signer cert Created signer cert, saving cert Reloading keystore: Failed to load the keystore after creation: Invalid keystore format
Fuente del caso de prueba:
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.InvalidKeyException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.SignatureException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import sun.security.x509.X500Name; public class KeystoreCreator { private String fPrivateKeyStore; private String fPrivateKeyStorePassword; private String fPrivateKeyStoreKeyPassword; private String fPublicKeyCipherPassword; private String fPrivateKeyAlias; /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { KeystoreCreator creator = new KeystoreCreator(); creator.setPrivateKeyStore("private.keystore"); creator.setPrivateKeyStorePassword("beer123"); creator.setPrivateKeyAlias("myalias"); creator.setPrivateKeyStoreKeyPassword("beer123"); creator.setPublicKeyCipherPassword("beer123"); creator.initKeyStores(); } public KeystoreCreator() { } public void setPrivateKeyStore(String name) { fPrivateKeyStore=name; } public void setPrivateKeyStorePassword(String pass) { fPrivateKeyStorePassword=pass; } public void setPrivateKeyStoreKeyPassword(String pass) { fPrivateKeyStoreKeyPassword=pass; } public void setPublicKeyCipherPassword(String pass) { fPublicKeyCipherPassword=pass; } public void setPrivateKeyAlias(String alias) { fPrivateKeyAlias=alias; } public void initKeyStores() throws Exception { OutputStream out = null; File f=new File(fPrivateKeyStore); if (f.exists()) { f.delete(); if (f.exists()) { throw new IOException("Want to remove the keystore but can't, still reported as present after removal"); } } try { System.out.println("Creating private keystore at '" + fPrivateKeyStore + "'."); out = new FileOutputStream(fPrivateKeyStore); KeyStore privateKeyStore = KeyStore.getInstance("JKS"); privateKeyStore.load(null, fPrivateKeyStorePassword.toCharArray()); System.out.println("Created keystore, now created signer cert"); X500Name x500name=getCA(); Certificate cert = createCertificate(fPrivateKeyAlias, fPrivateKeyStoreKeyPassword, x500name, privateKeyStore); System.out.println("Created signer cert, saving cert"); privateKeyStore.store(out, fPublicKeyCipherPassword.toCharArray()); out.flush(); out.close(); //try to load it. KeyStore reloadedKeyStore = KeyStore.getInstance("JKS"); try { InputStream reloadedIs=getClass().getClassLoader().getResourceAsStream(fPrivateKeyStore); if (reloadedIs!=null) { System.out.println("Reloading keystore:"); reloadedKeyStore.load(reloadedIs, fPrivateKeyStorePassword.toCharArray()); } } catch (Exception e) { System.err.println("Failed to load the keystore after creation: "+e.getLocalizedMessage()); } } catch (Exception e) { System.err.println("Failed to save the keystore: "+e.getLocalizedMessage()); } } private X500Name getCA() throws IOException { return new sun.security.x509.X500Name("a","b", "c","d","e", "GB"); } public Certificate createCertificate( String alias, String keyPassword, sun.security.x509.X500Name x500Name, KeyStore keyStore ) throws NoSuchAlgorithmException, InvalidKeyException, CertificateException, SignatureException, NoSuchProviderException, KeyStoreException { sun.security.x509.CertAndKeyGen keypair = new sun.security.x509.CertAndKeyGen( "RSA", "MD5WithRSA" ); keypair.generate( 1024 ); PrivateKey privKey = keypair.getPrivateKey(); X509Certificate[] chain = new X509Certificate[1]; chain[0] = keypair.getSelfCertificate( x500Name, 7000 * 24 * 60 * 60 ); keyStore.setKeyEntry( alias, privKey, keyPassword.toCharArray(), chain ); Certificate cert = keyStore.getCertificate( alias ); return cert; } }
Solución
1) Usted crea el almacén de claves privadas en el directorio de trabajo actual, escribiendo en un archivo : new FileOutputStream (fPrivateKeyStore);
2) Más tarde, lee desde la ruta de clase utilizando getClass().getClassLoader().getResourceAsStream(fPrivateKeyStore);
Creo que estás leyendo los archivos incorrectos. Y ya hay otro con el nombre private.keystore
de pruebas anteriores. Para verificar, es posible que desee imprimir la ruta absoluta del archivo de ambos archivos, p. new File (fPrivateKeyStore) .getAbsolutePath ()
y compárelo con getClass().getClassLoader().getResource(fPrivateKeyStore).toFileURL();
Otros consejos
Puede que me falte algo, pero ¿por qué no volver a cargar el almacén de claves privadas usando FileInputStream
?
InputStream reloadedIs = new FileInputStream(fPrivateKeyStore);
(No estoy seguro de que esto solucione el problema, solo lo noté mientras escaneaba su código)