身份证号码的编码规则及校验

article/2025/9/28 9:55:23

前言

本文内容适用于二代身份证,如无特殊说明,本文中所说的身份证皆指二代身份证。

笔者目前使用的jdk版本是1.6.0_29,Eclipse版本是Juno Release,Build id 20120614-1722。如无特殊说明,本文所有的Java代码都是基于此。

本文包含大量数学公式和Java代码,手机端浏览体验较差,可在手机端浏览文字性内容,数学公式和Java代码在PC端浏览,同时建议准备好纸、笔用于数学公式的演算。具有一定数学基础的读者也可以忽略此条建议。

本文中提供的Java代码都是笔者逐行编写、反复斟酌,以求能够抛砖引玉,使初学者可以孜孜不倦,在Java的学习道路上更进一层楼。本文内容,不足之处,欢迎大家批评指正。

身份证号码的编码规则

身份证号码共18位,由17位本体码和1位校验码组成。

  1. 前6位是地址码,表示登记户口时所在地的行政区划代码,依照《中华人民共和国行政区划代码》国家标准(GB/T2260)的规定执行;
  2. 7到14位是出生年月日,采用YYYYMMDD格式;
  3. 15到17位是顺序码,表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编订的顺序号,顺序码的奇数分配给男性,偶数分配给女性,即第17位奇数表示男性,偶数表示女性;
  4. 第18位是校验码,采用ISO 7064:1983, MOD 11-2校验字符系统,计算规则下一章节说明。

一代身份证与二代身份证的区别在于:

  1. 一代身份证是15位,二代身份证是18位;
  2. 一代身份证出生年月日采用YYMMDD格式,二代身份证出生年月日采用YYYYMMDD格式;
  3. 一代身份证无校验码,二代身份证有校验码。

校验码计算规则

身份证号码中各个位置上的号码字符值应满足下列公式的校验:

  • 表示号码字符从右至左包括校验码字符在内的位置序号;
  • 表示第i位置上的号码字符值,是身份证号码第18位校验码;
  • 表示第i位置上的加权因子,加权因子计算公式

举例说明:

笔者身份证号码为370683198901117657,根据上述公式进行校验。

 

大家可以根据此方法验证自己的身份证号码。

了解了身份证号码的校验公式后,根据同余定理可证得身份证号码校验码的计算公式:

值等于10时,用罗马数字符X表示。此处需要注意:是罗马数字X,不应理解为英文字母X。

实际应用

在金融行业软件系统中,对于身份证号码的采集、校验用途甚广。

  1. 身份证号码前6位,可采集客户户籍所在地,只需将国家标准GB/T 2260中定义的行政区划代码导入数据库,程序中进行映射即可;但需要注意的是,行政区划代码每隔几年会修订一次,从笔者手上的2007版来看,共经历了1982年、1984年、1986年、1988年、1991年、1995年、1999年、2002年、2007年九次修订,所以要预留更新机制;
  2. 身份证号码7到14位,可采集客户的出生日期、年龄、生日;
  3. 身份证号码17位,可采集客户的性别,奇数表示男性,偶数表示女性;
  4. 身份证号码的验证渠道,不管验证成功与否,往往都是收费的,比如银行渠道、公安部渠道,在发往这些渠道验证之前,先对其进行长度、正则表达式、校验码的验证,能够适当提高收费验证的成功率,节省成本支出;而且也可以提升用户体验,在用户输入错误时及时反馈而不必等待验证渠道结果的返回。

下面,就以实际代码为例,说明身份证号码校验的方法。首先,给出身份证号码的正则表达式:

/*** 18位二代身份证号码的正则表达式*/
public static final String REGEX_ID_NO_18 = "^"+ "\\d{6}" // 6位地区码+ "(18|19|([23]\\d))\\d{2}" // 年YYYY+ "((0[1-9])|(10|11|12))" // 月MM+ "(([0-2][1-9])|10|20|30|31)" // 日DD+ "\\d{3}" // 3位顺序码+ "[0-9Xx]" // 校验码+ "$";/*** 15位一代身份证号码的正则表达式*/
public static final String REGEX_ID_NO_15 = "^"+ "\\d{6}" // 6位地区码+ "\\d{2}" // 年YYYY+ "((0[1-9])|(10|11|12))" // 月MM+ "(([0-2][1-9])|10|20|30|31)" // 日DD+ "\\d{3}"// 3位顺序码+ "$";

校验身份证号码:

