身份证号码和统一社会信用代码校验

身份证号码

身份证号码结构

(身份证号码第一位到第六位)公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
其中,倒数第二位是单数,则性别是男,否则性别为女。

验真思路

  1. 将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2
  2. 将这17位数字和系数相乘的结果相加。
  3. 用加出来和除以11,看余数是多少?
  4. 余数只可能有0,1,2,3,4,5,6,7,8,9,10这11个数字。其分别对应的最后一位身份证的号码为1,0,X,9,8,7,6,5,4,3,2。(即余数0对应1,余数1对应0,余数2对应X…)
  5. 通过上面得知如果余数是3,就会在身份证的第18位数字上出现的是9。如果对应的数字是2,身份证的最后一位号码就是罗马数字X。

余数与校验位对应表格如下

余数 0 1 2 3 4 5 6 7 8 9 10
校验码 1 0 X 9 8 7 6 5 4 3 2

举例

比如已知身份证号码350627199711275419,按照思路将前17位和对应位置的系数相乘并求和:
3*7 + 5*9 + 0*10 + 6*5 + 2*8 + 7*4 + 1*2 + 9*1 + 9*6 + 7*3 + 1*7 + 1*9 + 2*10 + 7*5 + 5*8 + 4*4 + 1*2 = 355,然后用结果355除以11,余数是3,通过查询对应表格,得到校验码是9,与已知的身份证号码第18位相同,所以,可以判定这是一个正确的身份证号码。

再比如已知身份证号码23023019950212522X,按照思路将前17位和对应位置的系数相乘并求和:
2*7 + 3*9 + 0*10 + 2*5 + 3*8 + 0*4 + 1*2 + 9*1 + 9*6 + 5*3 + 0*7 + 2*9 + 1*10 + 2*5 + 5*8 + 2*4 + 2*2 = 245,然后用结果245除以11,余数是3,通过查询对应表格,得到校验码是9,与已知的身份证号码第18位不相同,所以,可以判定这是一个错误的身份证号码。

将上面错误的身份证号码修改为23023019950222522X,检测是否正确。

实现代码(C#)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public bool checkfarenID(string farenID)
{
bool re = false;
if(farenID.Length == 18)
{
char[] ids = farenID.ToCharArray();
int[] factor = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
char[] parity = { '1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2' };
int sum = 0;
int ai = 0;
int wi = 0;
for (int i = 0; i < 17; i++)
{
ai = (int)char.GetNumericValue(ids[i]);
wi = factor[i];
sum += ai * wi;
}
char last = parity[sum % 11];
if (last == ids[17])
{
re = true;
}
}
return re;
}

注:此处出现的身份证号码均为程序生成,如有雷同请联系删除。

统一社会信用代码

统一社会信用代码结构

标准规定统一社会信用代码用18位阿拉伯数字或大写英文字母表示,分别是1位登记管理部门代码、1位机构类别代码、6位登记管理机关行政区划码、9位主体标识码、1位校验码。

验真思路

统一社会信用代码的验真思路和身份证号码基本一致,不过统一社会信用代码包含大写英文字母,需要首先把英文字母转换成对应的数字序号,对应表格如下:

字符 0 1 2 3 4 5 6 7 8 9 A B C D E F G H J K L M N P Q R T U W X Y
对应序号 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

统一社会信用代码中没有I,O,S,V,Z

第1-17位对应的系数依次为:1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28

  1. 把统一社会信用代码中的应为字母按表格转换为对应的数字;
  2. 把1-17位对应的数字,分别于对应的系数相乘,再相加;
  3. 31减去上面的和除以31得到的余数,即31-和%31
  4. 得到的结果(如果结果为31,则设定为0),对比上面的表格,将数字转换为对应的字符(数字或英文字母)。

举例

比如已知统一社会信用代码91330100799655058B(阿里巴巴(中国)有限公司),先按照上面的表格依次得到对应的序号,然后乘以对应位置的系数并求和:9*1 + 1*3 + 3*9 + 3*27 + 0*19 + 1*26 + 0*16 + 0*17 + 7*20 + 9*29 + 9*25 + 6*13 + 5*8 + 5*24 + 0*10 + 5*30 + 8*28 = 1384,然后用31减去1384除以31的余数,得到结果是11,查询表格序号为30对应的字符是B,与已知的统一社会信用代码第18位的字符相同,所以,可以判定这是一个正确的统一社会信用代码。

再比如已知统一社会信用代码91110302562134966R,先按照上面的表格依次得到对应的序号,然后乘以对应位置的系数并求和:9*1 + 1*3 + 1*9 + 1*27 + 0*19 + 3*26 + 0*16 + 2*17 + 5*20 + 6*29 + 2*25 + 1*13 + 3*8 + 4*24 + 9*10 + 6*30 + 6*28 = 1055,然后用31减去1055除以31的余数,得到结果是30,查询表格序号为19对应的字符是Y,与已知的统一社会信用代码第18位的字符不相同,所以,可以判定这是一个错误的统一社会信用代码。

将上面错误的统一社会信用代码修改为91110302562134916R(北京京东世纪信息技术有限公司),检测是否正确。

实现代码(C#)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
public bool checkNumber(string companyNumber)
{
bool re = false;
if (companyNumber.Length == 18)
{
int[] weight = { 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28 };
char[] numbs = companyNumber.ToCharArray();
int sum = 0;
int num = 0;
for (int i = 0; i < 17; i++)
{
num = charToNumber(numbs[i]);
if(num != -1)
{
sum += num * weight[i];
}
}
num = 31 - sum % 31;
num = num == 31 ? 0 : num;
if(charToNumber(numbs[17]) == num)
{
re = true;
}
}
return re;
}
private int charToNumber(char c)
{
switch (c)
{
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
case 'A':
return 10;
case 'B':
return 11;
case 'C':
return 12;
case 'D':
return 13;
case 'E':
return 14;
case 'F':
return 15;
case 'G':
return 16;
case 'H':
return 17;
case 'J':
return 18;
case 'K':
return 19;
case 'L':
return 20;
case 'M':
return 21;
case 'N':
return 22;
case 'P':
return 23;
case 'Q':
return 24;
case 'R':
return 25;
case 'T':
return 26;
case 'U':
return 27;
case 'W':
return 28;
case 'X':
return 29;
case 'Y':
return 30;
default:
return -1;
}
}

写在最后

通过这种校验方法,可以检测人工输入的统一社会信用代码或者身份证号码是否正确。

因为如果输入错误的话,计算结果和输入数字相同的概率太小。