欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

IOS 身份证校验详细介绍及示例代码

程序员文章站 2024-02-17 20:30:16
ios 身份证校验 身份证基础知识: 身份证是国民的身份编号,编号是有一定规律的,这里介绍身份证验证规则比较详细。项目中经常会需要对身份证进行校验,我们先了解一些基本知...

ios 身份证校验

身份证基础知识:

身份证是国民的身份编号,编号是有一定规律的,这里介绍身份证验证规则比较详细。项目中经常会需要对身份证进行校验,我们先了解一些基本知识,然后分析代码

居民身份证号码,根据〖*国家标准 gb 11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。 居民身份证是国家法定的证明公民个人身份的有效证件。

结构和形式

1.号码的结构

   公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。

2.地址码

   表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按gb/t2260的规定执行。

3.出生日期码

   表示编码对象出生的年、月、日,按gb/t7408的规定执行,年、月、日代码之间不用分隔符。

4.顺序码

   表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。

5.校验码

  根据前面十七位数字码,按照iso7064:1983.mod11-2校验码计算出来的检验码。

地址码

华北地区: 北京市|110000,天津市|120000,河北省|130000,山西省|140000,内蒙古自治区|150000,

东北地区: 辽宁省|210000,吉林省|220000,黑龙江省|230000,

华东地区: 上海市|310000,江苏省|320000,浙江省|330000,安徽省|340000,福建省|350000,江西省|360000,山东省|370000,

华中地区: 河南省|410000,湖北省|420000,湖南省|430000,

华南地区: 广东省|440000,广西壮族自治区|450000,海南省|460000,

西南地区: 重庆市|500000,四川省|510000,贵州省|520000,云南省|530000,*自治区|540000,

西北地区: 陕西省|610000,甘肃省|620000,青海省|630000,宁夏回族自治区|640000,**自治区|650000,

特别地区:*地区(886)|710000,香港特别行政区(852)|810000,澳门特别行政区(853)|820000

*居民身份证号码中的地址码的数字编码规则为:

第一、二位表示省(自治区、直辖市、特别行政区)。

第三、四位表示市(地级市、自治州、盟及国家直辖市所属市辖区和县的汇总码)。其中,01-20,51-70表示省直辖市;21-50表示地区(自治州、盟)。

第五、六位表示县(市辖区、县级市、旗)。01-18表示市辖区或地区(自治州、盟)辖县级市;21-80表示县(旗);81-99表示省直辖县级市。

生日期码

  (身份证号码第七位到第十四位)表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。例如:1981年05月11日就用19810511表示。

顺序码

  (身份证号码第十五位到十七位)地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。其中第十七位奇数分给男性,偶数分给女性

校验码

       作为尾号的校验码,是由号码编制单位按统一的公式计算出来的,如果某人的尾号是0-9,都不会出现x,但如果尾号是10,那么就得用x来代替,因为如果用10做尾号,那么此人的身份证就变成了19位,而19位的号码违反了国家标准,并且中国的计算机应用系统也不承认19位的身份证号码。ⅹ是罗马数字的10,用x来代替10,可以保证公民的身份证符合国家标准。

身份证校验码的计算方法

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。

例如:某男性的身份证号码为【53010219200508011x】,我们看看这个身份证是不是合法的身份证。
首先我们得出前17位的乘积和【(5*7)+(3*9)+(0*10)+(1*5)+(0*8)+(2*4)+(1*2)+(9*1)+(2*6)+(0*3)+(0*7)+(5*9)+(0*10)+(8*5)+(0*8)+(1*4)+(1*2)】是189,然后用189除以11得出的结果是189/11=17----2,也就是说其余数是2。最后通过对应规则就可以知道余数2对应的检验码是x。所以,可以判定这是一个正确的身份证号码。

有了上面的基础知识点,下面具体看一下实现代码

18位身份证验证

-(bool)checkuseridcard:(nsstring *)userid 
{ 
  //长度不为18的都排除掉 
  if (userid.length!=18) { 
    return no; 
  } 
   
  //校验格式 
  nsstring *regex2 = @"^(^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$)|(^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[xx])$)$"; 
  nspredicate *identitycardpredicate = [nspredicate predicatewithformat:@"self matches %@",regex2]; 
  bool flag = [identitycardpredicate evaluatewithobject:userid]; 
   
  if (!flag) { 
    return flag;  //格式错误 
  }else { 
    //格式正确在判断是否合法 
    //将前17位加权因子保存在数组里 
    nsarray * idcardwiarray = @[@"7", @"9", @"10", @"5", @"8", @"4", @"2", @"1", @"6", @"3", @"7", @"9", @"10", @"5", @"8", @"4", @"2"]; 
     
    //这是除以11后,可能产生的11位余数、验证码,也保存成数组 
    nsarray * idcardyarray = @[@"1", @"0", @"10", @"9", @"8", @"7", @"6", @"5", @"4", @"3", @"2"]; 
     
    //用来保存前17位各自乖以加权因子后的总和 
    nsinteger idcardwisum = 0; 
    for(int i = 0;i < 17;i++){ 
      nsinteger substrindex = [[userid substringwithrange:nsmakerange(i, 1)] integervalue]; 
      nsinteger idcardwiindex = [[idcardwiarray objectatindex:i] integervalue]; 
      idcardwisum+= substrindex * idcardwiindex; 
    } 
     
    //计算出校验码所在数组的位置 
    nsinteger idcardmod=idcardwisum%11; 
     
    //得到最后一位身份证号码 
    nsstring * idcardlast= [userid substringwithrange:nsmakerange(17, 1)]; 
     
    //如果等于2,则说明校验码是10,身份证号码最后一位应该是x 
    if(idcardmod==2){ 
      if([idcardlast isequaltostring:@"x"]||[idcardlast isequaltostring:@"x"]){ 
        return yes; 
      }else{ 
        return no; 
      } 
    }else{ 
      //用计算出的验证码与最后一位身份证号码匹配,如果一致,说明通过,否则是无效的身份证号码 
      if([idcardlast isequaltostring: [idcardyarray objectatindex:idcardmod]]){ 
        return yes; 
      }else{ 
        return no; 
      } 
    } 
  } 
} 

