身份证校验算法
验证原理
我国的18位公民身份号码是特征组合是由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
第1、2位
表示省级行政区。第1位数字是以前的大区制代码。第2位是大区所在省市编码。全国共分为8个大区:华北(1)、东北(2)、华东(3)、中南(4)、西南(5)、西北(6)、台湾(7)和港澳(8)。
第3、4位
表示地级行政区。其中,01-20,51-70表示地级市(除儋州市);21-50表示地区、自治州、盟;90表示省直辖县级行政单位(含儋州市);直辖市身份证中01表示市辖区,02表示县。
第5、6位
表示县级行政区。01-18表示市辖区或地区、自治州、盟辖县级市;21-80表示县、旗;81-99表示省直辖县级行政单位。
第7~14位
表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。例如:2023年10月1日就用20231001表示。
第15~17位
表示在同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。其中第十七位奇数分给男性,偶数分给女性。
第18位
为根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2计算出来的检验码。如果某人的尾号为10,那么就得用X来代替,这是罗马数字十,正确读法是十,不读艾克斯或叉。
代码实现
/**
* 校验身份证
*/
function is_idcard($id)
{
$id = strtoupper($id);
$regx = '/(^\d{15}$)|(^\d{17}([0-9]|X)$)/';
$arr_split = array();
if (!preg_match($regx, $id)) {
return false;
}
if (15 == strlen($id)) {
//检查15位
$regx = '/^(\d{6})+(\d{2})+(\d{2})+(\d{2})+(\d{3})$/';
@preg_match($regx, $id, $arr_split);
//检查生日日期是否正确
$dtm_birth =
'19' . $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4];
if (!strtotime($dtm_birth)) {
return false;
} else {
return true;
}
}
//检查18位
else {
$regx = '/^(\d{6})+(\d{4})+(\d{2})+(\d{2})+(\d{3})([0-9]|X)$/';
@preg_match($regx, $id, $arr_split);
$dtm_birth = $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4];
if (!strtotime($dtm_birth)) {
//检查生日日期是否正确
return false;
} else {
//检验18位身份证的校验码是否正确。
//校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。
$arr_int = array(
7,
9,
10,
5,
8,
4,
2,
1,
6,
3,
7,
9,
10,
5,
8,
4,
2,
);
$arr_ch = array(
'1',
'0',
'X',
'9',
'8',
'7',
'6',
'5',
'4',
'3',
'2',
);
$sign = 0;
for ($i = 0; $i < 17; $i++) {
$b = (int) $id[$i];
$w = $arr_int[$i];
$sign += $b * $w;
}
$n = $sign % 11;
$val_num = $arr_ch[$n];
if ($val_num != substr($id, 17, 1)) {
// 校验位失败
return false;
}
}
// 成功,这里还可以进行前6位验证,也可以对17位进行性别验证
return true;
}
}
最后更新于 2023-08-31 17:19:21 并被添加「」标签,已有 445 位童鞋阅读过。
本站使用「署名 4.0 国际」创作共享协议,可自由转载、引用,但需署名作者且注明文章出处
此处评论已关闭