Lets say that on an Android app the user has to enter a 6-digit PIN on startup. Let's also say that we have some sensitive data in this application that we'd like to encrypt.

The way I would to this is:

  • Using a key derivation function (e.g. PBKDF2) we generate a key from the PIN.
  • Encrypt the sensitive data with AES using the key (and a decent config like CBC+padding).
  • Store encrypted data wherever, e.g. in shared preferences.

The main issue I see here: the original PIN space for a 6-digit PIN is 10^6, which is laughably small to use as the basis of your encryption...

Can we actually fine tune this so the stored data is reasonably secure for a while?

Even if we tune our KDF such that a simple derivation takes 1 second (I don't think we can expect our users to wait much longer during app start), then going through 1'000'000 of them takes merely 11.5 days (assuming same processing power as the phone, which isn't likely...).

Obviously using a longer/stronger PIN would help - but regretfully even just a 6-digit PIN is seen as a hurdle by users, so this isn't likely an option. Also the KDF strength is limited by the amount of time we can expect the users to wait during app start, which I'd say is in the order of magnitude of 1 second.

  • Does the data need to be stored on the device? Storing everything server-side would eliminate the need to do encryption on the client. Can the app be connected to the internet/intranet server? If you need to store the data on the device, but can reach out to the internet, you may be able validate the pin server-side, and return a more robust key from a key store. Commented Apr 20, 2017 at 18:23
  • 1
    The problem is that there is an offline use case which prevents us from doing encryption server side (or getting a key from there, ...). :(
    – fgysin
    Commented Apr 24, 2017 at 7:31
  • Hashing the pin can give you required key size. Can't it?
    – defalt
    Commented Jun 23, 2017 at 16:15
  • @defalt: to get a key of sufficient size one generally uses a key derivation function (KDF) such as PBKDF2. That includes hashing the original PIN. The originating key/PIN space stays the same though.
    – fgysin
    Commented Jun 26, 2017 at 7:00
  • sounds like a bad idea from the get-go, all around. there's no security point and several poor UX points here.
    – dandavis
    Commented Jul 23, 2017 at 19:10

2 Answers 2


My recommended option would be to either store the data, or at least store they key server side.

Since this isn't possible for you, I would bring it back to management that there are conflicting requirements. I would argue that the keyspace is too small for the encryption to provide any real value. I would recommend giving management a real world estimate of 156 guesses per second (from this article https://arstechnica.com/security/2015/08/cracking-all-hacked-ashley-madison-passwords-could-take-a-lifetime/), which would mean that a cracker would have all possible results within two hours. Custom built cracking hardware will be much faster than a mobile device. See here for an example: https://sagitta.pw/hardware/gpu-compute-nodes/brutalis/.

I would inform management that the offline requirement with such a small keyspace would preclude properly securing the data. If they want the data to be secure, they will either need to budge on the 6 digit pin, or they will need to budge on the offline requirement.

  • Also, I would like to call out that the 156 guesses per second was NOT run on the Brutalis system I linked to. The number of guesses on that system would likely be much higher on it. Commented Apr 24, 2017 at 14:47

The PIN code should not be considered a security token. It's only a UI thing, and as such, you can restrict number of unsuccessful attempts to enter it and/or introduce incremental waits between such attempts.

The data itself can (and should) be encrypted with a strong key. This protects the local data from offline cracking (malicious agent trying to read the disk directly). On Android 7.0 and above, you can rely on Direct Boot. Your app can check Storage Encryption Status and behave accordingly.

This does not provide full protection from malicious users who install your app on a rooted device and want to decrypt their data. You are definitely encouraged to check if the device is rooted, but you must know that a determined agent (user or malware) can enable root that your inspection will not detect.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .