2013-08-26 2 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"); 
} 

당신은 어디 generateSecretKeypassword를 사용하지 않는 매번 같은 비밀 키를 만드십시오 ...

당신이 그것을 변경하는 경우 :

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와 같은 적절한 키 유도 함수를 사용해야합니다. 또한 ECB보다는 CBC. 마지막으로 UTF-8은 모든 문자열 바이트 배열 변환에 사용됩니다. – ntoskrnl

+0

@ntoskrnl : 나는 그것을 위해 당신의 말을 가지고 갈 것이다 :) (나는 보안에 관해서는 나의 한계를 안다. ..) –

+0

Oh .. 나는 본다. 또 다른 한 가지는 패딩을 사용하는 것입니다. – BRsmover

0

generateSecretKey 메서드가 손상되었습니다. 빈 문자열의 다이제스트를 기반으로 키를 생성합니다. password 인수는 무시됩니다.

기타 문제가 있습니다. ECB 모드가 안전하지 않습니다. 핵심 파생은 여기에서 매우 약합니다. 플랫폼의 기본 문자 인코딩에 따라 좋은 생각이 아닙니다.

관련 문제