2015-02-20 11 views
8

Ich habe eine Anleitung zur Implementierung der AES-Verschlüsselung/Entschlüsselung in Java gefunden und versucht jede Zeile zu verstehen, wie ich sie in meine eigene Lösung einfüge. Ich verstehe es jedoch nicht vollständig und habe dadurch Probleme. Das Endziel ist die Verschlüsselung/Entschlüsselung auf Passphrase-Basis. Ich habe über diese andere Artikel/Stackoverflow Beiträge lesen, aber die meisten bieten nicht genug Erklärung (ich bin sehr neu in Java Crypto)AES-256 Passwortbasierte Verschlüsselung/Entschlüsselung in Java

Meine wichtigsten Fragen im Augenblick sind, dass selbst wenn ich byte[] saltBytes = "Hello".getBytes(); stelle ich immer noch eine bekommen unterschiedliches Base64 Ergebnis am Ende (char[] password ist jedes Mal zufällig, aber ich gelesen, dass es sicherer ist, Passwörter in char[] Form zu verlassen. Mein anderes Problem ist, dass, wenn das Programm auf decrypt() bekommt, erhalte ich eine Nullpointer bei byte[] saltBytes = salt.getBytes("UTF-8");

Vielen Dank im Voraus für jede Hilfe/Beratung, die Sie mir geben können

Der Code in Frage:

import java.security.AlgorithmParameters; 
import java.security.NoSuchAlgorithmException; 
import java.security.SecureRandom; 

import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.SecretKey; 
import javax.crypto.SecretKeyFactory; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.PBEKeySpec; 
import javax.crypto.spec.SecretKeySpec; 
import javax.xml.bind.DatatypeConverter; 

public class EncryptionDecryption { 

    private static String salt; 
    private static int iterations = 65536 ; 
    private static int keySize = 256; 
    private static byte[] ivBytes; 

    public static void main(String []args) throws Exception { 

     char[] message = "PasswordToEncrypt".toCharArray(); 
     System.out.println("Message: " + message.toString()); 
     System.out.println("Encrypted: " + encrypt(message)); 
     System.out.println("Decrypted: " + decrypt(encrypt(message).toCharArray())); 
    } 

    public static String encrypt(char[] plaintext) throws Exception { 

     salt = getSalt(); 
     byte[] saltBytes = salt.getBytes(); 

     SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
     PBEKeySpec spec = new PBEKeySpec(plaintext, saltBytes, iterations, keySize); 
     SecretKey secretKey = skf.generateSecret(spec); 
     SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getEncoded(), "AES"); 

     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, secretSpec); 
     AlgorithmParameters params = cipher.getParameters(); 
     ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV(); 
     byte[] encryptedTextBytes = cipher.doFinal(plaintext.toString().getBytes("UTF-8")); 

     return DatatypeConverter.printBase64Binary(encryptedTextBytes); 
    } 

    public static String decrypt(char[] encryptedText) throws Exception { 

     byte[] saltBytes = salt.getBytes("UTF-8"); 
     byte[] encryptedTextBytes = DatatypeConverter.parseBase64Binary(encryptedText.toString()); 

     SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
     PBEKeySpec spec = new PBEKeySpec(encryptedText, saltBytes, iterations, keySize); 
     SecretKey secretkey = skf.generateSecret(spec); 
     SecretKeySpec secretSpec = new SecretKeySpec(secretkey.getEncoded(), "AES"); 

     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.DECRYPT_MODE, secretSpec, new IvParameterSpec(ivBytes)); 

     byte[] decryptedTextBytes = null; 

     try { 
      decryptedTextBytes = cipher.doFinal(encryptedTextBytes); 
     } catch (IllegalBlockSizeException e) { 
      e.printStackTrace(); 
     } catch (BadPaddingException e) { 
      e.printStackTrace(); 
     } 

     return decryptedTextBytes.toString(); 

    } 

    public static String getSalt() throws Exception { 

     SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 
     byte[] salt = new byte[20]; 
     sr.nextBytes(salt); 
     return salt.toString(); 
    } 
} 

