58 votes

Comment lister / exporter les clés privées d'un keystore ?

Comment lister et exporter une clé privée depuis un keystore ?

103voto

Donal Fellows Points 56559

Vous pouvez extraire une clé privée d'un keystore avec Java6 et OpenSSL. Tout dépend du fait que Java et OpenSSL supportent tous deux les keystores au format PKCS#12. Pour effectuer l'extraction, vous devez d'abord utiliser keytool pour convertir au format standard. Assurez-vous que vous utilisez le même mot de passe pour les deux fichiers (le mot de passe de la clé privée, pas celui du keystore) ou vous obtiendrez des échecs bizarres plus tard dans la deuxième étape.

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

Ensuite, utilisez OpenSSL pour faire l'extraction vers PEM :

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

Vous devriez être en mesure de traiter ce fichier PEM assez facilement ; c'est du texte brut avec une clé privée non cryptée et un ou plusieurs certificats à l'intérieur (dans un format assez évident).

Lorsque vous faites cela, veillez à sécuriser les fichiers créés. Ils contiennent des informations d'identification secrètes. Rien ne vous avertira si vous ne les sécurisez pas correctement. La méthode la plus simple pour les sécuriser est de faire tout cela dans un répertoire qui n'a pas de droits d'accès pour quelqu'un d'autre que l'utilisateur. Et ne mettez jamais votre mot de passe sur la ligne de commande ou dans des variables d'environnement ; c'est trop facile pour les autres utilisateurs.

31voto

ConroyP Points 24021

Une portion de code provenant de l'exemple de dépôt pour lister tous les alias dans un magasin de clés :

    // 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'exportation de clés privées est apparue sur le site de la Commission européenne. Forums du soleil il y a quelques mois, et u:turingcompleter a créé une classe DumpPrivateKey à intégrer dans votre application.

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

Note : ceci utilise le paquet Sun, ce qui est une "mauvaise chose" .
Si vous pouvez télécharger code apache commons Voici une version qui compilera sans avertissement :

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

et donnera le même résultat :

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

Vous pouvez l'utiliser comme ça :

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

6voto

Dustin Points 4694

Si vous n'avez pas besoin de le faire par programme, mais souhaitez simplement gérer vos clés, j'utilise depuis longtemps l'outil gratuit KeyMan d'IBM. Il est très pratique pour exporter une clé privée vers un fichier PFX (vous pouvez alors facilement utiliser OpenSSL pour la manipuler, l'extraire, changer les pwds, etc).

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

Sélectionnez votre keystore, sélectionnez l'entrée de la clé privée, puis File->Save to a pkcs12 file (*.pfx, typiquement). Vous pouvez ensuite visualiser le contenu avec :

$ openssl pkcs12 -in mykeyfile.pfx -info

5voto

jrk Points 70

Voici une version plus courte du code ci-dessus, en Groovy. L'encodage base64 est également intégré :

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

4voto

diyism Points 1191

Pour le développement d'Android, pour convertir le keystore créé dans eclipse ADT en clé publique et clé privée utilisées dans SignApk.jar :

exporter la clé privée :

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

modifier private.rsa.pem et laisser le paragraphe "-----BEGIN PRIVATE KEY-----" à "-----END PRIVATE KEY-----", ensuite :

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

la clé publique d'exportation :

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

signer l'apk :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X