跳到主要内容
实用工具2026-10-30李帅5 分钟阅读

身份证校验位怎么算:GB 11643 的 MOD 11-2 算法与结尾 X 的由来

做实名表单、清洗一批实名数据、或者排查「为什么用户的身份证号总是校验不过」——你迟早会撞上那几个经典问题:结尾的 X 存不进 int 字段、小写 x 校验不过、有人身份证 15 位。本文把 18 位身份证号的结构、校验位算法和真实数据里的脏法一次讲透,所有结论可以在 身份证校验工具 里当场验证——纯浏览器本地计算,贴任何号码都不出设备。

18 位逐段拆解

位置字段说明
1–2省份11 北京、31 上海、44 广东……标准表里还预留了 71 台湾、81 香港、82 澳门
3–6市/县区划与省份合成 6 位登记区划码
7–14出生日期YYYYMMDD,必须是真实日历日期(2 月 30 日这类在校验位之前就该被拒)
15–17顺序码同区划同生日内的分配序号;第 17 位奇偶即性别位——奇男偶女
18校验码前 17 位按 ISO 7064 MOD 11-2 计算,值为 10 时写作 X

两个比校验位更便宜的拒绝动作:出生日期必须真实存在、省份前缀必须真实存在。这两行代码拦下的垃圾数据往往比校验位多——因为它们拦的是语义错误,校验位拦的是转录错误。

校验位算法:加权求和取模

前 17 位各自乘固定位权重求和,模 11 后折返:

权重表 = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]

v = (12 - (Σ 数字 × 权重) mod 11) mod 11
校验码 = v 的十进制写法(v=10 时写 X)

这张权重表是 2 的幂模 11、从右往左数:第 17 位乘 2¹、第 16 位乘 2²……周期 10 循环(2¹⁰ ≡ 1 mod 11)。和统一社会信用代码是同一族构造——那边是 3 的幂 mod 31,这边是 2 的幂 mod 11,都用了「素数模 + 原根底数」的加权序列。收益也一样:每个权重都是非零剩余,任何单数字替换必被抓;相邻权重永远不同(比值是 2 或其逆,不可能 ≡ 1 mod 11),任何相邻换位也必被抓。这点强于银行卡的 Luhn 算法——Luhn 会漏掉 0/9 这类特定相邻换位。

手算一遍。取 17 位主体 11010119900815001(北京东城 110101,1990-08-15,顺序码 001):

  • 前四位贡献:1×7 + 1×9 + 0×10 + 1×5 = 21;
  • 17 位总和:199;
  • 199 mod 11 = 1;12 − 1 = 11 → mod 11 = 0;校验位为 0。

完整号码 110101199008150010。把顺序码改成 002——区划生日全同、看起来完全合法——正确的校验位就变了,原来的 0 立即被判 checksum 错误。整条链路(含生日与性别解析)可在校验工具里复现。

结尾 X 的三条处理纪律

校验值算出 10 时没有单个十进制数字可写,标准规定记作 X。实务上三条:

  1. 入库必须是文本列。大约 1/11 的号码以 X 结尾,int 列物理上存不下它们——静默截断或导入报错的经典事故源。已有系统还在用数字列的,迁移时先补这一课。
  2. 校验前 toUpperCase() + NFKC 归一化。小写 x 是转录噪声,全角 X(U+FF38)是 PDF/输入法复制 artifact——都是可修复输入,别用「格式错误」一刀切。
  3. 永远不要「重算校验位并覆写」。那会制造一个格式合法但查无此人的号码,让污染对所有下游校验隐形。校验不过就转人工。

真实数据里最常见的五种脏法

症状常见原因处置
小写 x / 全角 X输入法、PDF、OCR转大写 + NFKC 后重校
O 混入数字段OCR「自动纠错」(O 原是 0)仅修复场景映射 O→0,禁止一刀切
只有 15 位1999 年前的旧版号(无世纪位、没有校验位)结构性不同,走升级登记流程,别套 18 位校验
生日 2 月 30 日 / 未来日期生日位敲错校验位之前就拒,报错要说清是哪个字段
校验通过但人证不符复制错行 / 手滑填了别人的任何校验位都管不了——见下节边界

校验能保证什么、不能保证什么

校验位通过的号码只是格式合法。它不能证明号码真实存在、属于提交者本人、或与姓名匹配——那是公安验证服务的职责,本站工具刻意不做这类查询,也因此整段计算都在浏览器内完成,贴真实号码无泄露风险。给下游系统造测试数据时,用中国格式测试数据生成器:区划形状真实、生日真实、校验位正确,且确定是合成号。

隐私提醒顺带说透:身份证号是最高敏感级 PII,任何在线校验器用之前先开 DevTools Network 面板看一眼——上传式的一票否决。

FAQ

X 结尾和出生日期有关系吗? 没有。X 只是校验值算到 10 的写法,约占全部号码的 1/11,与生日无关。

港台澳居民用这个 18 位格式吗? 不用,三地各有自己的证件格式。标准表预留 71/81/82 只是区划占位,实际号码体系不同。本文只覆盖大陆居民身份证。

为什么有些系统里身份证号占 19 个字符? 要么补了空格要么拼了别的字段。号码就是 18 字符,末位可能是 X。

15 位的老号码还能校验吗? 不能按 18 位规则校验——它没有校验位、出生日期没有世纪位。正确姿势是走升级流程换发,代码里识别出来单独标记即可。

同系列:中国标识符

实现注记

工具源码里是一份权重表 + 一张校验映射表,外加一个值得抄的细节:生日真实性用 UTC 往返检查(new Date(Date.UTC(y, m-1, d)) 必须落回同一天),不用月份天数查找表就能拦住 2 月 30 日。我们在野见过的一类 bug:校验器只做大写转换不做 NFKC,全角数字 1990 触发的报错是莫名其妙的「字符集错误」而不是「可修复的全角输入」。这些行为全部由 round-trip 测试钉死(生成 N 个合法号 → 全部通过 → 逐位篡改 → 断言拒绝)。