Android KeyStore provides a whole list of available ciphers, which leads me to the following question: Which combination would be Best Practice to use in 2019? Every combination seems to have its own set of drawbacks and as someone who is not a security expert, it is realy difficult to decide which one to use.
Some background information: I am working on a Kotlin-based Android app which connects to an API. The user must provide a pair of username:password to authenticate to the API, which will then return a hexadecimal bearer token for future authentication. The connection to the API is already TLS-encrypted, so no need for additional encryption here. The problem is storing the informations securely. The username as well as the password and bearer token have to be stored securely. A common solution to this problem seems to be to encrypt the credentials and store them via the Preferences API. As the encryption only happens inside the app and no key-exchange is needed, symmetric-key encryption looks like the way to go.
TL; DR: Prefer AES/GCM/NoPadding
. Do not ever use AES/ECB/*
.
In your situation, you'll want to prefer authenticated symmetric encryption, and the only option that provides this in the list you link is AES/GCM/NoPadding
.
The benefit for you here is that, not only is your data encrypted, it is also safe from tampering - if someone or something modifies the stored data, you'll get an exception when you attempt to decrypt it. The other listed modes do not have this property. This means that the stored ciphertext could be modified and you wouldn't know - it may or may not still decrypt (I say may or may not as it can throw an exception in other circumstances, like bad padding after modification).
The drawback (and it isn't much of one) is that you must ensure you never use the same key and nonce together. If you do - and an attacker can access or view two different sets of ciphertext - it becomes trivial for them to break and decrypt. The easiest way around this is to simply always generate a random nonce. You'll be able to encrypt 2^96
times before you run into any issues!
If you can't or don't want to use AES/GCM/NoPadding
for whatever reason, select from AES/CTR/NoPadding
or AES/CBC/PKCS7Padding
. Both have their own drawbacks. You'll need to find a way to prevent tampering yourself (HMACs are usually used). I tend to prefer AES/CTR/NoPadding
as it is very similar (at least to use) to AES/GCM/NoPadding
.
Lastly, do not use anything ECB related. ECB BAD.