h3. What At the moment, after a successfully login, the token values are persisted on device using the private shared preferences.
However, it is still possible to access the data and tamper with it. We should try to improve the security of it
h3. How h4. Suggestions:
*Pre Android M (API < 23)* The Android KeyStore only supports RSA key generation. RSA is not suitable for encrypting large amounts of data (like the data we're storing in shared preferences). The other option is to use an AES key but the Android KeyStore does not support symmetric key generation pre Android M. So we must ensure that our AES key is secure. We can secure it by encrypting it with RSA keys that are stored in the Android KeyStore.
Generate RSA key pairs using `KeyPairGenerator` and `KeyPairGeneratorSpec`. These will be stored in the Android KeyStore and can only be accessed by the app that created those keys.
To generate an AES Key you can use `SecureRandom` and `SecretKeySpec`. Before generating the AES key you should encrypt the `SecureRandom` bytes with the RSA public key previously generated in the KeyStore. Then the encrypted AES key can be stored in Shared Preferences.
*Post Android M (API > 23)* The Android Keystore supports AES key generation post Android M so its more straightforward. You can use the `KeyGenerator ` and `KeyGenParameterSpec` APIs for this. The same key is used for encryption and decryption and can handle large amounts of data so this key is enough.
*Issues with Android KeyStore* The Android KeyStore can get wiped if a user changes or removes their screen lock on their device e.g. changing from PIN to fingerprint. So if the data in the Shared Preferences cannot be decrypted all of sudden this leaves our app in an unstable state so we need a way to recover from this. For more info on this issue see [The Forgetful KeyStore|https://doridori.github.io/android-security-the-forgetful-keystore/]
This The [ library Secured-Preference-Store |https://github.com/iamMehedi/Secured-Preference-Store] library works but not for Android O unfortunately. I think the problem in Android O is the initialisation vector byte array size for the AES key is wrong (see [here|https://github.com/iamMehedi/Secured-Preference-Store/blob/master/securedpreferencestore/src/main/java/devliving/online/securedpreferencestore/EncryptionManager.java#L373]). And so when trying to encrypt the bytes with the cipher an `IllegalBlockSizeException` exception is thrown [here|https://github.com/iamMehedi/Secured-Preference-Store/blob/master/securedpreferencestore/src/main/java/devliving/online/securedpreferencestore/EncryptionManager.java#L401].
We could commit to the Secured-Preference-Store library upstream but it may take some time for it be merged and released. The other option is to implement our own framework to secure the Shared Preferences file. |
|