公民身份证号校验规则
前些天注册某应用时,要求提交身份证号码,随便填了一个,不给通过。想来也是,身份证号码肯定有一套规则,里面必定包含了校验码,经过查证,便有了此篇。
结构及定义:
身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。
从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
地址码 | - | - | 出生日期码 | - | - | 顺序码 | 校验码 |
---|---|---|---|---|---|---|---|
11 | 01 | 05 | 1949 | 12 | 31 | 002 | X |
北京市 | 市辖区 | 朝阳区 | 出生年 | 出生月 | 出生日 | 计算得出 |
组成部分:
六位地址码
行政区划代码,公民出生后申报户口时的所在地的行政地区编码。
另如果行政区改名或升级、合并的,行政区代码将会发生变化,这时已有的身份证号码(老人)不变,新出生的(新人)身份证将用新的行政区代码。
八位出生日期码
出生日期代码,四位年份,两位月份,两位日期。不足两位的补 0 填充。
比如 1989 年 2 月 1 日生,写为 19890201 。
三位数字顺序码
分配顺序代码,是在同一区域内,对同一天出生的人员编制的顺序号。
其中末尾(第 17 位)单数是男性,双数是女性。
一位数字校验码
按统一的公式计算出来,计算结果是数字 0-10(取模运算,模 11 ),用X代替 10 。
校验规则
$$ \sum_{i=1}^{18}(a_i * W_i) \equiv1(mod 11)\quad Wi=2^{i-1}(mod 11) \quad //i从右至左数 $$
权重表
位数i | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
加权Wi | 7 | 9 | 10 | 5 | 8 | 4 | 2 | 1 | 6 | 3 | 7 | 9 | 10 | 5 | 8 | 4 | 2 | 1 |
其中,加权因子由 计算得出。
生成规则
六位地址码,参考这里的对应规则 https://github.com/cn/GB2260/blob/develop/200712.tsv
八位出生日期码,注意日期的合法性,不要出现2月30日这类错误!
三位数字顺序码,注意最后一位奇数为男性,偶数为女性。
一位数字校验码,其生成公式和校验公式一致,是其校验公式的变形。
$$ a_1= trans\sum_{i=2}^{18}(a_i * W_i)(mod 11) \quad trans(m)=(12-m)\%11 $$
映射如下
m | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|
trans(m) | 1 | 0 | X | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 |
js脚本
//只负责生成和校验最后一位,不对地区码、日期码做出判断。如果需要可自行添加。
function getCheckNum(s){
let sum =0; for(let i = 0;i<17;i++)sum+=s[i]*(Math.pow(2,17-i)%11);
return (12-sum%11)%11;
}
function CheckNum(s){
let sum =0; for(let i = 0;i<18;i++)sum+=s[i]*(Math.pow(2,17-i)%11);
return sum%11===1;
}
附录
GB/T 2260-1995 中华人民共和国行政区划代码
GB/T 7408-1994 数据元和交换格式 信息交换 日期和时间表示法
本文由 ukuq 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Oct 5, 2019 at 07:37 pm