I'm familiar with password hashing, using salts, bcrypt etc.

But it doesn't seem like this would work to store a 4 digit pin code since the attacker could try all 10,000 combinations quite quickly. Is there something I'm missing or how is this commonly done?

  • 7
    How is the PIN entered: is this an ATM (Automated Teller Machine), a door lock, or something else? How is the PIN verified? What is the transmission channel between the user input and the verification mechanism?
    – this.josh
    Commented Aug 31, 2011 at 16:35
  • The PIN is entered over HTTPS in a webpage. (think online banking) Commented Jan 20, 2012 at 19:46

4 Answers 4


If you are worried about a "leaked database" scenario (rather than the online cracking vector, which can be mitigated by per-user, per-IP, per-site rate-limiting and lockout) then you are right that hashing is not enough.

Even using the most complex sequence of hashes & salting e.g. bcrypt(pbkdf2(sha256(pin),salt1),salt2) you are still going to be vulnerable to anyone who can see (e.g. from a source code/docs leak) what algorithms are used and who can find your salts (normally stored in the same DB/table) -- they can just run the same series of hashes, and even if it takes a minute for each that's only 7 days to try them all. So you would basically be relying on security-by-obscurity.

In this case it would be worth encrypting the password hashes with a secret key (which can be kept separately from the source code, only accessible to trusted "production security operations" users, never re-used in pre-prod environments, changed regularly, etc.). That secret key will need to be present on the server which validates/updates PIN codes, but it can be kept separately from the user/pin database (e.g. in an encrypted config file), which means that Little Bobby Tables won't automatically get access to it when he snarfs the whole of T_USERS via SQL injection, or when someone grabs a DVD with a DB backup on it from your sysadmin's desk.

[Normally encrypting the hashes is not recommended, because its better to use a secure hash, good salt and strong password/phrases, and encrypting the hashes can give a false sense of security. But if you can't have strong passwords then there aren't many other options -- beggars can't be choosers...]

You could combine the PIN with a password -- but in that case why bother with the PIN at all? Just require a strong alphanumeric password. (If the PIN is used in combination with a smartcard or token or similar, of course, then it can add to the overall security.)

We could use a bigger (6/8 digit) PIN. Its not feasible to make a digit-only PIN be secure from brute force: at 1B hashes per second, we'd need 16 or more digits to push the brute force time beyond a year. But adding a few more digits might be enough to make the online attack easier to detect and block -- with only 10K combinations its going to be hard to set "slow-force" thresholds low enough to make an attack infeasible. Unfortunately, you have likely have physical constraints (hardware selection) which preclude longer PINs.

  • 2
    Thanks this best answers it I think, since I was mainly wondering about the scenario where the database is compromised. I think keeping a secret key separate from the main database, using this to salt the pin hash, and only sharing it with key employees makes the most sense. This way getting access to the db wouldn't be sufficient, they'd need to hack the server also. Thanks! Commented Sep 3, 2011 at 20:14
  • Don't forget that with banking I have encountered, often a user is only allowed 2 incorrect attempts, after the 3rd they have to re-enable login.
    – kristianp
    Commented Jun 3, 2019 at 6:09

Password hashing schemes such as bcrypt are meant to give some security in the following context: the attacker can read whatever information you store to verify the password (e.g. he gets a dump of the database through a SQL injection attack). With a 4-digit PIN, entropy is too low to provide much resistance in this situation, even with huge salts and iteration counts of biblical magnitude. Therefore, if you use a 4-digit PIN, then you already assume that the attacker cannot access the password verification information, in which case you can simply store PINs "as is".

Even if the attacker must go through the normal authentication process for each guess (that's an online dictionary attack: for each guess, the attacker must interact with either the user or the server, or both), 10000 possible PINs are a very low figure. So proper security can be achieved only by enforcing arbitrary delays -- the extreme case being what smartcards usually do, i.e. lock themselves out after three wrong PINs (a locked smartcard is like an infinite delay). This is delicate with networked services, because you do not want people to be able to lock at will other people's accounts.

  • 2
    Your analysis in para 1 seems to assume that an attacker who "gets a dump the database" has access to everything on the server which is used to verify the PIN. SQL injection and priv-escalation vulns are quite distinct (and its probably rare for SQL injection to be bad enough to provide a platform for OS-level priv escalation), which makes this untrue in general, I think.
    – Misha
    Commented Aug 31, 2011 at 11:32

The two common things that limit this type of attack are:

  • for sensitive applications the PIN is in often addition to a password
  • brute forcing is disallowed, usually by a lockout after 3 or 5 tries. Sometimes the input device also enforces slow entry of the PIN in addition to lockout, as a further defense.
  • 4
    Slow entry is usually combined with the lockout - I should have written that explicitly.
    – Rory Alsop
    Commented Aug 31, 2011 at 7:30
  • 2
    Also, if you are able to enumerate enough users (say 10.000), you can try one static random pin for all users, and you most probably would find an account. And, since you only tried once per user, no lockout would happen! Also see: security.stackexchange.com/questions/6694/… Commented Aug 31, 2011 at 7:32
  • 2
    Hence the 1st common thing - it is often used in addition to a password:-)
    – Rory Alsop
    Commented Aug 31, 2011 at 7:36
  • 4
    @Dog eat cat world: "since you only tried once per user, no lockout" - I disagree. The system should detect that someone has made a lot of attempts from a given location (e.g. from one PIN pad/terminal/network address/what-have-you) and react accordingly (lockout the location, trigger a warning to system operators, etc.). As you've shown, only associating lockouts with users is a security vulnerability. Commented Aug 31, 2011 at 9:35
  • 2
    @Dog eat cat world: actually fewer than 10k users: it's like the birthday problem only you care whether someone has the same PIN as you chose, not the same PIN as anyone else. I think you'd hit 50% chance of success after <7k users.
    – user185
    Commented Aug 31, 2011 at 13:14

You don't say what your application is, but you could consider having a dedicated back-end server used to verify pins.

You can then restrict access to that server more than you can for the front-end web server. You can implement restrictions such as rate-limiting on the pin-checking server so that even if the front-end server gets taken over by an attacker they will have trouble brute-forcing pins.

You must log in to answer this question.

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