15位和18位身份证验证

//正则匹配用户身份证号15或18位 
-(bool)validateidcardnumber:(nsstring *)value { 
 
  value = [value stringbytrimmingcharactersinset:[nscharacterset whitespaceandnewlinecharacterset]]; 
  nsinteger length =0; 
  if (!value) { 
    return no; 
  }else { 
    length = value.length; 
    //不满足15位和18位,即身份证错误 
    if (length !=15 && length !=18) { 
      return no; 
    } 
  } 
  // 省份代码 
  nsarray *areasarray = @[@"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"]; 
   
  // 检测省份身份行政区代码 
  nsstring *valuestart2 = [value substringtoindex:2]; 
  bool areaflag =no; //标识省份代码是否正确 
  for (nsstring *areacode in areasarray) { 
    if ([areacode isequaltostring:valuestart2]) { 
      areaflag =yes; 
      break; 
    } 
  } 
   
  if (!areaflag) { 
    return no; 
  } 
   
  nsregularexpression *regularexpression; 
  nsuinteger numberofmatch; 
   
  int year =0; 
  //分为15位、18位身份证进行校验 
  switch (length) { 
    case 15: 
      //获取年份对应的数字 
      year = [value substringwithrange:nsmakerange(6,2)].intvalue +1900; 
     
      if (year %4 ==0 || (year %100 ==0 && year %4 ==0)) { 
        //创建正则表达式 nsregularexpressioncaseinsensitive:不区分字母大小写的模式 
        regularexpression = [[nsregularexpression alloc]initwithpattern:@"^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$" 
          options:nsregularexpressioncaseinsensitive error:nil];//测试出生日期的合法性 
      }else { 
        regularexpression = [[nsregularexpression alloc]initwithpattern:@"^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$" 
        options:nsregularexpressioncaseinsensitive error:nil];//测试出生日期的合法性 
      } 
      //使用正则表达式匹配字符串 nsmatchingreportprogress:找到最长的匹配字符串后调用block回调 
      numberofmatch = [regularexpression numberofmatchesinstring:value 
                                options:nsmatchingreportprogress 
                                 range:nsmakerange(0, value.length)]; 
       
      if(numberofmatch >0) { 
        return yes; 
      }else { 
        return no; 
      } 
    case 18: 
      year = [value substringwithrange:nsmakerange(6,4)].intvalue; 
      if (year %4 ==0 || (year %100 ==0 && year %4 ==0)) { 
        regularexpression = [[nsregularexpression alloc]initwithpattern:@"^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9xx]$" options:nsregularexpressioncaseinsensitive error:nil];//测试出生日期的合法性 
      }else { 
        regularexpression = [[nsregularexpression alloc]initwithpattern:@"^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9xx]$" options:nsregularexpressioncaseinsensitive error:nil];//测试出生日期的合法性 
      } 
      numberofmatch = [regularexpression numberofmatchesinstring:value 
                                options:nsmatchingreportprogress 
                                 range:nsmakerange(0, value.length)]; 
       
       
      if(numberofmatch >0) { 
        //1:校验码的计算方法 身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。将这17位数字和系数相乘的结果相加。 
         
        int s = [value substringwithrange:nsmakerange(0,1)].intvalue*7 + [value substringwithrange:nsmakerange(10,1)].intvalue *7 + [value substringwithrange:nsmakerange(1,1)].intvalue*9 + [value substringwithrange:nsmakerange(11,1)].intvalue *9 + [value substringwithrange:nsmakerange(2,1)].intvalue*10 + [value substringwithrange:nsmakerange(12,1)].intvalue *10 + [value substringwithrange:nsmakerange(3,1)].intvalue*5 + [value substringwithrange:nsmakerange(13,1)].intvalue *5 + [value substringwithrange:nsmakerange(4,1)].intvalue*8 + [value substringwithrange:nsmakerange(14,1)].intvalue *8 + [value substringwithrange:nsmakerange(5,1)].intvalue*4 + [value substringwithrange:nsmakerange(15,1)].intvalue *4 + [value substringwithrange:nsmakerange(6,1)].intvalue*2 + [value substringwithrange:nsmakerange(16,1)].intvalue *2 + [value substringwithrange:nsmakerange(7,1)].intvalue *1 + [value substringwithrange:nsmakerange(8,1)].intvalue *6 + [value substringwithrange:nsmakerange(9,1)].intvalue *3; 
         
        //2:用加出来和除以11,看余数是多少?余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字 
        int y = s %11; 
        nsstring *m =@"f"; 
        nsstring *jym =@"10x98765432"; 
        m = [jym substringwithrange:nsmakerange(y,1)];// 3:获取校验位 
        //4:检测id的校验位 
        if ([m isequaltostring:[value substringwithrange:nsmakerange(17,1)]]) { 
          return yes; 
        }else { 
          return no; 
        } 
         
      }else { 
        return no; 
      } 
    default: 
      return no; 
  } 
} 

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!