3

I've files on my computer which are encrypted using this code:

//Arbitrarily selected 8-byte salt sequence:
private static final byte[] salt = {
    (byte) 0x43, (byte) 0x76, (byte) 0x95, (byte) 0xc7,
    (byte) 0x5b, (byte) 0xd7, (byte) 0x45, (byte) 0x17 
};

public static Cipher makeCipher(String pass, Boolean decryptMode) throws GeneralSecurityException{

    //Use a KeyFactory to derive the corresponding key from the passphrase:
    PBEKeySpec keySpec = new PBEKeySpec(pass.toCharArray());
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");//PBKDF2WithHmacSHA256
    SecretKey key = keyFactory.generateSecret(keySpec);

    //Create parameters from the salt and an arbitrary number of iterations:
    PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 42);

    //Set up the cipher:
    Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");

    //Set the cipher mode to decryption or encryption:
    if(decryptMode){
        cipher.init(Cipher.ENCRYPT_MODE, key, pbeParamSpec);
    } else {
        cipher.init(Cipher.DECRYPT_MODE, key, pbeParamSpec);
    }

    return cipher;
}


/**Encrypts one file to a second file using a key derived from a passphrase:**/
public static void encryptFile(String fileName, String pass){
    try{
        byte[] decData;
        byte[] encData;
        File inFile = new File(fileName);
        //Generate the cipher using pass:
        Cipher cipher = Main.makeCipher(pass, true);

        //Read in the file:
        FileInputStream inStream = new FileInputStream(inFile);

        int blockSize = 8;
        //Figure out how many bytes are padded
        int paddedCount = blockSize - ((int)inFile.length()  % blockSize );

        //Figure out full size including padding
        int padded = (int)inFile.length() + paddedCount;

        decData = new byte[padded];


        inStream.read(decData);

        inStream.close();

        //Write out padding bytes as per PKCS5 algorithm
        for( int i = (int)inFile.length(); i < padded; ++i ) {
            decData[i] = (byte)paddedCount;
        }

        //Encrypt the file data:
        encData = cipher.doFinal(decData);

        writeToFile(fileName, encData);

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

private static void writeToFile(String path, byte[] data) {
    try {
        File file = new File(path);

        //Write the encrypted data to a new file:
        FileOutputStream outStream = new FileOutputStream(file);
        outStream.write(data);
        outStream.close();
    } catch(Exception e){
        e.printStackTrace();
    }
}

The key used to encrypt the files is: 'Test', 'test' or 'goon'.

The problem lays around the fact that I'm not able to access the encrypted files. I have an decrypt method which should work:

 /**Decrypts one file to a second file using a key derived from a passphrase:**/
public static void decryptFile(String fileName, String pass, String addition)
                        throws GeneralSecurityException, IOException{
    byte[] encData;
    byte[] decData;
    File inFile = new File(fileName);

    //Generate the cipher using pass:
    Cipher cipher = Main.makeCipher(pass, false);

    //Read in the file:
    FileInputStream inStream = new FileInputStream(inFile);
    encData = new byte[(int)inFile.length()];
    inStream.read(encData);
    inStream.close();

    //Decrypt the file data:
    decData = cipher.doFinal(encData);

    //Write the decrypted data to a new file:
    FileOutputStream target = new FileOutputStream(new File(fileName + addition+ ".png"));
    target.write(decData);
    target.close();
}

But when trying to decrypt the file, the following error is thrown:

Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
at com.sun.crypto.provider.PBES1Core.doFinal(PBES1Core.java:416)
at com.sun.crypto.provider.PBEWithMD5AndDESCipher.engineDoFinal(PBEWithMD5AndDESCipher.java:316)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)
at Main.decryptFile(Main.java:145)
at Main.main(Main.java:22)

Which is this line :

decData = cipher.doFinal(encData);

This is just one of many files. All of my programming projects, websites, work, internship related files are encrypted.

I would really appreciate if someone could help me regaining access to my files. The reason the files got encrypted is because of some wrong permission settings of my user folder which I didn't change back after testing. Which is now fixed.

Is it possible that I did not correctly encrypt the data and therefore cannot decrypt it?

I uploaded an encrypted word document so you can get an insight of what the problem might be. It can be found here:

http://www70.zippyshare.com/v/KfY6qFGD/file.html

This document contains 3 lists of HTML/CSS related checks..

  • To summarise, did you encrypt these files accidentally? If you are trying to decrypt, I would first suggest checking your backups - do you have anything that can help you? If not, then at least you have a passphrase and code to try, so it is likely that all is not lost. However, if you need to persist with decrypting, **take a backup first** - you might do something that makes matters worse, so take precautions. – halfer May 04 '16 at 17:58
  • Hello, yes I ran a project on the wrong folder which caused this problem. Sad enough I've not made backups. I agree, I'm making it right now. Thanks a lot for your response! – Kas Feenema May 04 '16 at 18:04
  • See [this possible duplicate](https://stackoverflow.com/questions/8049872/given-final-block-not-properly-padded) or [a couple of hundred possible dups](https://stackoverflow.com/search?q=Given+final+block+not+properly+padded+Java). – halfer May 04 '16 at 18:08
  • I already went through these questions. They do not help me to get closer to whatever is causing the error to be thrown. Thanks though for pointing out – Kas Feenema May 04 '16 at 18:19
  • It may be worth being more expansive as to how they do not help - most readers will be somewhere between fairly sure and certain that they _will_ help - unfortunately we frequently get questions of the form "I have Googled but did not find anything to solve this" - and the top answer in a popular search engine turns out to be a perfectly suitable answer. – halfer May 04 '16 at 18:22
  • For example, are you padding the file data, or the key, or both? It is fairly clear the problem is related to padding. – halfer May 04 '16 at 18:24
  • I understand. The first question you referred says it probably has to do with the wrong key. While I'm sure it has to be one of the passes I mentioned. Besides I have zero experience with data encryption. Therefore I probably won't recognize a right answer.. This is the reason I posted my question here. To make use of someone's experience to point me what I'm doing wrong. – Kas Feenema May 04 '16 at 18:28
  • In respond to your question. I don't know to be honest. I provided the code that I used. I think the padding is added to the key only? – Kas Feenema May 04 '16 at 18:30
  • OK, I've no idea - just helping improve the question to assist a Java programmer when he/she comes along! (Side note: the question has a good level of detail. However, note that a good approach is to aim for "help me" in your questions rather than "do it for me" - as I say the question isn't bad, but carrying on research now the question is posted is a good next step. You may still find the answer yourself). – halfer May 04 '16 at 18:31
  • I appreciate your help! I totally agree with you. I do not want it to be done for me but with me. I definitely will go on with research as I have to continue with my internship tomorrow. Which require a few, now encrypted, files. – Kas Feenema May 04 '16 at 18:36
  • 1
    Do you have an encrypted text file you know the first characters of? Some XML with header file for example... – vojta May 04 '16 at 18:47
  • @vojta Yes, for example (is from a patch file) : «ƒ|ñVÓ¨¥žkLüÞªRŒÙ6‰ÊŠC‘ëyöß¾Öº©€èAl^§@ÞAÈÂ÷Fë™°÷‚{™)=\}JßbJ„]PØ";#YðjÛ .. What does thiss tell you? – Kas Feenema May 04 '16 at 20:07
  • Another txt file: 迒昏ᶧ汊㾐ি A html file: ’Ãô8õßÅ´PÒªÐÐ a file: {:ìWiÛ˜é*]ú I don't see any similarity :s – Kas Feenema May 04 '16 at 20:19
  • I am quite convinced your key is wrong. That is why I try to crack your encrypted file using brute force. The problem is I can't easily recognize if the decrypted file is the correct file - there are plenty of keys that do not throw an exception on your Checklist.odt. So it would help me if you gave me encrypted text file and some first characters from the correct decrypted text file. – vojta May 04 '16 at 20:36
  • I expect the correct .odt file begins with ODT magic bytes 0x50 0x4B, so I check if the decrypted data starts with them. I have already tried all 3- and 4-letter words both lowercase and uppercase, no success. I am trying mix of lowercase and uppercase right now, but it will take some time. – vojta May 04 '16 at 20:38
  • @vojta Thanks alot for trying to help. That is possible as I am not 100% sure. The password probably contains the text: test, goon or lock. I'm not sure if you can do anything with that information. I cannot access my email atm and therefore can not see the original file. First thing tomorrow I'll upload the file and add the link to a comment. thanks in advance. – Kas Feenema May 05 '16 at 18:56
  • The first line of the checklist.odt is : 'CSS Checklist: - Controleer of alle stijlregels nodig zijn'. Without the quotes – Kas Feenema May 06 '16 at 07:28
  • I found out that if I use the 'crypted' version of the pass, which is saved in a text file, the error is not being thrown. However the data is still encrypted. Unfortunately these password files are encrypted. The crypted version of Test = FJlp-+o_pdtWs%eTTx(notice this is just a string that is modified, so none encrypting algorithm are used) . This will not throw an error. But the data still is encrypted. Hope it helps. – Kas Feenema May 06 '16 at 08:13
  • I have already tried all possible 3- and 4-letter combinations and all 5-letter combinations "xxxxx", "XXXXX" and "Xxxxx". None of them resulted in valid .odt file. As I said, there is a lot of passwords you can use with no exception thrown. The problem is how to recognize the correct decrypted file. Could you please find one file you have both encrypted and decrypted? – vojta May 06 '16 at 08:47
  • @vojta Here is the link to a rar which contains a encrypted and decrypted patch file : http://www105.zippyshare.com/v/vhRmQLol/file.html . Once again, thanks a lot for your help. – Kas Feenema May 06 '16 at 08:53
  • Thanks, I will try the brute force once again. – vojta May 06 '16 at 08:57
  • Are you sure it is the same file? The decrypted one contains 9856 bytes, but the encrypted one 10232 bytes. The size cannot increase that much during the encryption... – vojta May 06 '16 at 09:04
  • Yes I'm absolutely sure. I sent the file as an email attachment just before all this happened. I have my fingers crossed. Do you have Skype or any other place we can talk? – Kas Feenema May 06 '16 at 09:12
  • @vojta I found out that the files are probably encrypted multiple times. I have a lock.txt file which I decrypted 3 times with this pass: FJlp-+o_pdtWs%eTTx . Maybe this explains the increment in file size. I uploaded the lock.txt file and the three decrypted versions here: http://www83.zippyshare.com/v/OcFAWUYn/file.html . To accomplish this I had to manually remove the trailing padding on the text. However this solution is not working for Checklist.odt.. Maybe this gives you more insight? – Kas Feenema May 06 '16 at 10:25
  • @KasFeenema The padding is definitely wrong in this code, I know that - it is once done in the code and once in the doFinal(...). So is it possible you encrypted the patch 23 times? Each encryption adds 16 bytes. – vojta May 06 '16 at 10:27

1 Answers1

2

This exception message means the key is wrong.

Firstly the encrypted data is decrypted using DES.

If the key is wrong, the resulting data will be random. There is a probability 1/256 it will end with 0x01, which is a correct PKCS padding, a probability 1/(256 * 256) it will end with 0x02 0x02, which is also a correct padding, probability 1/(256 * 256 * 256) it will end with 0x03 0x03 0x03, which is also a correct padding, etc. No exception is thrown in these highly improbable cases, but the decrypted data is incorrect, of course.


There is one important bug in the OP's code above: the encryptFile method performs input padding, although it does not have to: doFinal(...) adds padding as well. That's why padding is added twice and one padding remains in the resulting data after decryption.

vojta
  • 5,591
  • 2
  • 24
  • 64