Luhn算法(卢恩算法,也叫模10算法)
Luhn 是一种简单的校验算法,用来验证一串数字(银行卡号、身份证、IMEI、会员号等)是否格式合法,不能验证信息真假,只能检测输入错误(比如输错一位、相邻数字颠倒)。
由 IBM 工程师 Hans Peter Luhn 发明。
✅ 计算步骤
举个例子:卡号 49927398716(最后一位6是校验位)
规则:从右往左,从倒数第二位开始,隔一位乘以2
- 把数字从右向左编号:
4 9 9 2 7 3 9 8 7 1 | 6
从右数:第1位=6(校验位不动),第2位=1,第3位=7,第4位=8……
- 偶数位置(从右数第2、4、6…位)数字 ×2
如果乘完结果≥10,把十位和个位相加(等价于减9)
- 1×2 = 2
- 7×2 =14 → 1+4=5
- 8×2 =16 →1+6=7
- 3×2 =6
- 2×2 =4
- 9×2 =18 →1+8=9
- 奇数位置(除校验位外)数字保持原样:9、7、9、4
- 把上面所有结果相加,再加上最后的校验位:
总和如果 是10的倍数 → Luhn校验通过
校验公式:总和 mod 10 == 0
📌 快速总结
- 从最右边开始,跳过最后一位校验码;
- 向左依次,隔一个数字 ×2;
- 乘2后大于9,各位相加;
- 全部数字求和;
- 总和对10取余等于0,校验成功。
🎯 能检测什么,不能检测什么
✅ 可以发现:
- 单个数字输错(如
123→124) - 相邻两位数字交换(
12→21,大部分情况)
❌ 无法发现:
- 两个数字同时错,且错误刚好抵消校验和
- 完全编造但符合Luhn规则的号码(只能校验格式,不能验证号码真实存在)
Python 简易实现
def luhn_check(num_str):
total = 0
# 反向遍历
for i, c in enumerate(reversed(num_str)):
digit = int(c)
if i % 2 == 1: # 倒数第2、4...位 ×2
digit *= 2
if digit > 9:
digit -=9
total += digit
return total %10 ==0
print(luhn_check("49927398716")) # True
常见用途
银行卡号、信用卡号、IMEI手机序列号、加拿大社保号、部分平台编号校验。
如果你想要,我可以给你 JS / Java / C 版本的 Luhn 代码。
产品的防伪二维码建议用哪些算法生成?
防伪二维码配套校验算法选型说明
重点:二维码本身只是载体(存文本),二维码标准没有内置防伪算法。防伪能力来自二维码里面存储的数据 + 后台校验逻辑,二维码只是把这段信息展示给手机扫码端。
区分两个概念:
- 二维码编码:QR Code / Data Matrix 等,只是图形编码,不防伪;
- 防伪校验算法:用来生成防伪码、校验真伪、防篡改。
一、轻量场景:单品短码、本地校验(不需要联网也能初步校验)
1. Luhn 算法(你刚才问的)
✅ 优点:计算极快、数字串、人眼可打印,适合短序列号,检测录入错误;
❌ 缺点:安全强度很低,只能防手输错误,不能防伪造。攻击者很容易批量生成符合Luhn的号码。
👉 适用:辅助校验(防扫码输入错误),绝对不能单独作为防伪核心。
2. Mod 校验、加权和校验(类似Luhn变种)
和Luhn定位一致,仅做格式校验,不防破解。
小结:这类校验和类算法只能做格式合法性检查,不能防伪,只适合搭配主防伪算法一起用。
二、主流商用防伪方案(推荐)
方案A:带签名的防伪码(推荐,强防伪)
核心:非对称加密算法(RSA / ECC(SM2国密))
流程:
- 服务器(私钥)生成唯一流水号,对流水号做签名,把【流水号+签名】放到二维码;
- 手机扫码拿到内容,使用公钥验证签名;
- 一旦二维码里的内容被篡改,签名校验直接失败。
- SM2(国密):国内产品首选,合规,椭圆曲线,签名短,适合二维码存储空间有限场景;
- RSA:成熟,但是签名结果更长,二维码内容会变多;
✅ 优势:无法伪造有效签名,不需要把密钥暴露在包装/客户端;
✅ 搭配:二维码内容可以再加 SM3(国密哈希)辅助;
❌ 必须联网校验(或者内置公钥离线验签)。
方案B:哈希摘要方案(SM3 / SHA256)
适合:码体存储短摘要,原始数据在后台数据库
流程:
- 生成唯一序列号,后台计算
SM3(序列号+密钥盐); - 二维码存放:序列号+哈希摘要;
- 扫码后上传序列号,后台重新计算哈希比对。
✅ SM3国密,国内政企、品牌产品推荐;SHA256通用;
⚠️ 注意:哈希算法不能直接裸用!必须加盐(salt)。不加盐很容易彩虹表批量碰撞伪造。
缺点:纯哈希方案必须联网到服务器校验,不能离线校验;如果盐泄露,批量伪造风险上升。
方案C:一次性验证码(OTP类,较少用于包装防伪)
HMAC-SHA256,适合动态码,包装印刷静态防伪码一般不用。
三、工程组合推荐(实际项目常用组合)
✅ 推荐1(国内品牌产品首选,国密方案)
二维码存储内容:序列号 + SM2签名
- 防伪核心:SM2非对称签名(防篡改、防伪造)
- 可选附加:SM3做内部摘要,Luhn做前端格式校验(仅防输入错误)
适用:烟酒、化妆品、汽配、食品等实体商品防伪溯源。
✅ 推荐2(海外产品,无国密要求)
二维码:序列号 + ECDSA(secp256r1)签名
或者:序列号 + SHA256加盐哈希,联网校验。
四、避坑提醒(非常关键)
- ❌ 不要单独用 Luhn / CRC / 简单加权和做防伪!
CRC32、Luhn这类校验算法,攻击者可以批量生成大量合法号码,完全没有防伪能力,只能用来校验用户手动输错数字。
- ❌ 不要把密钥直接写在二维码里。
- ❌ 只靠二维码图片本身不能防伪,二维码图片可以拍照复制。
二维码防伪本质是:一物一码 + 后台数据库/数字签名校验;如果别人拍照复制二维码,多人扫码,后台可以标记“已被多次查询,疑似假冒”。
五、补充:二维码本身选型(载体)
防伪常用二维码类型:
- QR Code:最通用,手机微信/支付宝直接扫;
- Data Matrix:小尺寸,小标签(零件、药瓶)常用,容错强。
如果你告诉我场景:产品行业、是否要求国密、是否支持扫码联网、一个码最多允许多少字符,我可以直接给你一套完整的数据结构示例(二维码里面字符串格式)。