1. iPhone的四位数密码
  2. Android的图案密码
  3. 总结

个人认为,在只考虑按顺序暴力解密的情况下,设置至少6个点的Android图案密码要比iPhone四位数密码安全。

iPhone的四位数密码

iPhone的密码是一个从0000到9999的四位数(带前置0)。

显然有\(10^4=10000\)种密码。

Android的图案密码

Android的图案密码是\(3 \times 3\)均匀分布点阵中的一条路径,要求每个点最多只能经过一次,路径中任意两点间的点必须经过,且路径至少经过4个点,至多9个点。

设9个点分别用1到9来表示,路径可表示为长度为49,数字为19的排列,且要求2出现在(1, 3), (3, 1)之前,4出现在(1, 7), (7, 1)之前,6出现在(3, 9), (9, 3)之前,8出现在(7, 9), (9, 7)之前,5出现在(1, 9), (9, 1), (2, 8), (8, 2), (3, 7), (7, 3), (4, 6), (6, 4)之前。(其中(x, y)表示排列中的子串)

我们可以用代码来枚举所有的排列,并筛选出不符合要求的排列。

如以下的python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from itertools import *
illegal = [('2', '13'), ('2', '31'), ('4', '17'), ('4', '71'),
('6', '39'), ('6', '93'), ('8', '79'), ('8', '97'),
('5', '19'), ('5', '91'), ('5', '28'), ('5', '82'),
('5', '37'), ('5', '73'), ('5', '46'), ('5', '64')]
perm = chain(*(permutations('123456789', i) for i in range(4, 10)))
ans = 0
for i in perm:
si = ''.join(i)
for x, y in illegal:
if y in si and x not in si[:si.find(y)]:
break
else:
ans += 1
print(ans)

计算得到有\(389112\)种密码。

同理可以算出长度为4、5、6、7、8、9时的密码种类数为\(1624, 7152, 26016, 72912, 140704, 140704\)

从OEIS上可以查到这个数列:http://oeis.org/A163889

总结

如果Android的密码被知道长度不大于5的话,密码的种类数有\(1624 + 7152 = 8776 < 10000\)种,比iPhone的种类数要少;故如果被知道设置的密码长度不大于5,且不考虑其它因素,暴力枚举密码的话,Android的密码并没有比iPhone的四位数密码安全。

然而如果并不知道密码长度的话,Android的密码种类数还是比iPhone的密码种类数多的。

但若只考虑解密者按顺序使用暴力解密的方法,那么Android密码路径长度至少为6时才能比iPhone的密码安全,因为当长度小于6时,解密者按长度为4、长度为5的顺序暴力解密,并不需要试10000次;而iPhone密码按0000, 0001, ..., 9999的顺序暴力解密,最多需要10000次。

故若不考虑额外因素,只考虑按顺序暴力解密的情况下,Android的图案密码需要设置至少6个点的路径才比iPhone的四位数密码安全。