/*** 校验身份证号码* * <p>* 适用于18位的二代身份证号码* </p>* * @param IDNo18 身份证号码* @return true - 校验通过<br>*         false - 校验不通过* @throws IllegalArgumentException *             如果身份证号码为空或长度不为18位或不满足身份证号码组成规则*             <i>6位地址码+*             出生年月日YYYYMMDD+3位顺序码*             +0~9或X(x)校验码</i>*/
public static boolean checkIDNo(String IDNo18) {// 校验身份证号码的长度if (!checkStrLength(IDNo18, 18)) {throw new IllegalArgumentException();}// 匹配身份证号码的正则表达式if (!regexMatch(IDNo18, REGEX_ID_NO_18)) {throw new IllegalArgumentException();}// 校验身份证号码的验证码return validateCheckNumber(IDNo18);
}/*** 校验字符串长度* * @param inputString 字符串* @param len 预期长度* @return true - 校验通过<br>*         false - 校验不通过*/
private static boolean checkStrLength(String inputString, int len) {if (inputString == null || inputString.length() != len) {return false;}return true;
}/*** 匹配正则表达式* * @param inputString 字符串* @param regex 正则表达式* @return true - 校验通过<br>*         false - 校验不通过*/
private static boolean regexMatch(String inputString, String regex) {return inputString.matches(regex);
}/*** 校验码校验* <p>* 适用于18位的二代身份证号码* </p>* * @param IDNo18 身份证号码* @return true - 校验通过<br>*         false - 校验不通过*/
private static boolean validateCheckNumber(String IDNo18) {// 加权因子int[] W = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };char[] IDNoArray = IDNo18.toCharArray();int sum = 0;for (int i = 0; i < W.length; i++) {sum += Integer.parseInt(String.valueOf(IDNoArray[i])) * W[i];}// 校验位是X,则表示10if (IDNoArray[17] == 'X' || IDNoArray[17] == 'x') {sum += 10;} else {sum += Integer.parseInt(String.valueOf(IDNoArray[17]));}// 如果除11模1,则校验通过return sum % 11 == 1;
}

计算校验码:

/*** 计算身份证号码的校验码* <p>* 适用于18位的二代身份证号码,身份证号码由17位本体码和1位校验码组成* </p>* * @param masterNumber 本体码* @return 身份证号码* @throws IllegalArgumentException *             如果本体码为空或长度不为17位或不满足本体码组成规则*             <i>6位地址码+*             出生年月日YYYYMMDD+3位顺序码</i>*/
public static String computeIDNoCheckNumber(String masterNumber) {// 校验本体码的长度if (!checkStrLength(masterNumber, 17)) {throw new IllegalArgumentException();}// 匹配本体码的正则表达式if (!regexMatch(masterNumber, REGEX_MASTER_NUMBER)) {throw new IllegalArgumentException();}// 计算校验码String checkNumber = computeCheckNumber(masterNumber);// 返回本体码+校验码=完整的身份证号码return masterNumber + checkNumber;
}/*** 计算校验码* <p>* 适用于18位的二代身份证号码* </p>* * @param masterNumber 本体码* @return 校验码*/
private static String computeCheckNumber(String masterNumber) {// 加权因子int[] W = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };char[] masterNumberArray = masterNumber.toCharArray();int sum = 0;for (int i = 0; i < W.length; i++) {sum += Integer.parseInt(String.valueOf(masterNumberArray[i])) * W[i];}// 根据同余定理得到的校验码数组String[] checkNumberArray = { "1", "0", "X", "9", "8", "7", "6", "5", "4","3", "2" };// 得到校验码String checkNumber = checkNumberArray[sum % 11];// 返回校验码return checkNumber;
}

虽然15位的一代身份证已经停用,但是难免有需要用到将15位的一代身份证升级为18位的二代身份证的情形,代码示例如下:

/*** 15位一代身份证号码升级18位二代身份证号码* <p>* 为15位的一代身份证号码增加年份的前2位和最后1位校验码* </p>* * @param IDNo15 15位的一代身份证号码* @return 18位的二代身份证号码*/
public static String updateIDNo15to18(String IDNo15) {// 校验身份证号码的长度if (!checkStrLength(IDNo15, 15)) {throw new IllegalArgumentException();}// 匹配身份证号码的正则表达式if (!regexMatch(IDNo15, REGEX_ID_NO_15)) {throw new IllegalArgumentException();}// 得到本体码,因一代身份证皆为19XX年生人,年份中增加19,组成4位String masterNumber = IDNo15.substring(0, 6) + "19" + IDNo15.substring(6);// 计算校验码String checkNumber = computeCheckNumber(masterNumber);// 返回本体码+校验码=完整的身份证号码return masterNumber + checkNumber;
}
12345678910111213141516171819202122232425

同余

同余的定义

给定一个正整数m,如果两个整数a和b满足a-b能够被m整除,即得到一个整数,那么就称整数a与b对模m同余,记作

