Android: How safe is PBKDF2 with a 4 digit pin?


Our Product Manager wants a 4 digit pin for login in our app, obviously for UX reasons, so user don’t have to remember their password each time when they login.

A refresh token can be retrieved from backend to obtain a session token, which have access to the API. On our app, we encrypt the refresh token with AES and PBKDF2. A random salt and IV are generated plus the 4 digit used as password for PBKDF2.

After the encryption, I store the salt, IV and the cipher text base64 encoded in private shared preference.

The encryption code looks like this:

const val CPR_TRANSFORMATION = "AES/CBC/PKCS7Padding" const val ALGORITHM_TYPE = "PBKDF2WithHmacSHA1" const val ITERATION_AMOUNT = 12000 const val KEY_SIZE = 256  private fun encrypt(passCode: String, data: ByteArray): Encrypted { //e.g.: passCode = "0000"     val salt = ByteArray(256)     SecureRandom().nextBytes(salt)      val iv = ByteArray(16)     SecureRandom().nextBytes(iv)      val cipher = Cipher.getInstance(CPR_TRANSFORMATION)     cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(passCode, salt), IvParameterSpec(iv))     val raw = cipher.doFinal(data)     return Encrypted(salt.encodeBase64(), iv.encodeBase64(), raw.encodeBase64()) }  private fun getSecretKey(passCode: String, salt: ByteArray): Key {     val pbKeySpec = PBEKeySpec(passCode.toCharArray(), salt, ITERATION_AMOUNT, KEY_SIZE)     val keyBytes = SecretKeyFactory.getInstance(ALGORITHM_TYPE).generateSecret(pbKeySpec).encoded     return SecretKeySpec(keyBytes, KeyProperties.KEY_ALGORITHM_AES) } 

Now my question is: How secure is this implementation?

  • How could an attacker retrieve the refresh token from shared preference and decrypt it?
  • Is the symmetric key inside secure element?
  • How safe is this implementation against malware or root?
  • How easy can the key be brute forced? (except that user tries 10k times manually to insert the correct pin)