web-dev-qa-db-fra.com

Comment répertorier / exporter des clés privées à partir d'un magasin de clés?

Comment répertorier et exporter une clé privée à partir d'un magasin de clés?

58
ScArcher2

Une partie du code originaire d'Example Depot pour répertorier 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 a eu lieu le forums Sun il y a quelques mois, et : turingcompleter est venu avec une classe DumpPrivateKey à assembler 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;
    }
}

Remarque: ceci utilise le package Sun, ce qui est une "mauvaise chose" .
Si vous pouvez télécharger code Apache commons , voici une version qui se 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 ceci:

Java -classpath .:commons-codec-1.4/commons-codec-1.4.jar DumpPrivateKey $HOME/.keystore changeit Tomcat
31
ConroyP

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

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

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

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

Vous devriez pouvoir gérer ce fichier PEM assez facilement; c'est du texte brut avec une clé privée non chiffrée codée et des certificats à l'intérieur (dans un format assez évident).

Lorsque vous faites cela, veillez à garder les fichiers créés sécurisé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 aucun droit d'accès pour quiconque autre que l'utilisateur . Et ne mettez jamais votre mot de passe sur la ligne de commande ou dans des variables d'environnement; il est trop facile à saisir pour les autres utilisateurs.

103
Donal Fellows

Si vous n'avez pas besoin de le faire par programme, mais que vous souhaitez simplement gérer vos clés, alors j'utilise depuis longtemps l'outil gratuit KeyMan d'IBM. Très bien pour exporter une clé privée dans un fichier PFX (alors vous pouvez facilement utiliser OpenSSL pour le 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 fichier de clés, sélectionnez l'entrée de clé privée, puis Fichier-> Enregistrer dans un fichier pkcs12 (* .pfx, généralement). Vous pouvez ensuite visualiser le contenu avec:

$ openssl pkcs12 -in mykeyfile.pfx -info

6
DustinB

Voici une version plus courte du code ci-dessus, dans Groovy. Dispose également d'un encodage base64 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-----"
5
jrk

Pour Android, pour convertir le magasin de clés créé dans Eclipse ADT en clé publique et clé privée utilisée 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

éditez private.rsa.pem et laissez le paragraphe "----- BEGIN PRIVATE KEY -----" à "----- END PRIVATE KEY -----", puis:

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

exporter la clé publique:

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

signe apk:

Java -jar SignApk.jar public.x509.der private.rsa.der input.apk output.apk
4
diyism

Cette question est venue sur la sécurité stackexchange, une des suggestions était d'utiliser Keystore Explorer

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

Je viens de l'essayer, ça marche vraiment bien et je le recommande vivement.

4
PhilDin

Un autre excellent outil est KeyStore Explorer: http://keystore-Explorer.sourceforge.net/

3
Davio

Tout d'abord, soyez prudent! Toute votre sécurité dépend de la… euh… confidentialité de vos clés privées. Keytool n'a pas d'exportation de clé intégré pour éviter la divulgation accidentelle de ce matériel sensible, donc vous voudrez peut-être envisager des garanties supplémentaires qui pourraient être mises en place pour protéger vos clés exportées.

Voici un code simple qui vous donne PKCS # 8 PrivateKeyInfo non chiffré qui peut être utilisé par OpenSSL (voir le -nocrypt option de son tilitaire 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();
    }
  }
}

Si vous avez besoin d'autres formats, vous pouvez utiliser une KeyFactory pour obtenir une spécification de clé transparente pour différents types de clés. Ensuite, vous pouvez obtenir, par exemple, l'exposant privé d'une clé privée RSA et le produire dans le format souhaité. Cela ferait un bon sujet pour une question de suivi.

3
erickson

Un autre moyen moins conventionnel mais sans doute plus simple de le faire est d'utiliser JXplorer . Bien que cet outil soit conçu pour parcourir les répertoires LDAP, il possède une interface graphique facile à utiliser pour manipuler les magasins de clés. L'une de ces fonctions sur l'interface graphique peut exporter des clés privées à partir d'un fichier de clés JKS.

1
Kkkev