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;
  }
}

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

(0)

相关推荐

  • Objective-C实现身份证验证的方法示例

    前言 最近在一个二次开发的项目中看到了一段身份证验证的OC代码,虽然我一直讨厌二次开发.因为这这个二次开发的项目太老,代码太乱,毫无层次感.可是令人欣慰的是,我在里面发现了一段有用的代码,感兴趣的可以参考学习. 直接上代码 - (BOOL)isValidIdCardNum { NSString *value = [self copy]; value = [value stringByReplacingOccurrencesOfString:@"X" withString:@"

  • iOS正则表达式验证手机号、邮箱、身份证号等

    本文实例为大家分享了常用的iOS正则表达式,供大家参考,具体内容如下 #import "NSString+RegexCategory.h" @implementation NSString (RegexCategory) #pragma mark - 正则相关 - (BOOL)isValidateByRegex:(NSString *)regex{ NSPredicate *pre = [NSPredicate predicateWithFormat:@"SELF MATCH

  • iOS 中使用正则表达式判断身份证格式及银行卡号格式是否正确(推荐)

    1.有时候我们会用到上传身份证号,或者银行卡号,这个时候就需要我们对身份证号以及银行卡号,进行基本的判断. 下面便是身份证号的判断返回YES是合法,反之不合法 #pragma mark 判断身份证号是否合法 - (BOOL)judgeIdentityStringValid:(NSString *)identityString { if (identityString.length != 18) return NO; // 正则表达式判断基本 身份证号是否满足格式 NSString *regex2

  • iOS身份证号码识别示例

    一.前言 身份证识别,又称OCR技术.OCR技术是光学字符识别的缩写,是通过扫描等光学输入方式将各种票据.报刊.书籍.文稿及其它印刷品的文字转化为图像信息,再利用文字识别技术将图像信息转化为可以使用的计算机输入技术. 因为项目需要,所以这些天查阅了相关资料,想在网上看看有没有大神封装的现成的demo可以用.但是无果,网上关于ocr这一块的资料很少,比较靠谱的都是要收费的,而且价格也不便宜.但是在天朝,收费感觉心里不爽,所以就决定自己研究一番. 先上一个最终实现的效果(如果mac不是retain屏

  • IOS身份证识别(OCR源码)详解及实例代码

    IOS身份证识别(OCR源码)详解 最近项目用到身份证识别,在github上搜了一堆demo,在Google上找了一堆代码,有能识别出证件照的,但是都是打包成.a的静态库,没有源码,我努力吃了几天书,有了一点研究成果,现在贴出来与大家分享,要是有更好的方法,希望大神指正,共同探讨解决方案.(以下代码本人亲测可用,正在进一步探索智能识别,如有兴趣,请加入) 这里用到了两个开源库:OpenCV.TesseractOCRiOS,两个语言包chi_sim.eng.身份证识别的流程主要有:灰度化,阀值二值

  • iOS判断身份证号码是否正确的方法

    ①根据百度百科中身份证号码的标准实现该方法 ②该方法只能判断18位身份证,且不能判断身份证号码和姓名是否对应(要看姓名和号码是否对应,应该有大量的数据库做对比才能实现) ③直接copy这段代码,就能通过调用这个方法判断身份证号码是否符合标准,非常easy /** * 验证身份证号码是否正确的方法 * * @param IDNumber 传进身份证号码字符串 * * @return 返回YES或NO表示该身份证号码是否符合国家标准 */ - (BOOL)isCorrect:(NSString *)

  • iOS Touch ID 身份认证

    iOS Touch ID 身份认证 iOS 8 及以后录了指纹的设备可以使用 touch ID 进行身份认证,指纹符合录入的指纹才能认证成功. 步骤 导入 LocalAuthentication 框架:import LocalAuthentication 初始化 LAContext 对象:let context = LAContext() 调用 LAContext 对象的 canEvaluatePolicy(_ policy: LAPolicy, error: NSErrorPointer) -

  • IOS开发之由身份证号码提取性别的实现代码

    一,代码. - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. NSString *sex=[self sexStrFromIdentityCard:@"139876456767892345"]; NSLog(@"--sex--%@",sex); } //由身份证号返回为性别 -(NSString *)sexStrFromIdent

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

    IOS 身份证校验 身份证基础知识: 身份证是国民的身份编号,编号是有一定规律的,这里介绍身份证验证规则比较详细.项目中经常会需要对身份证进行校验,我们先了解一些基本知识,然后分析代码 居民身份证号码,根据[中华人民共和国国家标准 GB 11643-1999]中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成.排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码. 居民身份证是国家法定的证明公民个人身份的有效证件. 结

  • C语言 运算符详细介绍及示例代码

    C 运算符 运算符是一种告诉编译器执行特定的数学或逻辑操作的符号.C 语言内置了丰富的运算符,并提供了以下类型的运算符: 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 杂项运算符 本章将逐一介绍算术运算符.关系运算符.逻辑运算符.位运算符.赋值运算符和其他运算符. 算术运算符 下表显示了 C 语言支持的所有算术运算符.假设变量 A 的值为 10,变量 B 的值为 20,则: 运算符 描述 实例 + 把两个操作数相加 A + B 将得到 30 - 从第一个操作数中减去第二个操作数 A

  • JAVA HashMap详细介绍和示例

    第1部分 HashMap介绍HashMap简介HashMap 是一个散列表,它存储的内容是键值对(key-value)映射.HashMap 继承于AbstractMap,实现了Map.Cloneable.java.io.Serializable接口.HashMap 的实现不是同步的,这意味着它不是线程安全的.它的key.value都可以为null.此外,HashMap中的映射不是有序的.HashMap 的实例有两个参数影响其性能:"初始容量" 和 "加载因子".容量

  • iOS 对view进行截图的示例代码

    本文主要介绍了iOS 对view进行截图的示例代码,分享给大家,具体如下: 需要对WKWebView进行截图,之前用的是下面的方法,高版本的系统是没有问题的,低版本的却截到一张白图 - (UIImage *)convertViewToImage:(UIView *)view{ // 第二个参数表示是否非透明.如果需要显示半透明效果,需传NO,否则YES.第三个参数就是屏幕密度了 UIGraphicsBeginImageContextWithOptions(CGSizeMake(view.boun

  • Qt 实现画线笔锋效果详细原理及示例代码

    前言 之前写过一篇文章介绍Qt中绘制平滑曲线的两种方式,文章在这里.这篇文章详细介绍了绘制的原理和实现方式,那么,如果要在此曲线上实现笔锋效果怎么做呢? 所谓的笔锋效果,就是钢笔书写抬笔时的笔尖,也就是说,绘制曲线抬笔时形成一个笔尖的效果. 话不多说,直接来看效果: 动画效果如下: 实现原理 要实现该效果,需要完成以下几个关键步骤: 1.每两个点形成一个贝塞尔曲线path进行绘制 2.最新的一条path绘制细线(笔锋最细处的宽度) 3.倒数第二条path绘制粗线(正常的线条宽度) 4.在两条pa

  • C++实现三子棋游戏详细介绍(附代码)

    目录 游戏描述: 游戏思维导图: (从头开始)头文件也写在前面: 先把游戏与主函数写在前面: 游戏函数: 主函数: 1.构建游戏菜单 2.构建棋盘 3.玩家和电脑下棋 3.1玩家先下 3.2电脑下棋 4.判断胜负与下棋结果 代码附上: 总结 游戏描述: 先来点真实的!三子棋其实就是我们小时候经常玩的井字棋,如果一方玩家实现横着三个或者竖着三个,或者对角线三个就算游戏胜利! 游戏思维导图: (从头开始)头文件也写在前面: #include <stdio.h> #include <stdli

  • iOS如何为圆角添加阴影效果示例代码

    前言 大家都知道在iOS中为UIView添加阴影还是比较简单的,只需要设置layer的shadow属性就可以了,但是问题在于设置阴影之后,必须设置masksToBounds为NO,而圆角图片则要求masksToBounds必须为YES,两者相互冲突,会导致无法正确的添加阴影.下面就来给大家介绍正确为圆角添加阴影的效果,话不多说了,来一起看看详细的介绍吧. 先来看看效果图: 正确的做法: 先创建一个透明的UIView,并添加阴影,设置masksToBounds为NO: 然后在透明的UIView上添

  • iOS Swift控制器转场动画示例代码

    前言 在IOS开发中,我们model另外一个控制器的时候,一般都使用默认的转场动画.本文将给大家详细介绍关于iOS Swift控制器转场动画的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 返回效果也可更改 四种转场动画 1. move:源图片位置移动到目标图片位置: 2. circle:根据源控件大小创建圆形或者椭圆形path路径,放大展示目标: 3. tier:源左右,目标由小到大缩放: 4. middle:源的中心点开始放大,返回是缩回到中心. 代码解析 给UI

  • IOS设置按钮为圆角的示例代码

    iOS中很多时候都需要用到指定风格的圆角按钮,以下是UIButton提供的创建圆角按钮方法 设置按钮的4个角: 左上:UIRectCornerTopLeft 左下:UIRectCornerBottomLeft 右上:UIRectCornerTopRight 右下:UIRectCornerBottomRight 示例代码: UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(50, 60, 80, 40)]; button.b

  • iOS中使用对象的弱引用示例代码

    简介 我们都知道使用 UIImage imageNamed 创建的 UIImage 对象会被持有(强引用),如果图片太大会占用内存,损耗 APP 的性能,影响用户体验,如果能改造对其的强引用变为弱引用就可以解决问题. 我们可能会有类似上面的场景,有些对象暂时保存起来,可能后面会用到,也有可能不会使用,但是又不想去管理它们的生命周期,如果它们能够自己被销毁就很省事,不需要去关心这些对象到底耗费了多少内存. 今天跟大家聊聊如何在 iOS 开发中保持对对象的弱引用而不是强引用,希望看完之后,能帮助到大

随机推荐