2010-04-16 12 views
13

Ich habe privaten Schlüssel in einer Datei im PKCS8 DER-Format gespeichert und durch ein Passwort geschützt. Was ist der einfachste Weg, um es zu lesen?Wie liest man einen Passwort-verschlüsselten Schlüssel mit Java?

Hier ist der Code, den ich eine unverschlüsselte zu laden verwenden, um:

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

Es funktioniert für unverschlüsselte Schlüssel mit der gleichen Spezifikation in Ordnung. Übrigens benutze ich BouncyCastle.

kann ich diesen privaten Schlüssel anzuzeigen folgenden openssl Befehl

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

Bitte Hilfe !!!

Ich habe einige Lösungen in meiner eigenen Antwort zu diesem Thema geschrieben. Aber ich behalte die Frage unbeantwortet für den Fall, dass irgendjemand helfen kann, es ohne extra Bibliothek zu machen, nur BouncyCastle.

Antwort

7

Ich fand die Lösung! Vielleicht ist es nicht so elegant, aber ... Hier werde ich zwei Lösungen posten:

  1. Prefferable, aber die Arbeit nicht
  2. ein Arbeiten, erfordert aber zusätzliche Bibliothek

Erste :

Ich fand eine Art Lösung here, aber es löst Ausnahme aus. Lösung:

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

} 

Und meine Ausnahme:

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

Zweite:

und im Anschluss an diese http://juliusdavies.ca/commons-ssl/pkcs8.html Sie über die zweite lesen können, Lösung

+0

+1 für noch nicht commons-ssl. Sie brauchen dann nicht einmal Bouncy Castle. – Thilo

+1

Für die zweite Lösung. Kannst du den Code hier einfügen? Ich kann diesen Link nicht öffnen. Welche Bibliothek hast du benutzt? – BRabbit27

+0

Das funktioniert eigentlich für mich. –

1

Arbeits Das ist mein Code und es funktioniert :)

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

Mit nur dem JDK (kein Bouncy Castle) bekomme ich "Kann keinen Anbieter finden, der 1.2.840.113549.1.5.13 unterstützt" (was die ID für PBEWithMD5AndDES ist). – Thilo

+1

Haben Sie es geschafft, den privaten Schlüssel mit nur Java API zu lesen? – BRabbit27