2014-04-14 3 views
5

Ich habe eine private Schlüsseldatei mit DES/ECB/PKCS5Padding (56 Bit DES-Schlüssel generiert durch eine geheime Phrase) und ich möchte es entschlüsseln. Ich weiß nicht, warum, aber jedes Mal wenn ich versuche, die Methode doFinal meiner Chiffre Klasse decript, wird diesen Fehler zu werfen:BadPaddingException: Endgültige Block nicht ordnungsgemäß gepolstert

javax.crypto.BadPaddingException: Given final block not properly padded at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) at com.sun.crypto.provider.DESCipher.engineDoFinal(DashoA13*..) at javax.crypto.Cipher.doFinal(DashoA13*..) at...

Hier ist mein Code:

public static PrivateKey readPrivateKeyFromFile(File file, String chaveSecreta) { 
    try { 
     SecureRandom r = new SecureRandom(chaveSecreta.getBytes()); 
     KeyGenerator keyGen = KeyGenerator.getInstance("DES"); 
     keyGen.init(56, r); 
     Key key = keyGen.generateKey(); 

     byte[] privateKeyBytes = decryptPKFile(file, key); 

     KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 
     EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes); 
     PrivateKey privateKey = null; 
     try { 
      privateKey = keyFactory.generatePrivate(privateKeySpec); 
     } catch (InvalidKeySpecException e) { 
      JOptionPane.showMessageDialog(null, "Erro 01, tente mais tarde"); 
     } 
     return privateKey; 
    } catch (NoSuchAlgorithmException e) { 
     JOptionPane.showMessageDialog(null, "Erro 02, tente mais tarde"); 
    } 
    return null; 
} 

public static byte[] decryptPKFile(File file, Key key){ 
    try{ 
     Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); 
     byte[] cipherText = readBytes(file); 
     cipher.init(Cipher.DECRYPT_MODE, key); 
     System.out.println(cipher); 
     System.out.println(cipherText); 
     byte[] text = cipher.doFinal(cipherText); 
     return text; 
    }catch(Exception e){ 
     e.printStackTrace(); 
     return null; 
    } 
} 

public static byte[] readBytes(File file) { 
    try { 
     FileInputStream fs = new FileInputStream(file); 
     byte content[] = new byte[(int) file.length()]; 
     fs.read(content); 
     return content; 
    } catch (FileNotFoundException e) { 
     System.out.println("Arquivo não encontrado!"); 
     e.printStackTrace(); 
    } catch (IOException ioe) { 
     System.out.println("Erro ao ler arquivo!"); 
     ioe.printStackTrace(); 
    } 
    return null; 
} 

Alle syggestions?

+0

Ich vermute, die Eingabe, die Sie aus der Datei lesen, ist kein gültiger verschlüsselter Text. Da DES ein Blockalgorithmus ist, sollten Sie prüfen, ob die Länge der Datei eine Multiplikation von 64 ist. Wenn nicht, würde dies bedeuten, dass die Datei beschädigt ist. – markubik

+2

Sie meinen mehrere von 8? Es ist, die Datei ist nicht beschädigt, ich habe überprüft. –

+0

@markubik Es ist ein zufälliger Schlüssel: P –

Antwort

8

Sie versuchen, den Chiffretext mit einem Zufallszahlengenerator zu entschlüsseln, der mit einem bestimmten Seed erzeugt wurde. Sie geben jedoch keinen Algorithmus an und der Algorithmus kann sich auch intern ändern. Es ist sogar bekannt, dass Android stattdessen für einige Versionen einen vollständig zufälligen Wert generiert.

Sie müssen eine SecretKeyFactory nicht eine KeyGenerator verwenden. Und Sie werden natürlich die 8-Byte-Schlüsseldaten benötigen. Die einzige Möglichkeit, dies in Ihrem Fall abzurufen, besteht darin, den SecureRandom Algorithmus/die Implementierung zu finden und den Schlüssel neu zu berechnen.

Nun wird jeder verschlüsselte Text mit einem beliebigen Schlüssel entschlüsseln. DES EZB stellt nur (irgendeine Art von) Vertraulichkeit zur Verfügung, nicht Integrität. Das Problem ist, dass es in Müll entschlüsselt wird. Wenn Sie nun versuchen, das Padding aus dem Müll zu entfernen, erhalten Sie wahrscheinlich einen Padding-Fehler.

Wenn Sie "Glück" haben - einmal in etwa 256 Mal - erhalten Sie ein Ergebnis. Dies passiert, wenn der entschlüsselte Block mit 01 oder 0202 endet, das ist gültiges Padding. Das Ergebnis wird natürlich Müll sein, aber es wird nicht mit einem BadPaddingException enden. In Ihrem Fall ist die SecureRandom Instanz wahrscheinlich, um den gleichen falschen Wert immer und immer wieder, so dass dies nie passieren kann.

Bitte verwenden Sie in Zukunft PBKDF2 und geben Sie das verschlüsselte Passwort ein. Beachten Sie die verwendete Zeichencodierung, Java SE verwendet die niedrigsten 8 Bits des char-Arrays. Verwenden Sie niemals String.getBytes(), da die Standardcodierung von System zu System unterschiedlich sein kann.

+1

Puh, tut mir leid für die vielen Bearbeitungen, es wird spät. –

+2

Ich denke, es liegt an meinem System. Alles funktioniert mit Windows, aber es funktioniert nicht auf meinem Mac. Raten Sie, es ist die String.getBytes() Sache, die Sie sagten. –

+1

http://StackOverflow.com/Questions/9312816/java-platforms-default-charset-on-different-platforms –

Verwandte Themen