Как мне перечислить / экспортировать закрытые ключи из хранилища ключей?

StackOverflow https://stackoverflow.com/questions/150167

  •  02-07-2019
  •  | 
  •  

Вопрос

Как мне перечислить и экспортировать закрытый ключ из хранилища ключей?

Это было полезно?

Решение

Фрагмент кода, первоначально взятый из Example Depot для перечисления всех псевдонимов в хранилище ключей:

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

Экспорт закрытых ключей появился на Форумы Sun пару месяцев назад, и u: туринский измеритель придумал класс DumpPrivateKey для вшивания в ваше приложение.

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

Примечание:для этого используйте солнцезащитный пакет, что является "плохой вещью"..
Если вы можете скачать код apache commons для общего доступа, вот версия , которая будет скомпилирована без предупреждения:

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

и даст тот же результат:

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

Вы можете использовать его следующим образом:

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

Другие советы

Вы можете извлечь закрытый ключ из хранилища ключей с помощью Java6 и OpenSSL.Все это зависит от того факта, что как Java, так и OpenSSL поддерживают хранилища ключей в формате PKCS # 12.Чтобы выполнить извлечение, вы сначала используете keytool для преобразования в стандартный формат.Убедитесь, что вы используйте один и тот же пароль для обоих файлов (пароль закрытого ключа, а не пароль хранилища ключей). или вы получите странные сбои позже, на втором шаге.

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

Затем используйте OpenSSL для извлечения в PEM:

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

Вы должны быть в состоянии достаточно легко справиться с этим PEM-файлом;это обычный текст с закодированным незашифрованным закрытым ключом и сертификатами внутри него (в довольно очевидном формате).

Когда вы делаете это, позаботьтесь о том, чтобы сохранить созданные файлы в безопасности.Они содержат секретные учетные данные.Ничто не предупредит вас, если вы не сможете закрепить их должным образом. Самый простой способ обезопасить их - сделать все это в каталоге, который не имеет никаких прав доступа ни для кого, кроме пользователя.И никогда не вводите свой пароль в командной строке или в переменных окружения;это слишком легко для других пользователей.

Если вам не нужно делать это программно, а просто хотите управлять своими ключами, то я уже давно пользуюсь бесплатным инструментом IBM KeyMan.Очень удобно экспортировать закрытый ключ в PFX-файл (тогда вы можете легко использовать OpenSSL для манипулирования им, извлечения, изменения pwd и т.д.).

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

Выберите хранилище ключей, выберите запись закрытого ключа, затем Файл-> Сохранить в файл pkcs12 (обычно * .pfx).Затем вы можете просмотреть содержимое с помощью:

$ openssl pkcs12 -в mykeyfile.pfx -info

Вот сокращенная версия приведенного выше кода на языке Groovy.Также имеет встроенную кодировку base64:

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

Для разработки под Android преобразовать хранилище ключей, созданное в eclipse ADT, в открытый ключ и закрытый ключ, используемый в SignApk.jar:

экспортировать закрытый ключ:

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

отредактируйте private.rsa.pem и замените "----- НАЧАЛО ЗАКРЫТОГО КЛЮЧА-----" на "----- КОНЕЦ ЗАКРЫТОГО КЛЮЧА-----" абзаца, затем:

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

экспорт открытого ключа:

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

знак apk:

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

Этот вопрос возник в stackexchange security, одним из предложений было использовать Проводник хранилища ключей

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

Я только что попробовал его, и он работает действительно хорошо, и я настоятельно рекомендую его.

Прежде всего, будьте осторожны!Вся ваша безопасность зависит от ... э-э… конфиденциальность из вашего закрытые ключи. Keytool не имеет встроенного экспорта ключей, чтобы избежать случайного раскрытия этого конфиденциального материала, поэтому вы можете рассмотреть некоторые дополнительные меры предосторожности, которые можно было бы применить для защиты ваших экспортированных ключей.

Вот несколько простых кодов, которые предоставляют вам незашифрованный PKCS # 8 PrivateKeyInfo, который может быть использован OpenSSL (см. -nocrypt вариант его утилита 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();
    }
  }
}

Если вам нужны другие форматы, вы можете использовать KeyFactory, чтобы получить прозрачную спецификацию ключа для различных типов ключей.Затем вы можете получить, например, закрытый показатель закрытого ключа RSA и вывести его в желаемом формате.Это было бы хорошей темой для последующего вопроса.

Еще одним замечательным инструментом является KeyStore Explorer: http://keystore-explorer.sourceforge.net/

Другой менее традиционный, но, возможно, более простой способ сделать это - с помощью JXplorer.Хотя этот инструмент предназначен для просмотра каталогов LDAP, он имеет простой в использовании графический интерфейс для управления хранилищами ключей.Одна из таких функций в графическом интерфейсе может экспортировать закрытые ключи из хранилища ключей JKS.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top