同余的性质

  1. 反身性:
  2. 对称性:若,则
  3. 传递性:若,则
  4. 同余式相加:若,则
  5. 同余式相乘:若,则

校验码计算规则章节中,用到了以下公式


我们以此为例进行证明,设


校验字符系统

关于校验字符系统,其国际标准ISO 7064有2个版本,分别是ISO 7064:1983和ISO/IEC 7064:2003,从内容上来说,除了表面的调整,本质上没有区别,我想可以理解为是IEC成立后对其工作范围主权的宣示。那么,对应的国家标准,也有了2个版本,分别是GB/T 17710-1999和GB/T 17710-2008,基本上保证了对国际标准的高水准翻译水平,使英文阅读能力欠佳的读者可以通过国家标准来体会国际标准制定的严谨,并从中受益。

标准中,提供了如下几个校验字符系统,基本涵盖日常所需。身份证号码校验使用的ISO 7064, MOD 11-2,便是其中之一。在实际项目中,可按需选用。

系统类型系统名称适用范围校验码数目及类型数字表示法
纯系统ISO 7064, MOD 11-2数字1位数字或附加符X1
纯系统ISO 7064, MOD 37-2字母数字1位数字或字母或附加符*2
纯系统ISO 7064, MOD 97-10数字2位数字3
纯系统ISO 7064, MOD 661-26字母2位字母4
纯系统ISO 7064, MOD 1271-36字母数字2位数字或字母5
混合系统ISO 7064, MOD 11,10数字1位数字6
混合系统ISO 7064, MOD 27,26字母1位字母7
混合系统ISO 7064, MOD 37,36字母数字1位数字或字母8

表格中可见,校验字符系统,包括纯系统和混合系统。使用一个模数的称为纯系统,系统名称中MOD后第1个数字是模数,第2个数字是基数;使用两个模数的称为混合系统,系统名称中MOD后的2个数字都是模数。

纯系统

纯系统又包括使用一个校验字符和使用两个校验字符。使用一个校验字符的纯系统与使用两个校验字符的纯系统本质上是相同的,都遵守校验公式:

  •  - 包括校验字符在内的字符串的字符个数;
  •  - 表示从右至左包括校验码字符在内的字符的位置索引,即最右边的字符
  •  - 表示第i位置上字符值;
  • - 基数;
  • - 模数。

只不过,使用一个校验字符的纯系统与使用两个校验字符的纯系统在计算校验字符的方式上略有不同:

  • 使用一个校验字符的纯系统的校验字符计算公式

其中是校验字符,也可以使用替代,

  • 使用两个校验字符的纯系统的校验字符计算公式


    其中是校验字符, 也可以使用 替代,

纯系统有两种基本的计算方法,纯系统递归法和纯系统多项式法:

  • 递归法
    从左往右计算:

  • 多项式法
    使用公式表示:

其实递归法的计算完全展开,得到的也就是多项式法,所以两种计算方法产生相同的结果。

混合系统

混合系统使用一个校验字符,遵守校验公式:

  •  - 包括校验字符在内的字符串的字符个数;
  •  - 表示从右至左包括校验码字符在内的字符的位置索引,即最右边的字符i=1
  •  - 表示第i位置上字符值;
  •  - 两个模数;
  •  - 除以后的余数,如果其值为0,则用 代替;
  •  - 除以后的余数,在经过上述处理后,余数绝不会为0。

上述公式本身就是递归法,无法展开,因此混合系统仅支持递归法计算,不支持多项式法。

最后,附上大家喜闻乐见的代码。

