2010-04-16 9 views
13

Mam prywatny klucz zapisany w pliku w formacie PKCS8 DER i chroniony hasłem. Jaki jest najprostszy sposób, aby go przeczytać?Jak odczytać klucz zaszyfrowany hasłem za pomocą java?

Oto kod używam załadować niezaszyfrowane jeden:

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

To działa dobrze dla niezaszyfrowanych kluczy o tej samej specyfikacji. Przy okazji, używam BouncyCastle.

mogę zobaczyć ten klucz prywatny za pomocą następujących openssl polecenia

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

Proszę, pomóż !!!

Napisałem kilka rozwiązań w mojej własnej odpowiedzi na ten temat. Pozostaje jednak pytanie bez odpowiedzi, na wypadek gdyby ktokolwiek mógł pomóc w jego pracy bez dodatkowej biblioteki, tylko BouncyCastle.

Odpowiedz

7

Znalazłem rozwiązanie! Może to nie jest tak eleganckie, ale ... Tutaj będę pisać dwa rozwiązania:

  1. prefferable, ale nie działa
  2. Praca jeden, ale wymaga dodatkowej biblioteki

First :

Znalazłem rodzaj rozwiązania here, ale zgłasza wyjątek. Rozwiązanie:

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

} 

A mój wyjątek:

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

drugie:

oraz po to http://juliusdavies.ca/commons-ssl/pkcs8.html można przeczytać o sekundę, roztwór roboczy

+0

+1 dla nie-jeszcze-commons-ssl. Nie potrzebujesz wtedy Bouncy Castle. – Thilo

+1

Dla drugiego rozwiązania. Czy możesz tutaj wkleić kod? Nie mogę otworzyć tego linku. Z jakiej biblioteki korzystałeś? – BRabbit27

+0

To faktycznie działa dla mnie. –

1

To jest mój kod i to działa :)

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); 
+1

Tylko z JDK (bez dmuchanego zamku) otrzymuję komunikat "Nie mogę znaleźć żadnego dostawcy obsługującego 1.2.840.113549.1.5.13" (który jest identyfikatorem dla PBEWithMD5AndDES). – Thilo

+1

Czy udało Ci się odczytać klucz prywatny za pomocą interfejsu API Java? – BRabbit27

Powiązane problemy