Antwort

17

Ich denke, dass man zwei Fehler machen :)

ich Ihr Beispielcode korrigiert haben, damit es funktioniert:

import java.security.AlgorithmParameters; 
import java.security.NoSuchAlgorithmException; 
import java.security.SecureRandom; 

import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.SecretKey; 
import javax.crypto.SecretKeyFactory; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.PBEKeySpec; 
import javax.crypto.spec.SecretKeySpec; 
import javax.xml.bind.DatatypeConverter; 

public class EncryptionDecryption { 

    private static String salt; 
    private static int iterations = 65536 ; 
    private static int keySize = 256; 
    private static byte[] ivBytes; 

    private static SecretKey secretKey; 

    public static void main(String []args) throws Exception { 

     salt = getSalt(); 

     char[] message = "PasswordToEncrypt".toCharArray(); 
     System.out.println("Message: " + String.valueOf(message)); 
     System.out.println("Encrypted: " + encrypt(message)); 
     System.out.println("Decrypted: " + decrypt(encrypt(message).toCharArray())); 
    } 

    public static String encrypt(char[] plaintext) throws Exception { 
     byte[] saltBytes = salt.getBytes(); 

     SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
     PBEKeySpec spec = new PBEKeySpec(plaintext, saltBytes, iterations, keySize); 
     secretKey = skf.generateSecret(spec); 
     SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getEncoded(), "AES"); 

     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, secretSpec); 
     AlgorithmParameters params = cipher.getParameters(); 
     ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV(); 
     byte[] encryptedTextBytes = cipher.doFinal(String.valueOf(plaintext).getBytes("UTF-8")); 

     return DatatypeConverter.printBase64Binary(encryptedTextBytes); 
    } 

    public static String decrypt(char[] encryptedText) throws Exception { 

     System.out.println(encryptedText); 

     byte[] encryptedTextBytes = DatatypeConverter.parseBase64Binary(new String(encryptedText)); 
     SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getEncoded(), "AES"); 

     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.DECRYPT_MODE, secretSpec, new IvParameterSpec(ivBytes)); 

     byte[] decryptedTextBytes = null; 

     try { 
      decryptedTextBytes = cipher.doFinal(encryptedTextBytes); 
     } catch (IllegalBlockSizeException e) { 
      e.printStackTrace(); 
     } catch (BadPaddingException e) { 
      e.printStackTrace(); 
     } 

     return new String(decryptedTextBytes); 

    } 

    public static String getSalt() throws Exception { 

     SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 
     byte[] salt = new byte[20]; 
     sr.nextBytes(salt); 
     return new String(salt); 
    } 
} 

Der erste Fehler ist dass Sie zwei verschiedene Salze generieren (wenn Sie die Methode encrypt verwenden), also waren die verschlüsselten/entschlüsselten Protokolle unterschiedlich (logisch, aber die Entschlüsselung würde immer noch funktionieren, weil Sie die Entschlüsselung direkt nach der Verschlüsselung aufrufen).

Der zweite Fehler war für den geheimen Schlüssel. Sie müssen beim Verschlüsseln einen geheimen Schlüssel generieren, aber nicht entschlüsseln. Um es einfacher auszudrücken, es ist so, als ob ich mit dem Passwort "encrypt" verschlüsseln würde und dass Sie versuchen, es mit dem Passwort "entschlüsseln" zu entschlüsseln.

Ich würde Ihnen raten, jedes beliebige Zeugs (wie privater Schlüssel, Salz usw. beim Start) zu generieren. Aber hüte dich davor, dass du, wenn du deine App stoppst, nicht in der Lage sein wirst, alte Sachen zu entschlüsseln, wenn du nicht die gleichen zufälligen Sachen bekommst.

Hoffe, dass ich geholfen :)

Grüße,

+0

DatatypeConverter ist jetzt nicht unterstützt? –