0

I'm trying to do an exercise to encrypt a file.txt with a DES algorithm. I must save the generated key in a file without extension. I think this part is well solved. But I have troubles to decrypting the encrypted file using the same key. I'm getting the error: "Given final block not properly padded".

Exercise: 1. Encryption Program: Read a text file, encrypts it using the DES algorithm and the result is written to a new file, another file stored in the key used for encryption. 2. decryption program: read the program saved by the encryption key, decrypts the text stored by the encryption program and displays it on the screen.

NOTES: uses FileInputStream and FileOutputStream, performs encryption in blocks of 8 bytes and performs decryption in blocks of 16 bytes.

ENCRYPTING

import java.io.*;
import javax.crypto.*;
import javax.crypto.spec.*;

public class Encrypt {

    public static void main(String[] args) {

        try {
            SecretKey key = KeyGenerator.getInstance("DES").generateKey();

            FileOutputStream fosKey = new FileOutputStream("..\\KEY");
            SecretKeyFactory keyfac = SecretKeyFactory.getInstance("DES");
            DESKeySpec keyspec = (DESKeySpec) keyfac.getKeySpec(key, DESKeySpec.class);
            fosKey.write(keyspec.getKey());
            fosKey.close();

            Cipher crypt = Cipher.getInstance("DES");
            crypt.init(Cipher.ENCRYPT_MODE, key);

            FileInputStream fis = new FileInputStream("..\\File.txt");
            FileOutputStream fos = new FileOutputStream("..\\FileCrypted.txt");
            byte[] arrayBytes = new byte[8];
            int bytesReads;
            while ((bytesReads = fis.read(arrayBytes)) != -1) {
                fos.write(crypt.doFinal(arrayBytes), 0, bytesReads);
            }
            fis.close();
            fos.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

DECRYPTING

import java.io.*;
import javax.crypto.*;
import javax.crypto.spec.*;

public class Decrypt {

    public static void main(String[] args) {

        try {
            FileInputStream fisKey = new FileInputStream("..\\KEY");
            byte[] arrayKey = new byte[fisKey.available()];
            fisKey.read(arrayKey);
            SecretKey key = new SecretKeySpec(arrayKey, "DES");

            Cipher decrypt = Cipher.getInstance("DES");
            decrypt.init(Cipher.DECRYPT_MODE, key);

            FileInputStream fis = new FileInputStream("..\\FileCrypted.txt");
            byte[] encText = new byte[16];
            int bytesReads;
            while ((bytesReads = fis.read(encText)) != -1) {
                fis.read(decrypt.doFinal(encText), 0, bytesReads);
            }
            fis.close();
            System.out.println(new String(encText));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
2
  • Always use a fully qualified Cipher string, because Cipher.getInstance("DES"); may have different defaults based on the security provider, which might break compatibility across multiple JVM's. It most likely defaults to Cipher.getInstance("DES/ECB/PKCS5Padding"); Commented Feb 3, 2016 at 18:54
  • Never use ECB mode. It's deterministic and therefore not semantically secure. You should at the very least use a randomized mode like CBC or CTR. It is better to authenticate your ciphertexts so that attacks like a padding oracle attack are not possible. This can be done with authenticated modes like GCM or EAX, or with an encrypt-then-MAC scheme. Commented Feb 3, 2016 at 18:55

1 Answer 1

2

You should use the update() method for the intermediate encrypt calls, and only use doFinal() on the last call. This goes for both encrypt and decrypt.

DES - in ECB or CBC mode -always uses block size of 8 bytes (both encrypt and decrypt). If padding is active, additional data (1-8 bytes) will be appended to ensure a block size of 8 when you do the doFinal(). If padding is not active on the cipher, you need to ensure data have been provided as a multiple of 8 bytes when you do the doFinal().

The update() allows you to handle data to the encryption without aligning to the 8 byte block size, as it is just buffered up until it have data for a full block. The doFinal() flushes any excessive bytes that might be in the buffer for encryption and applies any padding that may be in effect.


Please notice that DES is not considered secure anymore, so it should not be used for any serious security.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.