package com.godson.util;import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** ISO7064工具类* <p>* 使用ISO7064规范中定义的校验字符系统进行字符串的校验以及生成校验字符* </p>* */
public class ISO7064Util {/*** ISO7064规范中定义的校验字符系统* <p>* <li>ISO 7064, MOD 11-2使用 {@link #ISO_7064_MOD_11_2}表示* </li>* <li>ISO 7064, MOD 37-2使用{@link #ISO_7064_MOD_37_2}表示</li>* <li>ISO 7064, MOD 97-10使用{@link #ISO_7064_MOD_97_10}* 表示</li>* <li>* ISO 7064, MOD 661-26使用 {@link #ISO_7064_MOD_661_26}表示* </li>* <li>ISO 7064, MOD 1271-36使用* {@link #ISO_7064_MOD_1271_36}表示</li>* <li>ISO 7064, MOD 11,10使用* {@link #ISO_7064_MOD_11_HYBRID_10}表示</li>* <li>ISO 7064, MOD 27,26使用* {@link #ISO_7064_MOD_27_HYBRID_26}表示</li>* <li>ISO 7064, MOD 37,36使用* {@link #ISO_7064_MOD_37_HYBRID_36}表示</li>*/public enum Designation {/** ISO 7064, MOD 11-2 */ISO_7064_MOD_11_2,/** ISO 7064, MOD 37-2 */ISO_7064_MOD_37_2,/** ISO 7064, MOD 97-10 */ISO_7064_MOD_97_10,/** ISO 7064, MOD 661-26 */ISO_7064_MOD_661_26,/** ISO 7064, MOD 1271-36 */ISO_7064_MOD_1271_36,/** ISO 7064, MOD 11,10 */ISO_7064_MOD_11_HYBRID_10,/** ISO 7064, MOD 27,26 */ISO_7064_MOD_27_HYBRID_26,/** ISO 7064, MOD 37,36 */ISO_7064_MOD_37_HYBRID_36}/*** 计算校验字符* * @param withoutCheckCharacterString 不含校验字符的字符串* @param designation 校验字符系统* @return 校验字符* @throws IllegalArgumentException*             如果字符串不匹配对应校验字符系统的正则表达式*/public static String computeCheckCharacter(String withoutCheckCharacterString, Designation designation) {// 检查字符串是否匹配对应校验字符系统的正则表达式if (!RegexMatcher.withoutCheckCharacterStringIsMatch(withoutCheckCharacterString, designation)) {throw new IllegalArgumentException();}// 计算校验字符return CheckCharacterComputor.compute(withoutCheckCharacterString,designation);}/*** 校验字符串* * @param withCheckCharacterString 含校验字符的字符串* @param designation 校验字符系统* @return true - 校验通过<br>*         false-校验不通过* @throws IllegalArgumentException*             如果字符串不匹配对应校验字符系统的正则表达式*/public static boolean checkString(String withCheckCharacterString,Designation designation) {// 检查字符串是否匹配对应校验字符系统的正则表达式if (!RegexMatcher.withCheckCharacterStringIsMatch(withCheckCharacterString, designation)) {throw new IllegalArgumentException();}// 校验字符串return CheckCharacterSystemValidator.validate(withCheckCharacterString,designation);}/*** 正则表达式匹配器* <p>* 检查字符串是否匹配对应校验字符系统的正则表达式* </p>* <table border="1">* <tr>* <th>系统名称</th>* <th>适用范围</th>* <th>校验码数目及类型</th>* </tr>* <tr>* <td>ISO 7064, MOD 11-2</td>* <td>数字</td>* <td>1位数字或附加符X</td>* </tr>* <tr>* <td>ISO 7064, MOD 37-2</td>* <td>字母数字</td>* <td>1位数字或字母或附加符*</td>* </tr>* <tr>* <td>ISO 7064, MOD 97-10</td>* <td>数字</td>* <td>2位数字</td>* </tr>* <tr>* <td>ISO 7064, MOD 661-26</td>* <td>字母</td>* <td>2位字母</td>* </tr>* <tr>* <td>ISO 7064, MOD 1271-36</td>* <td>字母数字</td>* <td>2位数字或字母</td>* </tr>* <tr>* <td>ISO 7064, MOD 11,10</td>* <td>数字</td>* <td>1位数字</td>* </tr>* <tr>* <td>ISO 7064, MOD 27,26</td>* <td>字母</td>* <td>1位字母</td>* </tr>* <tr>* <td>ISO 7064, MOD 37,36</td>* <td>字母数字</td>* <td>1位数字或字母</td>* </tr>* </table>*/private static class RegexMatcher {/*** 检查不含校验字符的字符串是否匹配对应校验字符系统的正则表达式* * @param withoutCheckCharacterString 不含校验字符的字符串* @param designation 校验字符系统* @return true - 匹配<br>*         false - 不匹配*/static boolean withoutCheckCharacterStringIsMatch(String withoutCheckCharacterString, Designation designation) {return regexMatch(withoutCheckCharacterString,REGEX_MAPPING_WITHOUT_CHECK_CHARACTER_STRING.get(designation));}/*** 检查有校验字符的字符串是否匹配对应校验字符系统的正则表达式* * @param withCheckCharacterString 含校验字符的字符串* @param designation 校验字符系统* @return true - 匹配<br>*         false - 不匹配*/static boolean withCheckCharacterStringIsMatch(String withCheckCharacterString, Designation designation) {return regexMatch(withCheckCharacterString,REGEX_MAPPING_WITH_CHECK_CHARACTER_STRING.get(designation));}/** 数字正则表达式 */static final String REGEX_NUMBERIC_STRINGS = "^[0-9]+$";/** 含补充校验字符X的数字正则表达式 */static final String REGEX_NUMBERIC_STRINGS_WITH_SUPPLEMENTARY_CHECK_CHARACTER = "^[0-9]+[0-9X]$";/** 字母正则表达式 */static final String REGEX_ALPHABETIC_STRINGS = "^[A-Z]+$";/** 字母数字正则表达式 */static final String REGEX_ALPHANUMBERIC_STRINGS = "^[0-9A-Z]+$";/** 含补充校验字符*的字母数字表达式 */static final String REGEX_ALPHANUMBERIC_STRINGS_WITH_SUPPLEMENTARY_CHECK_CHARACTER = "^[0-9A-Z]+[0-9A-Z*]$";/** 校验字符系统对应的正则表达式(不含校验字符) */@SuppressWarnings("serial")static final Map<Designation, String> REGEX_MAPPING_WITHOUT_CHECK_CHARACTER_STRING = new HashMap<Designation, String>() {{put(Designation.ISO_7064_MOD_11_2, REGEX_NUMBERIC_STRINGS);put(Designation.ISO_7064_MOD_37_2, REGEX_ALPHANUMBERIC_STRINGS);put(Designation.ISO_7064_MOD_97_10, REGEX_NUMBERIC_STRINGS);put(Designation.ISO_7064_MOD_661_26, REGEX_ALPHABETIC_STRINGS);put(Designation.ISO_7064_MOD_1271_36,REGEX_ALPHANUMBERIC_STRINGS);put(Designation.ISO_7064_MOD_11_HYBRID_10,REGEX_NUMBERIC_STRINGS);put(Designation.ISO_7064_MOD_27_HYBRID_26,REGEX_ALPHABETIC_STRINGS);put(Designation.ISO_7064_MOD_37_HYBRID_36,REGEX_ALPHANUMBERIC_STRINGS);}};/** 校验字符系统对应的正则表达式(含校验字符) */@SuppressWarnings("serial")static final Map<Designation, String> REGEX_MAPPING_WITH_CHECK_CHARACTER_STRING = new HashMap<Designation, String>() {{put(Designation.ISO_7064_MOD_11_2,REGEX_NUMBERIC_STRINGS_WITH_SUPPLEMENTARY_CHECK_CHARACTER);put(Designation.ISO_7064_MOD_37_2,REGEX_ALPHANUMBERIC_STRINGS_WITH_SUPPLEMENTARY_CHECK_CHARACTER);put(Designation.ISO_7064_MOD_97_10, REGEX_NUMBERIC_STRINGS);put(Designation.ISO_7064_MOD_661_26, REGEX_ALPHABETIC_STRINGS);put(Designation.ISO_7064_MOD_1271_36,REGEX_ALPHANUMBERIC_STRINGS);put(Designation.ISO_7064_MOD_11_HYBRID_10,REGEX_NUMBERIC_STRINGS);put(Designation.ISO_7064_MOD_27_HYBRID_26,REGEX_ALPHABETIC_STRINGS);put(Designation.ISO_7064_MOD_37_HYBRID_36,REGEX_ALPHANUMBERIC_STRINGS);}};static boolean regexMatch(String inputString, String regex) {Pattern pattern = Pattern.compile(regex);Matcher matcher = pattern.matcher(inputString);return matcher.matches();}}/** 适用于数字的校验字符系统的数值对应表 */private static final String[] NUMBERIC_STRINGS = { "0", "1", "2", "3", "4","5", "6", "7", "8", "9", "X" };/** 适用于字母的校验字符系统的数值对应表 */private static final String[] ALPHABETIC_STRINGS = { "A", "B", "C", "D","E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q","R", "S", "T", "U", "V", "W", "X", "Y", "Z" };/** 适用于字母数字的校验字符系统的数值对应表 */private static final String[] ALPHANUMBERIC_STRINGS = { "0", "1", "2", "3","4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G","H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T","U", "V", "W", "X", "Y", "Z", "*" };/*** 校验字符系统验证器*/private static class CheckCharacterSystemValidator {static boolean validate(String inputString, Designation designation) {switch (designation) {case ISO_7064_MOD_11_2:case ISO_7064_MOD_37_2:case ISO_7064_MOD_97_10:case ISO_7064_MOD_661_26:case ISO_7064_MOD_1271_36:return validatePureSystem(inputString, designation);case ISO_7064_MOD_11_HYBRID_10:case ISO_7064_MOD_27_HYBRID_26:case ISO_7064_MOD_37_HYBRID_36:return validateHybridSystem(inputString, designation);default:return false;}}/*** 纯系统校验*/static boolean validatePureSystem(String inputString,Designation designation) {int M = 0; // 模数int r = 0; // 基数List<String> mapping = null;switch (designation) {case ISO_7064_MOD_11_2:M = 11;r = 2;mapping = Arrays.asList(NUMBERIC_STRINGS);break;case ISO_7064_MOD_37_2:M = 37;r = 2;mapping = Arrays.asList(ALPHANUMBERIC_STRINGS);break;case ISO_7064_MOD_97_10:M = 97;r = 10;mapping = Arrays.asList(NUMBERIC_STRINGS);break;case ISO_7064_MOD_661_26:M = 661;r = 26;mapping = Arrays.asList(ALPHABETIC_STRINGS);break;case ISO_7064_MOD_1271_36:M = 1271;r = 36;mapping = Arrays.asList(ALPHANUMBERIC_STRINGS);break;default:return false;}char[] strArray = inputString.toCharArray();int S = 0;int n = strArray.length;for (int i = 1; i <= n; i++) {// 注意这里不要使用Math的pow方法S += mapping.indexOf(String.valueOf(strArray[i - 1]))* BigInteger.valueOf(r).pow(n - i).mod(BigInteger.valueOf(M)).intValue();}return S % M == 1;}/*** 混合系统校验*/static boolean validateHybridSystem(String inputString,Designation designation) {int M = 0; // 模数1List<String> mapping = null;switch (designation) {case ISO_7064_MOD_11_HYBRID_10:M = 10;mapping = Arrays.asList(NUMBERIC_STRINGS);break;case ISO_7064_MOD_27_HYBRID_26:M = 26;mapping = Arrays.asList(ALPHABETIC_STRINGS);break;case ISO_7064_MOD_37_HYBRID_36:M = 36;mapping = Arrays.asList(ALPHANUMBERIC_STRINGS);break;default:return false;}int Mplus1 = M + 1; // 模数2char[] strArray = inputString.toCharArray();int S = M + mapping.indexOf(String.valueOf(strArray[0]));int P = 0;for (int i = 1; i < strArray.length; i++) {P = ((S % M == 0 ? M : S % M) * 2) % Mplus1;S = P + mapping.indexOf(String.valueOf(strArray[i]));}return S % M == 1;}}/*** 校验字符生成器*/private static class CheckCharacterComputor {static String compute(String inputString, Designation designation) {switch (designation) {case ISO_7064_MOD_11_2:case ISO_7064_MOD_37_2:return polynomialMethod4PureSystemWith1CheckChar(inputString, designation);case ISO_7064_MOD_97_10:case ISO_7064_MOD_661_26:case ISO_7064_MOD_1271_36:return polynomialMethod4PureSystemWith2CheckChar(inputString, designation);case ISO_7064_MOD_11_HYBRID_10:case ISO_7064_MOD_27_HYBRID_26:case ISO_7064_MOD_37_HYBRID_36:return recursiveMethod4HybridSystemWith1CheckChar(inputString, designation);default:return null;}}/*** 通过多项式法计算纯系统一位校验字符*/static String polynomialMethod4PureSystemWith1CheckChar(String str,Designation designation) {int M = 0; // 模数int r = 0; // 基数List<String> mapping = null;switch (designation) {case ISO_7064_MOD_11_2:M = 11;r = 2;mapping = Arrays.asList(NUMBERIC_STRINGS);break;case ISO_7064_MOD_37_2:M = 37;r = 2;mapping = Arrays.asList(ALPHANUMBERIC_STRINGS);break;default:break;}char[] strArray = str.toCharArray();int S = 0;int n = strArray.length + 1;for (int i = n; i >= 2; i--) {// 注意这里不要使用Math的pow方法S += mapping.indexOf(String.valueOf(strArray[n - i]))* BigInteger.valueOf(r).pow(i - 1).mod(BigInteger.valueOf(M)).intValue();}return mapping.get((M + 1 - S % M) % M);}/*** 通过多项式法计算纯系统二位校验字符*/static String polynomialMethod4PureSystemWith2CheckChar(String str,Designation designation) {int M = 0; // 模数int r = 0; // 基数List<String> mapping = null;switch (designation) {case ISO_7064_MOD_97_10:M = 97;r = 10;mapping = Arrays.asList(NUMBERIC_STRINGS);break;case ISO_7064_MOD_661_26:M = 661;r = 26;mapping = Arrays.asList(ALPHABETIC_STRINGS);break;case ISO_7064_MOD_1271_36:M = 1271;r = 36;mapping = Arrays.asList(ALPHANUMBERIC_STRINGS);break;default:break;}char[] strArray = str.toCharArray();int S = 0;int n = strArray.length + 2;for (int i = n; i >= 3; i--) {// 注意这里不要使用Math的pow方法S += mapping.indexOf(String.valueOf(strArray[n - i]))* BigInteger.valueOf(r).pow(i - 1).mod(BigInteger.valueOf(M)).intValue();}return mapping.get(((M + 1 - S % M) % M) / r)+ mapping.get(((M + 1 - S % M) % M) % r);}/*** 通过递归法法计算混合系统一位校验字符*/static String recursiveMethod4HybridSystemWith1CheckChar(String inputString, Designation designation) {int M = 0; // 模数1List<String> mapping = null;switch (designation) {case ISO_7064_MOD_11_HYBRID_10:M = 10;mapping = Arrays.asList(NUMBERIC_STRINGS);break;case ISO_7064_MOD_27_HYBRID_26:M = 26;mapping = Arrays.asList(ALPHABETIC_STRINGS);break;case ISO_7064_MOD_37_HYBRID_36:M = 36;mapping = Arrays.asList(ALPHANUMBERIC_STRINGS);break;default:break;}int Mplus1 = M + 1; // 模数2char[] strArray = inputString.toCharArray();int S = 0;int P = M;int n = strArray.length + 1;for (int i = n; i >= 2; i--) {S = P + mapping.indexOf(String.valueOf(strArray[n - i]));P = ((S % M == 0 ? M : S % M) * 2) % Mplus1;}return mapping.get((M + 1 - P % M) % M);}}
}

参考资料

