公民身份证号校验规则

in 积露为波 with 0 comment

公民身份证号校验规则

前些天注册某应用时,要求提交身份证号码,随便填了一个,不给通过。想来也是,身份证号码肯定有一套规则,里面必定包含了校验码,经过查证,便有了此篇。

结构及定义:

身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。

从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。

地址码--出生日期码--顺序码校验码
11010519491231002X
北京市市辖区朝阳区出生年出生月出生日 计算得出

组成部分:

六位地址码

行政区划代码,公民出生后申报户口时的所在地的行政地区编码。

另如果行政区改名或升级、合并的,行政区代码将会发生变化,这时已有的身份证号码(老人)不变,新出生的(新人)身份证将用新的行政区代码。

八位出生日期码

出生日期代码,四位年份,两位月份,两位日期。不足两位的补 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从右至左数 $$

权重表

位数i181716151413121110987654321
加权Wi79105842163791058421

其中,加权因子由 计算得出。

生成规则

六位地址码,参考这里的对应规则 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 $$

映射如下

m012345678910
trans(m)10X98765432

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 11643-1999 公民身份号码

GB/T 2260-1995 中华人民共和国行政区划代码

GB/T 7408-1994 数据元和交换格式 信息交换 日期和时间表示法

Responses