证件校验规则研究
身份证
身份证格式
身份证为18位,构成规则如下:
- 前6位表示出生地所在县(市、区)
- 7~14位表示出生年月日
- 15~17位表示顺序码,对同地区、同年同月同日出生的人进行排序,其中第17位奇数分给男性,偶数分给女性
- 第18位为校验码,校验码如果出现数字10,用X来表示
校验码生成
- 将身份证号码的前17位分别乘以不同的系数。从第1位到第17位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。
- 将这17位数字和系数相乘的结果相加。
- 将相加得到的和除以11,取余数,余数只可能为0~10,分别对应身份证最后一位:1-0-X-9-8-7-6-5-4-3-2。
Python检验校验码
factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
verify_list = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
number = input()
checksum = 0
for i in range(len(number) - 1):
checksum = checksum + factor[i] * int(number[i])
checksum = checksum % 11
print(verify_list[checksum])
if number[-1] == verify_list[checksum]:
print("Pass")
else:
print("Fail")
合法地区列表
- 11:北京,12:天津,13:河北,14:山西,15:内蒙古;
- 21:辽宁,22:吉林,23:黑龙江;
- 31:上海,32:江苏,33:浙江,34:安徽,35:福建,36:江西,37:山东;
- 41:河南,42:湖北,43:湖南,44:广东,45:广西,46:海南;
- 50:重庆,51:四川,52:贵州,53:云南,54:西藏;
- 61:陕西,62:甘肃,63:青海,64:宁夏,65:新疆;
- 71:台湾;
- 81:香港,82:澳门;
- 91:国外。
测试点
不仅需要测试是否对身份证号的这些字段有校验,还需要测试是否将合法的证件号识别为非法。
因为证件号的校验过程中,可能还会因校验代码某处出错,导致合法证件号不通过的情况,这些情况所需要构造的测试输入较多。
与将非法的证件号识别为合法相比,将合法的证件号识别为非法风险更大,所以需要进行测试覆盖。
地区
合法地区列表取边界值
通过:11、15、21、23、31、37、41、46、50、54、61、65、71、81、82、91
不通过:00、01、09、10、16、20、24、30、38、40、47、55、60、66、70、72、80、83、90、92
对第3-6位不做校验,采取随机数生成的方式
出生年份
1900-当前年份取边界值
通过:1900、1999、2000、2001、当前年份(小于等于当前日期)
不通过:1899、2021
出生月份
01-12取边界值
通过:01、09、10、11、12
不通过:00、13
出生日期
01-31取边界值
通过:01、10、11、20、21、30、31
不通过:00、32
年月日组合
闰平年2月日期校验、每月日期校验
通过:20040229、0131、0228、0331、0430、0531、0630、0731、0831、0930、1031、1130、1231、当前日期
不通过:20010229、0132、0230、0332、0431、0532、0631、0732、0832、0931、1032、1131、1232、当前日期+1天
顺序码
000-999取边界值
通过:000、099、100、101、999
校验码
遍历0-9、X
通过:遍历0-9、X,且按照校验码计算规则生成
不通过:不按照校验码计算规则生成
用例生成
首先,测试应该验证通过的组合
除校验码外的选项进行单一选择组合
为每一个生成的结果构造身份证号,结果如下:
110692190001010004
154028199909100999
213694200010111005
233467200111201011
313659190012219990
370592199901300000
412401190008310991
467055200402291001
506681190001311017
542106199902289993
619982200003310007
656983200104300992
717280190005311008
815268199906301016
82094220000731999X
912217200108310002
112780190009300999
157117199910311004
21574119001130101X
233436199912319992
还需要额外增加一个当前日期构造的身份证号
已覆盖所有校验码的情况
然后验证应该验证不通过的组合
对于每一个非法的字段,组合其他合法的字段,并生成正确的校验码
地区非法:
- 00821019960110000X
- 016104199601100994
- 090596199601101008
- 106766199601101013
- 161241199601109994
- 207667199601100006
- 248306199601100992
- 301342199601101003
- 380558199601101019
- 406436199601109999
- 479475199601100007
- 559877199601100999
- 604832199601101001
- 666767199601101019
- 708179199601109995
- 721966199601100002
- 800764199601100995
- 831137199601101005
- 908908199601101011
- 929776199601109990
出生年份非法:
- 119266189901100000
- 155809202101100992
出生月份非法:
- 216299199600101007
- 233888199613101010
出生日期非法:
- 312544199601009998
- 271079199601320009
还需要一个当前日期+1天构造的身份证号,可使用附件脚本构造
年月日组合非法:
- 418429200102290995
- 465225199601321002
- 503522199602301011
- 542888199603329990
- 619936199604310009
- 650394199605320993
- 710026199606311009
- 817812199607321011
- 825244199608329990
- 914952199609310004
- 116092199610320999
- 15948219961131100X
- 219376199612321010
校验码非法:
- 112409199001010005