Search code examples
androidencryptionaes

What is the correct way to use Cipher.getInstance("AES")?


Cipher.getInstance("AES")

Android Studio's Lint complains about the above code as follows:

cipher.getinstance should not be called without setting the encryption mode and padding

The above code works perfectly as explained by an SO answer.

Could anyone shed some light on how to use cipher.getinstance() correctly?


Solution

  • When instantiating a Cipher instance, algorithm, mode, and padding should always be explicitly specified, e.g.:

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    

    If only the algorithm is specified, provider-specific values for mode and padding are applied, see Cipher in the Android or Java documentation. This has a number of error-prone disadvantages and should therefore strictly be avoided:

    • Many providers use ECB mode and PKCS#5 padding as default values, e.g. the BouncyCastle provider on Android (tested for API level 28 und 29). However, ECB mode is insecure and should therefore not be applied, see Why shouldn't I use ECB encryption?. To prevent the use of ECB mode, the mode needs to be explicitly specified.
    • Cross-platform problems can occur if different providers with different default values for mode and padding are involved.
    • Explicit specification of mode and padding improves readability.

    The Lint tool points out these problems with its warning Cipher.getInstance should not be called without setting the encryption mode and padding. By the way, the Lint report also warns about the insecurity of ECB when it is specified with AES/ECB/PKCS5Padding: ECB encryption mode should not be used.

    In contrast, CBC, when specified with AES/CBC/PKCS5Padding, does not trigger a warning in Lint.


    Although CBC is more secure than ECB, CBC only supports confidentiality. Therefore, authenticated encryption, which provides authenticity and integrity in addition to confidentiality, should be preferred, e.g. GCM. Since GCM is based on CTR, i.e. a stream cipher mode, no padding is required, unlike block cipher modes such as ECB or CBC (see Block cipher mode of operation). Thus, GCM is specified with AES/GCM/NoPadding.

    Here you can find a post regarding the difference between CBC and ECB: Should I use ECB or CBC encryption mode for my block cipher? and here regarding the difference between CBC and GCM: What is the difference between CBC and GCM mode?.

    Finally, a little note about PKCS#5 padding: what is called PKCS#5 padding in the Java/Android world for historical reasons is actually PKCS#7 padding. Here you can find more details about this topic: What is the difference between PKCS#5 padding and PKCS#7 padding?.