2013-08-26 69 views
0

我爲AES加密和解密編寫了一個小測試用例。計劃是從文件中讀取一些文本,使用密鑰對其進行加密並再次解密。現在的問題是,文本總是相同的,錯誤的密碼不會導致無法讀取的文本。Java AES加密/解密總是返回相同的內容

代碼中的問題在哪裏?或者我犯了一個根本錯誤?

Main.java

import javax.crypto.spec.SecretKeySpec; 

public class Main { 
    public static void main(String[] args) throws Exception { 
     new Main(); 
    } 

    public Main() throws Exception { 
     Reader reader = new Reader(); 
     String text = reader.readFile("/home/benjamin/Test.txt"); 
     System.out.println("Original text before encryption: " + text); 

     // User A verschlüsselt und speichert ab 
     Crypto crypto = new Crypto(); 
     SecretKeySpec secretkey = crypto.generateSecretKey("123456aA"); 
     byte[] encryptedtext = crypto.encrypt(text, secretkey); 

     // User B lädt Datei und kennt das Passwort 
     Crypto crypto2 = new Crypto(); 
     SecretKeySpec secretkey2 = crypto2.generateSecretKey("1kkk23456aAjbhhjbhjb"); 
     byte[] decryptedtext = crypto2.decrypt(encryptedtext, secretkey2); 
     System.out.println("Original text after encryption: " + new String(decryptedtext, "UTF-8")); 
    } 
} 

Crypto.java

import java.security.MessageDigest; 
import java.util.Arrays; 

import javax.crypto.Cipher; 
import javax.crypto.spec.SecretKeySpec; 


public class Crypto { 
    public SecretKeySpec generateSecretKey(String password) throws Exception { 
     MessageDigest shahash = MessageDigest.getInstance("SHA-1"); 
     byte[] key = shahash.digest(); 
     key = Arrays.copyOf(key, 16); 
     return new SecretKeySpec(key, "AES"); 
    } 

    public byte[] encrypt(String text, SecretKeySpec secretkey) throws Exception { 
     Cipher cipher = Cipher.getInstance("AES"); 
     cipher.init(Cipher.ENCRYPT_MODE, secretkey); 
     return cipher.doFinal(text.getBytes()); 
    } 

    public byte[] decrypt(byte[] encryptedtext, SecretKeySpec secretkey) throws Exception { 
     Cipher cipher = Cipher.getInstance("AES"); 
     cipher.init(Cipher.DECRYPT_MODE, secretkey); 
     return cipher.doFinal(encryptedtext); 
    } 
} 

回答

3

這就是問題所在:

public SecretKeySpec generateSecretKey(String password) throws Exception { 
    MessageDigest shahash = MessageDigest.getInstance("SHA-1"); 
    byte[] key = shahash.digest(); 
    key = Arrays.copyOf(key, 16); 
    return new SecretKeySpec(key, "AES"); 
} 

您沒有在generateSecretKey任何地方使用password,所以它會每次創建相同的密鑰...

如果將其更改爲:

public SecretKeySpec generateSecretKey(String password) throws Exception { 
    MessageDigest shahash = MessageDigest.getInstance("SHA-1"); 
    byte[] key = shahash.digest(password.getBytes("UTF-8")); 
    key = Arrays.copyOf(key, 16); 
    return new SecretKeySpec(key, "AES"); 
} 

則如預期給出了錯誤的密碼時,它會失敗。這並不一定意味着它是創建密鑰的最佳方式,或者其他任何加密代碼都是合適的,但我沒有足夠的經驗對此進行評論。

+3

應該使用適當的密鑰派生函數,例如PBKDF2,bcrypt或scrypt。另外,CBC而不是ECB。最後,UTF-8用於所有字符串字節數組轉換。 – ntoskrnl

+0

@ntoskrnl:我會說你的話:)(我知道我的限制,當涉及到安全...) –

+0

哦..我明白了。另一件事是使用填充,謝謝 – BRsmover

0

generateSecretKey方法壞了。它根據空字符串的摘要生成密鑰--參數將被忽略。

還有其他問題。 ECB模式不安全。這裏的關鍵推導非常薄弱。根據平臺的默認字符編碼不是一個好主意。