how (not) to choose a secure PIN code

introduction

There are 104 = 10,000 possible four-digit PIN codes (0000, 0001, …, 9998, 9999) because there are ten digits to choose from (09), they are independent of each other (0 may be followed by another 0 as well as 19) and their order matters (1234 is not equivalent to 4321). Some of the codes seem pretty easy to guess, though. Let us make a list of strong four-digit PIN codes by considering various factors.

Note: of course, the more rules we impose on our PIN codes, the fewer possible codes remain and the more likely an attacker is to guess the code if they know our rules!

rule 1: no duplicate digits

Discard codes with duplicate digits, e.g. 0000 and 0120.

The digits are now interdependent: the first digit may still be chosen freely but the second one must be picked from the unused digits, etc. Thus, the number of codes left is

10 × (10 − 1) × (10 − 2) × (10 − 3)
= 10 × 9 × 8 × 7
= 5 040.

The remaining codes lie between 0123 and 9876, inclusive.

rule 2: no consecutive digits

Ignoring the order of digits, discard codes in which any two digits are consecutive (9 and 0 are considered consecutive as well as 0 and 1). For example, discard 0123 and 9603.

To find out how many codes we have left, we first list all combinations of four digits that we still accept, ignoring the order of digits (see appendix for a program). There are only 25 such combinations:

0246, 0247, 0248, 0257, 0258, 0268, 0357, 0358, 0368, 0468, 1357, 1358, 1359, 1368, 1369, 1379, 1468, 1469, 1479, 1579, 2468, 2469, 2479, 2579, 3579.

Because each combination has four unique digits, it has 4! permutations and the number of remaining PIN codes is

25 × 4!
= 25 × 4 × 3 × 2 × 1
= 600.

They lie between 0246 and 9753, inclusive.

rule 3: both even and odd digits

Discard codes with no odd digits and codes with no even digits, e.g. 0246 and 1357.

Ignoring the order of digits, 15 combinations remain:

0247, 0257, 0258, 0357, 0358, 0368, 1358, 1368, 1369, 1468, 1469, 1479, 2469, 2479, 2579.

Each combination still has 4! permutations, so the number of remaining PIN codes is

15 × 4!
= 15 × 4 × 3 × 2 × 1
= 360.

They lie between 0247 and 9752, inclusive.

rule 4: no more than two digits on the same keypad row, column or diagonal

Let us look at a common keypad layout (it does not matter if rows 123 and 789 trade places):

1 2 3
4 5 6
7 8 9
  0

Rule 2 already took care of keeping rows 123, 456 and 789 non-full, so discard codes with more than two digits on columns 147, 2580 or 369 or on diagonals 159 or 357. For example, discard 1947 and 7035.

Of the 15 combinations listed in the previous chapter, we keep nine:

0247, 0368, 1358, 1368, 1468, 1469, 2469, 2479, 2579.

Each combination still has 4! permutations, so the number of remaining PIN codes is

9 × 4!
= 9 × 4 × 3 × 2 × 1
= 216.

They lie between 0247 and 9752, inclusive.

rule 5: no ascending or descending order

Discard codes with all digits in ascending or descending order (0 is considered both the smallest and the largest digit). For example, discard 1358, 2470, 9752 and 0742.

Of the nine combinations listed in the previous chapter, those containing 0 have four less permutations and the rest have two less permutations. Thus, the number of PIN codes remaining is

2 × (4! − 4) + (9 − 2) × (4! − 2)
= 2 × (4 × 3 × 2 × 1 − 4) + 7 × (4 × 3 × 2 × 1 − 2)
= 2 × (24 − 4) + 7 × (24 − 2)
= 2 × 20 + 7 × 22
= 40 + 154
= 194.

The remaining codes lie between 0274 and 9725, inclusive (see appendix for a program).

rule 6: no dates

Discard 14 codes that are valid dates (e.g. birthdays):

Number of PIN codes remaining:

194 − 14
= 180.

That is, less than two percent of all possible four-digit PIN codes. The complete list:

0638, 0836, 1385, 1386, 1486, 1496, 1538, 1583, 1638, 1648, 1649, 1683, 1684, 1694, 1835, 1836, 1846, 1853, 1863, 1864, 2047, 2074, 2496, 2497, 2597, 2649, 2694, 2740, 2749, 2759, 2794, 2795, 2946, 2947, 2957, 2964, 2974, 2975, 3068, 3086, 3158, 3168, 3185, 3186, 3518, 3581, 3608, 3618, 3681, 3806, 3815, 3816, 3851, 3860, 3861, 4027, 4072, 4168, 4169, 4186, 4196, 4207, 4269, 4270, 4279, 4296, 4297, 4618, 4619, 4629, 4681, 4691, 4692, 4702, 4720, 4729, 4792, 4816, 4861, 4916, 4926, 4927, 4961, 4962, 4972, 5138, 5183, 5279, 5297, 5318, 5381, 5729, 5792, 5813, 5831, 5927, 5972, 6038, 6083, 6138, 6148, 6149, 6183, 6184, 6194, 6249, 6294, 6308, 6318, 6380, 6381, 6418, 6419, 6429, 6481, 6491, 6492, 6803, 6813, 6814, 6830, 6831, 6841, 6914, 6924, 6941, 6942, 7024, 7042, 7240, 7249, 7259, 7294, 7295, 7429, 7492, 7529, 7592, 7924, 7925, 7942, 7952, 8036, 8063, 8135, 8136, 8146, 8153, 8163, 8164, 8315, 8316, 8351, 8360, 8361, 8416, 8461, 8513, 8613, 8614, 9146, 9164, 9246, 9247, 9257, 9264, 9274, 9275, 9416, 9426, 9427, 9461, 9462, 9472, 9527, 9572, 9614, 9624, 9724, 9725

appendices

rule 2

A Python program that prints combinations of four digits without two consecutive digits:

for a in range(10):
    for b in range(a + 2, 10):
        for c in range(b + 2, 10):
            for d in range(c + 2, min(a + 9, 10)):
                print(a, b, c, d)

rule 5

A Python program that prints non-ascending and non-descending permutations of specified combinations:

import itertools
def is_in_order(sequence):
    differences = [
        sequence[pos] - sequence[pos-1] for pos in range(1, len(sequence))
    ]
    return (
        min(differences) > 0
        or (sequence[-1] == 0 and min(differences[:-1]) > 0)
        or max(differences) < 0
        or (sequence[0] == 0 and max(differences[1:]) < 0)
    )
combinations = [
    "0247", "0368", "1358", "1368", "1468", "1469", "2469", "2479", "2579"
]
permutations = set()
for combination in combinations:
    permutations.update(
        "".join(permutation) for permutation
        in itertools.permutations(combination)
        if not is_in_order([int(symbol) for symbol in permutation])
    )
print(", ".join(sorted(permutations)))