AES Encryption is implemented in ECB mode but it is not security compliant. How to implement CBC mode

chandu ram picture chandu ram · Jun 3, 2016 · Viewed 10k times · Source

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 = "[email protected]".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 = "[email protected]".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

Answer

eckes picture eckes · Jun 3, 2016

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).