Pergunta

Como faço lista e exportar uma chave privada a partir de um armazenamento de chaves?

Foi útil?

Solução

Uma parte do código originalmente do Exemplo Depot para listar todos os aliases em uma loja chave:

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

A exportação de chaves privadas surgiu nas Sun fóruns um par de meses atrás, e u: turingcompleter veio com uma classe DumpPrivateKey costurar em seu aplicativo.

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

Nota: este uso pacote Sun, que é um "mau coisa ".
Se você pode baixar apache commons código , aqui está uma versão que irá compilar sem aviso:

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

e vai dar o mesmo resultado:

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

Você pode usá-lo assim:

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

Outras dicas

Você pode extrair uma chave privada a partir de um armazenamento de chaves com Java6 e OpenSSL. Isso tudo depende do fato de que ambos os PKCS suporte a Java e OpenSSL keystores # 12-formatado. Para fazer a extração, utilize primeiro keytool para converter para o formato padrão. Certifique-se de que você usar a mesma senha para ambos os arquivos (senha da chave privada, não a senha de armazenamento de chaves) , ou você receberá falhas estranhas, mais tarde, na segunda etapa.

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

Em seguida, uso OpenSSL para fazer a extração de PEM:

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

Você deve ser capaz de lidar com esse arquivo PEM com bastante facilidade; é texto simples com uma chave codificada sem criptografia privada e certificado (s) dentro dela (em um formato bastante óbvio).

Quando você fizer isso, tome cuidado para manter os arquivos criados seguro. Eles contêm as credenciais secretas. Nada irá avisá-lo se você não conseguir fixá-los corretamente. O método mais fácil para proteger-los é fazer tudo isso em um diretório que não tem quaisquer direitos de acesso para qualquer um que não seja o usuário. E nunca colocar a sua senha na linha de comando ou em variáveis ??de ambiente; é muito fácil para outros usuários para agarrar.

Se você não precisa fazê-lo através de programação, mas apenas pretende gerir as suas chaves, então eu usei ferramenta KeyMan livre da IBM por um longo tempo agora. Muito bom para exportar uma chave privada para um arquivo PFX (então você pode facilmente usar OpenSSL para manipulá-lo, extraí-lo, pwds mudança, etc).

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

Selecione o seu armazenamento de chaves, selecione a entrada de chave privada, então Arquivo-> Salvar para um arquivo PKCS12 (* .pfx, tipicamente). Você pode, então, visualizar o conteúdo com:

$ openssl pkcs12 -in mykeyfile.pfx -info

Aqui está uma versão mais curta do código acima, em Groovy. Também foi construído com codificação 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-----"

Para o desenvolvimento android, Para converter keystore criado em ADT eclipse em chave pública e chave privada usada em SignApk.jar:

exportação de chave privada:

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

editar private.rsa.pem e licença "----- BEGIN CHAVE PRIVADA -----" para "----- END CHAVE PRIVADA -----" parágrafo, então:

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

exportação de chave pública:

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

sinal apk:

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

Esta questão surgiu na segurança Stackexchange, uma das sugestões foi utilizar Keystore explorador

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

Tendo apenas tentou fazê-lo, ele funciona muito bem e eu recomendo fortemente.

Em primeiro lugar, tenha cuidado! Toda a sua segurança depende do ... er ... privacidade de sua chaves privadas. Keytool não ter de exportação chave construído em para evitar a divulgação acidental deste material sensível, para que você pode querer considerar algumas salvaguardas adicionais que poderiam ser postas em prática para proteger suas chaves exportados.

Aqui está um código simples que lhe dá não criptografado PKCS # 8 PrivateKeyInfo que pode ser usado pelo OpenSSL (veja a opção -nocrypt de sua PKCS8 utilidade ):

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

Se você precisar de outros formatos, você pode usar um KeyFactory para obter uma especificação de chave transparente para diferentes tipos de chaves. Então você pode obter, por exemplo, o expoente privado de uma chave privada RSA e sua saída será no seu formato desejado. Que faria um bom tema para uma pergunta de acompanhamento.

Outra grande ferramenta é KeyStore Explorer: http://keystore-explorer.sourceforge.net/

Outra forma menos convencional, mas sem dúvida mais fácil de fazer isso é com JXplorer . Embora esta ferramenta é projetada para procurar diretórios LDAP, tem uma interface gráfica fácil de usar para manipular keystores. Um tal função no GUI pode exportar chaves privadas a partir de um armazenamento de chave JKS.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top