  1. 中华人民共和国居民身份证法
  2. 中华人民共和国国家标准 GB/T 2260-2007 中华人民共和国行政区划代码
  3. 中华人民共和国国家标准 GB 11643-1999 公民身份证号码
  4. 中华人民共和国国家标准 GB/T 17710-1999 数据处理 校验码系统
  5. 中华人民共和国国家标准 GB/T 17710-2008 信息技术 安全技术 校验字符系统
  6. ISO 7064:1983 Data processing - Check character systems
  7. ISO/IEC 7064:2003 Information technology - Security techniques - Check character systems

 


http://chatgpt.dhexx.cn/article/kpcSDZ4j.shtml

相关文章

基于Python实现身份证号码验证

基于Python实现身份证号码验证 摘要: 该设计主要使用python语言来实现身份证号验证程序。它运用 tkinter模块生成GUI界面。当用户输入身份证号&#xff0c;按下检查按钮&#xff0c;即可判断身份证号是否正确。该程序简洁&#xff0c;灵活&#xff0c;执行效率高。 关键词: 身…

java验证身份证号码的合格性

中国居民身份证校验码算法步骤如下: 将身份证号码前面的17位数分别乘以不同的系数。从第一位到第十七位的系数分别为: 7&#xff0d;9&#xff0d;10&#xff0d;5&#xff0d;8&#xff0d;4&#xff0d;2&#xff0d;1&#xff0d;6&#xff0d;3&#xff0d;7&#xff0d;9&…

Python+Opencv身份证号码区域提取及识别

前端时间智能信息处理实训&#xff0c;我选择的课题为身份证号码识别&#xff0c;对中华人民共和国公民身份证进行识别&#xff0c;提取并识别其中的身份证号码&#xff0c;将身份证号码识别为字符串的形式输出。现在实训结束了将代码发布出来供大家参考&#xff0c;识别的方式…

身份证号码案例

我国的居民身份证号码&#xff0c;由由十七位数字本体码和一位数字校验码组成。请定义方法判断用户输入的身份证号码是否合法&#xff0c;并在主方法中调用方法测试结果。规则为&#xff1a;号码为18位&#xff0c;不能以数字0开头&#xff0c;前17位只可以是数字&#xff0c;最…

Python之身份证号码的校验

该文章已同步收录到我的博客网站&#xff0c;欢迎浏览我的博客网站&#xff0c;xhang’s blog 问题描述&#xff1a; 中华人民共和国居民身份证号码由17 位数字和1位校验码组成。 其中&#xff0c;前6位为所在地编号&#xff0c;第7~14 位为出生年月日&#xff0c;第15~17位为登…

JAVA 身份证号码的验证

一、身份证结构和形式 在通用的身份证号码有15位的和18位的&#xff1b; 15位身份证号码各位的含义: 1、1-2位省、自治区、直辖市代码&#xff1b; 2、3-4位地级市、盟、自治州代码&#xff1b; 3、5-6位县、县级市、区代码&#xff1b; 4、7-12位出生年月日,比如670401代…

等价类划分测试—身份证

目录 0.题目要求&#xff1a; 注意&#xff1a;一个测试用例只能覆盖一个无效等价类&#xff0c;但可以覆盖尽可能多的前面未覆盖到的有效等价类。 1.划分等价类 1.1有效等价类 1.2无效等价类 2.测试用例&#xff1a; 0.题目要求&#xff1a; 针对国内18位身份证号码验证…

二维码文件分析

将二维码保存&#xff0c;进行解码 进行base64解码,网址&#xff1a;https://www.sojson.com/base64.html。第一次解码&#xff1a;6LZ5Liq5bCx5piv6aqM6KB56CB77yaQkozNVVCNVNZNg 第二次解码&#xff1a;这个就是验证码&#xff1a;BJ35UB5SY6 得到key

Base64[再谈Base64] -- 附练习源代码

我打赌当你见到Base64这个词的时候你会觉得在哪里见过&#xff0c;因为在你能够上网看到这篇文章的时候你已经在后台使用它了。如果您对二进制数有所了解&#xff0c;你就可以开始读它了。 打开一封Email&#xff0c;查看其原始信息&#xff08;您可以通过收取、导出该邮件用文…

KgoUI(3) 之 vue + Sass

框架源代码&#xff1a;码云 直接上步骤&#xff1a; 第一&#xff1a;sass需要的模块 &#xff08;没有安装cnpm 就用 npm咯&#xff09; cnpm install --save-dev sass-loader cnpm install --save-dev node-sass cnpm install --save-dev sass-resources-loader…

安卓项目实战之强大的网络请求框架okGo使用详解(四):Cookie的管理

Cookie概念相关 具体来说cookie机制采用的是在客户端保持状态的方案&#xff0c;而session机制采用的是在服务器端保持状态的方案。同时我们也看到&#xff0c;由于采用服务器端保持状态的方案在客户端也需要保存一个标识&#xff0c;所以session机制是需要借助于cookie机制来…

Windows下安装Ginkgo测试框架

终端执行命令 #切换至GO安装路径 cd F:\Go\goProject\src\github.com F:#安装Ginkgo及其附加库 go get github.com/onsi/ginkgo/ginkgo go get github.com/onsi/gomega结果安装其附加库时开始报错 package golang.org/x/net/html/charset: unrecognized import path "g…

HTTPSConnectionPool(host=‘files.pythonhosted.org‘, port=443): Read timed out.

python 下载第三方库的时候一直报错怎么办&#xff0c; pip --default-timeout1000 install -U pip 尝试了延时操作依然不行&#xff0c;不能获取 这种情况有可能是你开了VPN或者是其他的软件&#xff0c;退出下载即可

Go:构建应用程序的10大框架

文章目录 简介一、CLI 命令(spf13/cobra)二、配置读取器(spf13/viper)三、Web 框架(labstack/echo)四、依赖注入(uber-go/fx)五、Swagger Generator, UI 和 Validation1. Swagger generator (swaggo/swag)2. Swagger UI (swaggo/echo-swagger)3. Swagger validation (go-swagge…

KgoUI(2) 之 vue + layui

框架源代码&#xff1a;码云 我接触layui 已经快2年多了&#xff08;Layui刚出的时候我就开始关注了&#xff09;&#xff0c;vue 和 layui并不是天生一对&#xff0c;elementui 和vue配合更加亲密无间。我认为layui的弹层layer是当前前端最好的弹层。 这里依旧选择layu…

2021年全国大学生网络安全邀请赛暨第七届“东华杯“上海市大学生网络安全大赛Writeup

2021年全国大学生网络安全邀请赛暨第七届"东华杯"上海市大学网格全大赛Writeup Misc checkin 题目给了AGYAbABhAGcAewBkAGgAYgBfADcAdABoAH0- 是UTF-7编码&#xff0c;解码得到flag flag为&#xff1a; flag{dhb_7th}project 下载附件&#xff0c;解压之后发现这…

玩转Kafka—SpringGo整合Kafka

玩转Kafka—Spring整合Kafka 1 新建Spring Boot项目&#xff0c;增加依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependenc…

视图单行子查询返回mysql,Oracle命令整理 - osc_sj1kgo4z的个人空间 - OSCHINA - 中文开源技术交流社区...

常用命令 1 sqlplus scott/tiger192.168.47.10:1521/orcl后面不要加&#xff1b; sqlplus sys/oracle as sysdba 【密码认证】 sqlplus用户名任意/密码任意as sysdba 【主机认证】 2 spool d:\基本查询.txt 录屏开始 spool off …

MLX90316KGO-BDG-100-RE传感器 旋转位置 角度测量

介绍 MLX90316是Tria⊗is旋转位置传感器&#xff0c;提供在设备表面旋转的小偶极磁铁(轴端磁铁)的绝对角位置。 得益于其表面的集成磁集中器(IMC)&#xff0c;单片设备以非接触式方式感知应用磁通量密度的水平分量。 这种独特的传感原理应用于旋转位置传感器&#xff0c;可在机…