Как прочитать пароль зашифрованный ключ с Java? - PullRequest
14 голосов
/ 16 апреля 2010

У меня есть закрытый ключ, который хранится в файле формата PKCS8 DER и защищен паролем. Какой самый простой способ прочитать это?

Вот код, который я использую для загрузки незашифрованного:

InputStream in = new FileInputStream(privateKeyFilename);
byte[] privateKeydata = new byte[in.available()];
in.read(privateKeydata);
in.close();
KeyFactory privateKeyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(privateKeydata);
PrivateKey privateKey = privateKeyFactory.generatePrivate(encodedKeySpec);

Отлично работает для незашифрованных ключей с той же спецификацией. Кстати, я использую BouncyCastle.

Я могу просмотреть этот закрытый ключ, используя следующую команду openssl

openssl pkcs8 -in ./privatekey.key -inform DER -passin pass:thisismypass

Пожалуйста, помогите !!!

Я опубликовал несколько решений в своем собственном ответе на эту тему. Но я оставляю вопрос без ответа на тот случай, если кто-нибудь может помочь заставить его работать без дополнительной библиотеки, только BouncyCastle.

Ответы [ 2 ]

8 голосов
/ 18 апреля 2010

Я нашел решение! Может быть, это не так элегантно, но ... Здесь я опубликую два решения:

  1. Желательно, но не работает
  2. Работает, но требует дополнительной библиотеки

First :

Я нашел какое-то решение здесь , но оно выдает исключение. Решение:

import java.io.*;
import java.security.*;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.*;

import javax.crypto.*;
import javax.crypto.spec.*;

/*
 * This class demonstrates how to import an encrypted RSA private key as
 * generated by openssl. The input file is presumed to be in DER
 * format.
 */
public class ImportEncryptedPrivateKey
{
    public static byte[] readPK8FromFile(String fileName) throws IOException
    {
        File f = new File(fileName);
        DataInputStream dis = new DataInputStream(new FileInputStream(f));
        byte[] theData = new byte[(int) f.length()];
        dis.readFully(theData);
        return theData;
    }

    public static void main(String[] args) throws IOException,
            NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeySpecException, InvalidKeyException,
            InvalidAlgorithmParameterException
    {
        byte[] encryptedPKInfo = readPK8FromFile("rsapriv.pk8");
        EncryptedPrivateKeyInfo ePKInfo = new EncryptedPrivateKeyInfo(
                encryptedPKInfo);
        char[] password = { 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' };
        Cipher cipher = Cipher.getInstance(ePKInfo.getAlgName());
        PBEKeySpec pbeKeySpec = new PBEKeySpec(password);
        // Now create the Key from the PBEKeySpec
        SecretKeyFactory skFac = SecretKeyFactory.getInstance(ePKInfo
                .getAlgName());
        Key pbeKey = skFac.generateSecret(pbeKeySpec);
        // Extract the iteration count and the salt
        AlgorithmParameters algParams = ePKInfo.getAlgParameters();
        cipher.init(Cipher.DECRYPT_MODE, pbeKey, algParams);
        // Decrypt the encryped private key into a PKCS8EncodedKeySpec
        KeySpec pkcs8KeySpec = ePKInfo.getKeySpec(cipher);
        // Now retrieve the RSA Public and private keys by using an
        // RSA keyfactory.
        KeyFactory rsaKeyFac = KeyFactory.getInstance("RSA");
        // First get the private key
        RSAPrivateCrtKey rsaPriv = (RSAPrivateCrtKey) rsaKeyFac.generatePrivate(pkcs8KeySpec);
        // Now derive the RSA public key from the private key
        RSAPublicKeySpec rsaPubKeySpec = new RSAPublicKeySpec(rsaPriv.getModulus(), rsaPriv.getPublicExponent());
        RSAPublicKey rsaPubKey = (RSAPublicKey) rsaKeyFac.generatePublic(rsaPubKeySpec);
    }

}

И мое исключение:

Exception in thread "main" java.security.NoSuchAlgorithmException: No such algorithm: 1.2.840.113549.1.5.13

Второй

И после этого http://juliusdavies.ca/commons-ssl/pkcs8.html вы можете прочитать о втором, рабочем решении

1 голос
/ 21 октября 2010

Это мой код и он работает:)

File f = new File(keyFile);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int)f.length()];
dis.readFully(keyBytes);
dis.close();
EncryptedPrivateKeyInfo encryptPKInfo = new EncryptedPrivateKeyInfo(keyBytes);
Cipher cipher = Cipher.getInstance(encryptPKInfo.getAlgName());
PBEKeySpec pbeKeySpec = new PBEKeySpec(passwd.toCharArray());
SecretKeyFactory secFac = SecretKeyFactory.getInstance(encryptPKInfo.getAlgName());
Key pbeKey = secFac.generateSecret(pbeKeySpec);
AlgorithmParameters algParams = encryptPKInfo.getAlgParameters();
cipher.init(Cipher.DECRYPT_MODE, pbeKey, algParams);
KeySpec pkcs8KeySpec = encryptPKInfo.getKeySpec(cipher);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(pkcs8KeySpec);
...