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

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

Ответ 1

Часть кода, первоначально из примера 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: turingcompleter появился класс 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;
    }
}

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

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

Ответ 2

Вы можете извлечь закрытый ключ из хранилища ключей с помощью Java6 и OpenSSL. Все это зависит от того, что как Java, так и OpenSSL поддерживают K-хранилища в формате 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 достаточно легко; это простой текст с закодированным незашифрованным закрытым ключом и сертификатом (ов) внутри него (в довольно очевидном формате).

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

Ответ 3

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

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

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

$openssl pkcs12 -in mykeyfile.pfx -info

Ответ 4

Ниже приведена более короткая версия вышеуказанного кода в 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-----"

Ответ 5

Для разработки Android, для преобразования keystore, созданного в 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 и оставьте "----- НАЧАТЬ ЧАСТНЫЙ КЛЮЧ -----" на "----- END PRIVATE KEY -----", а затем:

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

Ответ 7

Прежде всего, будьте осторожны! Вся ваша безопасность зависит от & hellip; эр & hellip; конфиденциальность ваших личных ключей. 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 и вывести его в желаемом формате. Это станет хорошей темой для последующего вопроса.

Ответ 9

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