Question

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

Était-ce utile?

La solution

Une partie du code originaire d’Exemple Depot pour répertorier tous les alias d’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 les forums Sun il y a quelques mois, et u: turingcompleter a créé une classe DumpPrivateKey à broder 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: il s’agit du package Sun, qui est un " mauvaise chose " .
Si vous pouvez télécharger le code apache commons , voici une version qui sera compilée 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 suit:

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

Autres conseils

Vous pouvez extraire une clé privée d'un magasin de clés avec Java6 et OpenSSL. Tout cela dépend du fait que Java et OpenSSL prennent en charge les magasins de clés au format PKCS # 12. Pour effectuer l'extraction, utilisez d'abord keytool pour convertir au format standard. Assurez-vous que vous utilisez le même mot de passe pour les deux fichiers (mot de passe de clé privée, pas le mot de passe du magasin de clés) , sinon 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 être capable de gérer ce fichier PEM assez facilement; c'est du texte brut avec une clé privée non chiffrée et un ou plusieurs 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 consiste à effectuer toutes ces opérations dans un répertoire ne disposant d'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 les variables d'environnement; il est trop facile à saisir pour les autres utilisateurs.

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

clé privée d'exportation:

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

Modifiez private.rsa.pem et laissez "----- COMMENCER LA CLÉ PRIVÉE -----". sur "----- FIN DE LA CLE PRIVEE -----" paragraphe, alors:

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

clé publique d'exportation:

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

signer apk:

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

Tout d’abord, soyez prudent! Toute votre sécurité dépend du & # 8230; er & # 8230; confidentialité de vos clés privées. Keytool n'a pas d'export de clé intégré pour éviter la divulgation accidentelle de ce contenu sensible. Par conséquent, vous voudrez peut-être envisager des mesures de protection supplémentaires mis en place pour protéger vos clés exportées.

Voici un code simple qui vous donne une clé privée PKCS # 8 PrivateKeyInfo pouvant être utilisée par OpenSSL (voir l’option -nocrypt de son Utilitaire 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 KeyFactory pour obtenir une spécification de clé transparente pour différents types de clé. Vous pouvez ensuite obtenir, par exemple, l’exposant privé d’une clé privée RSA et l’extraire au format souhaité. Cela ferait un bon sujet pour une question de suivi.

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

JXplorer constitue un autre moyen moins conventionnel, mais sans doute plus facile, de le faire. Bien que cet outil soit conçu pour parcourir les annuaires LDAP, il possède une interface utilisateur graphique facile à utiliser pour manipuler les magasins de clés. L’une de ces fonctions de l’interface graphique peut exporter des clés privées d’un magasin de clés JKS.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top