Domanda

Come posso elencare ed esportare una chiave privata da un keystore?

È stato utile?

Soluzione

Una parte di codice originariamente dal depot di esempio per elencare tutti gli alias in un keystore:

    // Load input stream into keystore
    keystore.load(is, password.toCharArray());

    // List the aliases
    Enumeration aliases = keystore.aliases();
    for (; aliases.hasMoreElements(); ) {
        String alias = (String)aliases.nextElement();

        // Does alias refer to a private key?
        boolean b = keystore.isKeyEntry(alias);

        // Does alias refer to a trusted certificate?
        b = keystore.isCertificateEntry(alias);
    }

L'esportazione di chiavi private è avvenuta nei Sun forum un paio di mesi fa e u: turingcompleter ha realizzato una classe DumpPrivateKey per ricucire la tua app.

import java.io.FileInputStream;
import java.security.Key;
import java.security.KeyStore;
import sun.misc.BASE64Encoder;

public class DumpPrivateKey {
     /**
     * Provides the missing functionality of keytool
     * that Apache needs for SSLCertificateKeyFile.
     *
     * @param args  <ul>
     *              <li> [0] Keystore filename.
     *              <li> [1] Keystore password.
     *              <li> [2] alias
     *              </ul>
     */
    static public void main(String[] args)
    throws Exception {
        if(args.length < 3) {
          throw new IllegalArgumentException("expected args: Keystore filename, Keystore password, alias, <key password: default same tha
n keystore");
        }
        final String keystoreName = args[0];
        final String keystorePassword = args[1];
        final String alias = args[2];
        final String keyPassword = getKeyPassword(args,keystorePassword);
        KeyStore ks = KeyStore.getInstance("jks");
        ks.load(new FileInputStream(keystoreName), keystorePassword.toCharArray());
        Key key = ks.getKey(alias, keyPassword.toCharArray());
        String b64 = new BASE64Encoder().encode(key.getEncoded());
        System.out.println("-----BEGIN PRIVATE KEY-----");
        System.out.println(b64);
        System.out.println("-----END PRIVATE KEY-----");
    }
    private static String getKeyPassword(final String[] args, final String keystorePassword)
    {
       String keyPassword = keystorePassword; // default case
       if(args.length == 4) {
         keyPassword = args[3];
       }
       return keyPassword;
    }
}

Nota: questo usa il pacchetto Sun, che è un " cosa negativa " .
Se puoi scaricare codice commons apache , ecco una versione che verrà compilata senza preavviso:

javac -classpath .:commons-codec-1.4/commons-codec-1.4.jar DumpPrivateKey.java

e darà lo stesso risultato:

import java.io.FileInputStream;
import java.security.Key;
import java.security.KeyStore;
//import sun.misc.BASE64Encoder;
import org.apache.commons.codec.binary.Base64;

public class DumpPrivateKey {
     /**
     * Provides the missing functionality of keytool
     * that Apache needs for SSLCertificateKeyFile.
     *
     * @param args  <ul>
     *              <li> [0] Keystore filename.
     *              <li> [1] Keystore password.
     *              <li> [2] alias
     *              </ul>
     */
    static public void main(String[] args)
    throws Exception {
        if(args.length < 3) {
          throw new IllegalArgumentException("expected args: Keystore filename, Keystore password, alias, <key password: default same tha
n keystore");
        }
        final String keystoreName = args[0];
        final String keystorePassword = args[1];
        final String alias = args[2];
        final String keyPassword = getKeyPassword(args,keystorePassword);
        KeyStore ks = KeyStore.getInstance("jks");
        ks.load(new FileInputStream(keystoreName), keystorePassword.toCharArray());
        Key key = ks.getKey(alias, keyPassword.toCharArray());
        //String b64 = new BASE64Encoder().encode(key.getEncoded());
        String b64 = new String(Base64.encodeBase64(key.getEncoded(),true));
        System.out.println("-----BEGIN PRIVATE KEY-----");
        System.out.println(b64);
        System.out.println("-----END PRIVATE KEY-----");
    }
    private static String getKeyPassword(final String[] args, final String keystorePassword)
    {
       String keyPassword = keystorePassword; // default case
       if(args.length == 4) {
         keyPassword = args[3];
       }
       return keyPassword;
    }
}

Puoi usarlo in questo modo:

java -classpath .:commons-codec-1.4/commons-codec-1.4.jar DumpPrivateKey $HOME/.keystore changeit tomcat

Altri suggerimenti

È possibile estrarre una chiave privata da un keystore con Java6 e OpenSSL. Tutto dipende dal fatto che sia Java che OpenSSL supportano i keystore formattati PKCS # 12. Per eseguire l'estrazione, devi prima usare keytool per convertire nel formato standard. Assicurati di utilizzare la stessa password per entrambi i file (password della chiave privata, non la password del keystore) o otterrai strani errori in seguito nel secondo passaggio.

keytool -importkeystore -srckeystore keystore.jks \
    -destkeystore intermediate.p12 -deststoretype PKCS12

Successivamente, utilizzare OpenSSL per eseguire l'estrazione in PEM:

openssl pkcs12 -in intermediate.p12 -out extracted.pem -nodes

Dovresti essere in grado di gestire quel file PEM abbastanza facilmente; è un testo semplice con una chiave privata non crittografata codificata e certificati al suo interno (in un formato piuttosto ovvio).

Quando lo fai, fai attenzione a proteggere i file creati. Contengono credenziali segrete. Nulla ti avviserà se non riesci a proteggerli correttamente. Il metodo più semplice per proteggerli è fare tutto questo in una directory che non ha alcun diritto di accesso per nessun altro che l'utente. E non mettere mai la tua password nella riga di comando o nelle variabili di ambiente; è troppo facile da afferrare per altri utenti.

Se non hai bisogno di farlo a livello di codice, ma vuoi solo gestire le tue chiavi, allora ho usato lo strumento KeyMan gratuito di IBM da molto tempo ormai. Molto utile per esportare una chiave privata in un file PFX (quindi puoi facilmente usare OpenSSL per manipolarlo, estrarlo, cambiare pwds, ecc.)

https :? //www.ibm.com/developerworks/mydeveloperworks/groups/service/html/communityview communityUuid = 6fb00498-f6ea-4f65-bf0c-adc5bd0c5fcc

Seleziona il tuo keystore, seleziona la voce della chiave privata, quindi File- > Salva in un file pkcs12 (* .pfx, in genere). È quindi possibile visualizzare i contenuti con:

$ openssl pkcs12 -in mykeyfile.pfx -info

Ecco una versione più corta del codice sopra, in Groovy. Ha anche la codifica Base64 integrata:

import java.security.Key
import java.security.KeyStore

if (args.length < 3)
        throw new IllegalArgumentException('Expected args: <Keystore file> <Keystore format> <Keystore password> <alias> <key password>')

def keystoreName = args[0]
def keystoreFormat = args[1]
def keystorePassword = args[2]
def alias = args[3]
def keyPassword = args[4]

def keystore = KeyStore.getInstance(keystoreFormat)
keystore.load(new FileInputStream(keystoreName), keystorePassword.toCharArray())
def key = keystore.getKey(alias, keyPassword.toCharArray())

println "-----BEGIN PRIVATE KEY-----"
println key.getEncoded().encodeBase64()
println "-----END PRIVATE KEY-----"

Per lo sviluppo Android, per convertire il keystore creato in eclipse ADT in chiave pubblica e chiave privata utilizzata in SignApk.jar:

esporta chiave privata:

keytool.exe -importkeystore -srcstoretype JKS -srckeystore my-release-key.keystore -deststoretype PKCS12 -destkeystore keys.pk12.der
openssl.exe pkcs12 -in keys.pk12.der -nodes -out private.rsa.pem

modifica private.rsa.pem e lascia " ----- INIZIA TASTO PRIVATO ----- " a " ----- FINE TASTO PRIVATO ----- " paragrafo, quindi:

openssl.exe base64 -d -in private.rsa.pem -out private.rsa.der

esporta chiave pubblica:

keytool.exe -exportcert -keystore my-release-key.keystore -storepass <KEYSTORE_PASSWORD> -alias alias_name -file public.x509.der

firma apk:

java -jar SignApk.jar public.x509.der private.rsa.der input.apk output.apk

Questa domanda è emersa sulla sicurezza di stackexchange, uno dei suggerimenti era di utilizzare Explorer archivio chiavi

https: / /security.stackexchange.com/questions/3779/how-can-i-export-my-private-key-from-a-java-keytool-keystore

Avendolo appena provato, funziona davvero bene e lo consiglio vivamente.

Prima di tutto, fai attenzione! Tutta la tua sicurezza dipende dalla ... er ... privacy delle tue chiavi private. Keytool non ha l'esportazione delle chiavi incorporata per evitare la divulgazione accidentale di questo materiale sensibile, quindi tu potrebbe voler prendere in considerazione alcune garanzie aggiuntive che potrebbero essere messe in atto per proteggere le chiavi esportate.

Ecco un semplice codice che ti dà PKCS # 8 PrivateKeyInfo non crittografato che può essere usato da OpenSSL (vedi l'opzione -nocrypt della sua opzione utility pkcs8 ):

KeyStore keys = ...
char[] password = ...
Enumeration<String> aliases = keys.aliases();
while (aliases.hasMoreElements()) {
  String alias = aliases.nextElement();
  if (!keys.isKeyEntry(alias))
    continue;
  Key key = keys.getKey(alias, password);
  if ((key instanceof PrivateKey) && "PKCS#8".equals(key.getFormat())) {
    /* Most PrivateKeys use this format, but check for safety. */
    try (FileOutputStream os = new FileOutputStream(alias + ".key")) {
      os.write(key.getEncoded());
      os.flush();
    }
  }
}

Se sono necessari altri formati, è possibile utilizzare una KeyFactory per ottenere una specifica di chiave trasparente per diversi tipi di chiavi. Quindi puoi ottenere, ad esempio, l'esponente privato di una chiave privata RSA e inviarlo nel formato desiderato. Ciò costituirebbe un buon argomento per una domanda di follow-up.

Un altro ottimo strumento è KeyStore Explorer: http://keystore-explorer.sourceforge.net/

Un altro modo meno convenzionale ma probabilmente più semplice di farlo è con JXplorer . Sebbene questo strumento sia progettato per sfogliare le directory LDAP, ha una GUI facile da usare per manipolare i keystore. Una di queste funzioni sulla GUI può esportare chiavi private da un keystore JKS.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top