Code fails for decrypting without salt or iv in Java

5.1k views Asked by At

I have a ciphertext and a 256-bit key to decrypt it, using AES. There is no salt or iv. I am using Java. I have implemented many of the solutions online, but they all use salts and input vectors. The following builds fine, but fails at runtime: "Salt not found." What salt?

    public class AESFileDecryption {
        public static void main(String[] args) throws Exception {

    String password = "80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01";

    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    KeySpec keySpec = new PBEKeySpec(password.toCharArray());
    SecretKey tmp = factory.generateSecret(keySpec);
    SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

    // file decryption
    Cipher cipher = Cipher.getInstance();
    cipher.init(Cipher.DECRYPT_MODE,secret);
    FileInputStream fis = new FileInputStream("encryptedfile.des");
    FileOutputStream fos = new FileOutputStream("plainfile_decrypted.txt");
    byte[] in = new byte[64];
    int read;
    while ((read = fis.read(in)) != -1) {
        byte[] output = cipher.update(in, 0, read);
        if (output != null)
            fos.write(output);
    }

    byte[] output = cipher.doFinal();
    if (output != null)
        fos.write(output);
    fis.close();
    fos.flush();
    fos.close();
    System.out.println("File Decrypted");
}

}

3

There are 3 answers

1
Jim Flood On BEST ANSWER

You can decrypt the ciphertext in exercise 3.8 by using the simple ECB mode of AES, which does not use an IV. Since you have the key, there is no need for salt (there is no key derivation). Use AES 256 ECB mode in Java, and pass the key as shown. These openssl commands at the command line show that this will work:

You have to convert the hex shown in the book to a string of bytes, for example:

echo '539B333B39706D149028CFE1D9D4A407' | xxd -r -p

You have to use the key as a string of 32 bytes, for example, the openssl command line converts hex to bytes for you with the -K argument:

-K 80000000000000000000000000000000000000000000000000000000000001

And you can convert the resulting binary plaintext back to a hex string for viewing, as in

xxd -p

For example:

echo '539B333B39706D149028CFE1D9D4A407' | xxd -r -p | openssl enc -aes-256-ecb -nopad  -d -K 8000000000000000000000000000000000000000000000000000000000000001 | xxd -p

The result is:

80706050403020100807060504030201

If you let the Java class strip the padding, the result will be 15 bytes of plaintext as:

807060504030201008070605040302

This should be enough for you to jump in with the Java classes and reproduce the same result. I just wanted to show you that this will work with AES 256 ECB, without any IV or salt involved.

2
TheGreatContini On

IVs are normally used with encryption modes such as CBC. I'm assuming Schneier is using ECB here, which doesn't involve an IV. ECB mode is not normally used in the real world because it lacks security. I would advise you to have a look at the WIkipedia modes of operation article. Salts are even more off.

If you agree that this is the problem you are dealing with, then you might want to look here for java code to encrypt in ECB mode.

0
mikebridge On

Both the answers here are correct about using ECB and therefore not requiring an IV (or padding). Here's an updated Java answer for question 3.8:

String hexCipherText = "539b333b39706d149028cfe1d9d4a407";
String hexSecretKey =  "80000000000000000000000000000000" +
                       "00000000000000000000000000000001";

byte[] secretKey = DatatypeConverter.parseHexBinary (hexSecretKey);
byte[] cipherText = DatatypeConverter.parseHexBinary (hexCipherText);

Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey,"AES");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);

byte[] plainText = cipher.doFinal(cipherText);
String hexPlainText = DatatypeConverter.printHexBinary(plainText);

If you get the error java.security.InvalidKeyException: Illegal key size or default parameters and you're using the Oracle JDK then you may also need to download the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files.