头图:https://cdn.naraku.cn/imgs/Python_id-cards0.jpg
最近突发奇想,想写一个小脚本来生成一个身份证后6位的小字典。因为学校有时候会发布的一些统一的账号表,例如校园网的账号密码,通常账号名为学号,密码则为身份证后6位,所以有时候可能会派上用场?
首先需要了解一下身份证号码结构:
1~6
,地址码,常住户口所在地的行政区划代码7~14
,出生年月日15~17
,顺序码,且第17位由性别决定。男性为奇数,女性为偶数18
校验码,将前面17位代入公式计算,结果为0~10
,若为10
则用X
表示
举例:440106 19990101 0010
44
广东省,01
广州市,06
天河区19990101
,出生年月日001
,第17
位为1
即男性0
,最后一位为校验码
如果需要爆破后6位,即身份证的第13~18
位,那么就有10*10*10*10*10*11
(最后一位有0~X
共11位)种可能
- 后6位中的第1位,即出生日期的十位,只能为
0~3
,即4*10*10*10*10*11
- 而如果是针对某人而写的字典,知道目标的性别,那么第
5
位就可以减掉一半。男性为1/3/5/7/9
,女性为0/2/4/6/8
,即4*10*10*10*5*11
- 同时,如果知道目标的出生日期(学校发的很多信息表中都会包含出生年月日等信息),即第
1~2
位也可以确定了。那么需要爆破的只有15~18
位,即10*10*5*11=5500
,这个数量级已经对于电脑来说很轻松就可以完成。
说了这么一大堆,其实最后也就10多行代码:
import itertools
if __name__ == '__main__':
date = input("出生日期: ")
sex = '02468' if int(input("性别(男1女2): ")) % 2 == 0 else '13579' # 性别位
check = '0123456789X' # 校验位
other = '0123456789' # 其它位
nums = itertools.product(other, other, sex, check)
cards = []
for num in nums:
card = date + "".join(num)
cards.append(card)
print(len(cards))
print(cards)