0

I get "error while finalizing cipher" whenever I want to decrypt a file I encrypted before.

For testing purposes, I've just copypasted Pero's code from here.

All I've changed is removed the salt and replaced it with my md5 function. Before that I've tried it with the salt and it gave me the same error :(

In that other question, the problem seems to be solved somehow, but he didn't further elaborate on that, it was just something with the salt that I didn't even use.

public static void encrypt(String path, String password) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
    FileInputStream fis = new FileInputStream(path);
    FileOutputStream fos = new FileOutputStream(path.concat(".scrypt"));
    byte[] key = md5(password).getBytes("UTF-8");
    MessageDigest sha = MessageDigest.getInstance("SHA-1");
    key = sha.digest(key);
    key = Arrays.copyOf(key,16);
    SecretKeySpec sks = new SecretKeySpec(key, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, sks);
    CipherOutputStream cos = new CipherOutputStream(fos, cipher);
    int b;
    byte[] d = new byte[8];
    while((b = fis.read(d)) != -1) {
        cos.write(d, 0, b);
    }
    cos.flush();
    cos.close();
    fis.close();
}

public static void decrypt(String path, String password) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
    FileInputStream fis = new FileInputStream(path);
    FileOutputStream fos = new FileOutputStream(path.replace(".scrypt", ""));
    byte[] key = md5(password).getBytes("UTF-8");
    MessageDigest sha = MessageDigest.getInstance("SHA-1");
    key = sha.digest(key);
    key = Arrays.copyOf(key,16);
    SecretKeySpec sks = new SecretKeySpec(key, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, sks);
    CipherInputStream cis = new CipherInputStream(fis, cipher);
    int b;
    byte[] d = new byte[8];
    while((b = cis.read(d)) != -1) {
        fos.write(d, 0, b);
    }
    fos.flush();
    fos.close();
    cis.close();
}

md5() is equivalent to php's md5()

Would be awesome if someone could help me, I searched for a solution for hours :(

Community
  • 1
  • 1
CiriousJoker
  • 552
  • 1
  • 7
  • 18

1 Answers1

1

The difference is this in encrypt:

byte[] key = md5(password).getBytes("UTF-8");

and decrypt:

byte[] key = (salt + password).getBytes("UTF-8");

Needless to say, this leads to different keys which makes proper decryption impossible.


This type of key derivation from a password is not remotely secure. Passwords have low entropy, but keys have high entropy. If you want to convert a password to a key then you need to utilize a computationally intensive operation so that attackers can't just try all easy passwords. This can be done with PBKDF2, bcrypt, scrypt or Argon2. Use a many iterations or a high cost factor, and always use a randomly generated salt. The salt doesn't have to be secret, but it must be send to the receiver along with the ciphertext. You can write it in front of the ciphertext and read it back during decryption.

Always use a fully qualified cipher string, because different JVM's may have different defaults. This would make interoperability a nightmare. Your current string probably defaults to Cipher.getInstance("AES/ECB/PKCS5Padding");

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.


Have a look at RNCryptor (Java, PHP), which has everything for secure encryption and interoperability.

Community
  • 1
  • 1
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • First of all, thanks for all the insight on how to encrypt, secondly thanks for mentioning RNCryptor. I've tried it and it least it works. However the performance is horrible. Just encrypting "Hello World!" and decrypting it takes 10 seconds total. Do you have any idea why this takes so long? Each command takes 5 seconds to load no matter what i encrypt ... – CiriousJoker Feb 01 '16 at 14:33
  • No, I have no idea why it's so slow. – Artjom B. Feb 01 '16 at 18:57
  • Nvm i switched to a new solution and i'm close to getting it to work. Could you take a look at the code once i'm finished and point out any mistakes i made? I'm pretty new to the game and it would benefit me a lot! – CiriousJoker Feb 01 '16 at 18:59
  • If you have working code, but you don't know if it is any good (security/performance/readability), [so] is not the right place to ask such a question. [codereview.se] is much better suited for this type of question. If you could make it work, then you can ask a new question here. – Artjom B. Feb 01 '16 at 19:06
  • One last thing: Can i post my finished code that solved my problem as an answer after it's reviewed by the dudes & dudettes over at Code Review? It might help one or another. Is stackoverflow the right place for that? – CiriousJoker Feb 01 '16 at 20:37
  • 1
    I see nothing wrong with it as long as it actually answers your question. Don't forget to link back to the specific Q&A on [codereview.se] to give proper attribution. – Artjom B. Feb 01 '16 at 20:49