BRsmover
BRsmover

Reputation: 887

Java AES encryption/decryption always return the same content

I wrote a little test case for an AES encryption and decryption. The plan is to read some text from a file, encrypt it with a key and decrypt it again. Now the problem is, that the text is always the same, a wrong password does not result in unreadable text.

Where is the problem in the code or did I make a fundamental mistake ?

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

Upvotes: 0

Views: 3590

Answers (2)

ntoskrnl
ntoskrnl

Reputation: 5744

The generateSecretKey method is broken. It generates the key based on the digest of the empty string – the password argument is ignored.

There are also other issues. ECB mode is not secure. Key derivation is very weak here. Depending on the platform default character encoding is not a good idea.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1499840

This is the problem:

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

You don't use password anywhere within generateSecretKey, so it'll create the same secret key every time...

If you change it to:

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

then it will fail as expected when given the wrong password. That doesn't necessarily mean it's the best way of creating a secret key, or that any of the rest of the crypto code is appropriate, but I don't have enough experience to comment on that.

Upvotes: 3

Related Questions