2

I have implemented AES encryption in java, but the algorithm is not accepted by team as it is implemented in ECB mode which is not security compliant.I am very new to cryptography and Security requirements.

Can someone please help me changing algorithm to CBC mode. I have attached my code implemented in ECB mode.

public String encrypt(String plainPwd)
{
    byte[] outputBytes = new byte[] {};
    String returnString = "";
    try
    {
        byte[] raw = "XXXXX@XXXXXX.XXX".getBytes("UTF-8");

        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

        outputBytes = cipher.doFinal(plainPwd.getBytes("UTF-8"));
        if (null != outputBytes)
        {
            returnString = Base64Encrypter.getInstance().encode(outputBytes);
        }
        return returnString.trim();

    }
    catch (Exception e)
    {
        System.out.println(e);
    }

    return new String(outputBytes).trim();
}

public String decrypt(String encryptedPwd)
{
    byte[] outputBytes = new byte[] {};
    try
    {
        byte[] raw = "XXXXX@XXXXXX.XXX".getBytes("UTF-8");

        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);

        byte[] inputBytes = Base64Encrypter.getInstance().decode(encryptedPwd);
        if (null != inputBytes)
        {
            outputBytes = cipher.doFinal(inputBytes);
        }
    }
    catch (Exception e)
    {
        System.out.println(e);
    }

    return new String(outputBytes).trim();
}

Early reply will be highly appreciated. Thanks in advance

chandu ram
  • 251
  • 2
  • 5
  • 19
  • ECB mode is insecure, see [ECB mode](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29), scroll down to the Penguin. – zaph Jun 03 '16 at 13:22
  • General advice: **Always use a fully qualified Cipher string.** `Cipher.getInstance("AES");` may result in different ciphers depending on the default security provider. It most likely results in `"AES/ECB/PKCS5Padding"`, but it doesn't have to be. If it changes, you'll lose compatibility between different JVMs. – Artjom B. Jun 03 '16 at 13:34

3 Answers3

1

AES has around 6 different encryption modes. It's important that you use the correct mode for the application that you are using it for. as @eckes says, ECB is fine for small amounts of data where random encrypt/decrypt access is useful. The disadvantage of ECB is that the same input will have the same output, so an attacker could see patterns and may reverse engineer it if there are limited numbers of practical values.

Check out how to choose AES encryption mode for more guidance on picking the correct operation mode.

Community
  • 1
  • 1
micker
  • 878
  • 6
  • 13
  • ECB is not even secure for short data lengths, see comment to @eckes answer. – zaph Jun 03 '16 at 13:23
  • There are many more than 6 modes of operation. There are 3 common non-authenticated modes and maybe 2 common authenticated modes. Of course both categories have their own esoteric or new modes. – Artjom B. Jun 03 '16 at 13:31
  • @ArtjomB. Yes, I'm aware there are many modes of AES. There are 5 standard ones, but there are various levels of support or research for many more. Unfortunately, I don't have time to keep track of all these. That's why I said "around 6" :) – micker Jun 03 '16 at 13:36
1

Change the request string from AES to AES/CBC/PKCS5PADDING and add an iv. While padding is not CBC specific it is good to explicitly define all parameters and with few exceptions padding is needed.

For the iv generate a cryptographically secure random number of block size (16-bytes for AES). In order to have the iv available for decryption common practice is to prepend it to the encrypted data, it does not need to be secret.

zaph
  • 111,848
  • 21
  • 189
  • 228
0

If your data is short and random ECB might be acceptable (at least not worse than CBC). But it is most likely a good idea to not even try to get this right.

Keep in mind, CBC does also not offer integrity protection. Using a extra HMAC or a dedicated mode for wrapping secrets (AESKeywrap) or using an authenticated mode (AES/GCM) is better. (and this is not only a question of avoiding modifications it also closes a class of attacks against the privacy protection of the protocols).

If the data is not random/predictable you need to use a mode which also uses an IV. In case of CBC Java will pick a random IV if not specified.

However for decrypt (especially if you have a padding which does verification) you need to specify the exactly same IV, so dont forget to retrieve and transmit it. So the (unsecure because not authenticated) encryption becomes:

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
byte[] iv = cipher.getIV(); // randomly filled.
...

// on decrypt specify this IV again
cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(iv));

This also has the advantage that it actually specifies the padding to use, so you do not depend on the default selection of Java (always specify the full mode string).

eckes
  • 10,103
  • 1
  • 59
  • 71
  • The problem with ECB, even for one block length or less data is that for the same key the encrypted data is the same. Consider encryption either "yes" to "no", there will just be two encryptions and they can be distinguished just from the encrypted data. With CBC and a random iv every encrypted message would be different. – zaph Jun 03 '16 at 13:10
  • Missing from the answer is the iv required by CBC mode and how to share it. GCM mode is very good but not yet universally available so interoperability s poor. – zaph Jun 03 '16 at 13:10
  • Dear eckes thanks for your reply, I tried by changing the code from Cipher cipher = Cipher.getInstance("AES"); to Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); in both encrypt and decrypt methods. Encryption is successful but while decrypting the encrypted password getting the exception java.security.InvalidKeyException:.. please suggest how to handle. – chandu ram Jun 03 '16 at 13:29
  • Actually if you do not specify a IV java will generate one. However you also need to provide that one to the decryption, otherwise your padding verification will give you the InvalidKeyException. I have expanded my answer a bit. – eckes Jun 03 '16 at 17:39
  • Thanks @zaph I expanded my answer, was too hasty :) – eckes Jun 03 '16 at 17:42
  • @chanduram If the library method returns any indication that the padding is incorrect that must not be returned to the caller, it must be ignored or a padding oracle will be created and the encrypted data will be vulnerable. Since the error `InvalidKeyException` is being returned the only explanation is that it is actually a padding error and must be ignored. `InvalidKeyException` is a misnomer, there is no way to know that from a failed encryption, that is an error in the implementation by the function's implementors. – zaph Jun 03 '16 at 19:47
  • @eckes In answering a question such as this on a forum such as this the assumption is best made that the OP will not know when it is safe to use ECB mode and therefore it is best to just say not to use it. By that I mean not to say never but say no in this context. But the answer is much better. – zaph Jun 03 '16 at 19:52
  • Tinfoil hat time with the disclaimer I am not paranoid: I have friends that do that professionally for me. There are government security agencies that get developers to put flaws in crypto code. Reporting padding errors is an example of something that is useful only in making encryption more vulnerable by getting naive developers to report padding errors back to the caller thus creating padding oracles. – zaph Jun 03 '16 at 20:18
  • @eckes: Thank you very much for your solution it works fine..I have one doubt for decryption of encrypted password i require iv right? so is there any way to store iv in database or in some file?? if i convert byte[] to string and retrieve that back to byte[] it is giving different value. So please suggest how can i store iv for decryption of password during validation. – chandu ram Jun 07 '16 at 05:53
  • Never convert byte[] to String, use base64 or Hex encoding. But if your transport is binary transparent just read and write byte[]. – eckes Jun 09 '16 at 10:40
  • Typically you "just" prepend (or append) the IV to your encrypted file. You do not need to keep it secret so it is best stored with the data. If you know if it is before you just read as many bytes as the blocksize of the ciher is and use them as the IV. (and you most likely also add a hmac tag at the end with the same mechanism). – eckes Jun 09 '16 at 15:10