Lnhn算法

Luhn算法

Luhn算法,也称为“模10”算法,是一种简单的校验和(Checksum)算法,一般用于验证身份识别号
例如信用卡号码、国际移动设备识别码(International Mobile Equipment Identity,缩写为IMEI),美国供应商识别号码,加拿大社会保险号码,以色列身份证号码,希腊社会安全号码等。
Luhn算法在ISO/IEC 7812-1中定义,它不是一种安全的加密哈希函数,设计它的目的只是防止意外出错而不是恶意攻击,即我们常说的防君子不防小人。
使用Luhn算法校验的步骤:
1.从右边第1个数字(校验数字)开始偶数位乘以2;
2.把步骤1种获得的乘积的各位数字与原号码中未乘2的各位数字相加;
3.如果步骤2得到的总和模10为0,则校验通过。

/**

  • Luhn算法工具类
  • Luhn算法在ISO/IEC 7812-1中定义,使用Luhn算法进行字符串的校验以及生成校验数字

*/
public class LuhnUtil {

/**
 * 校验字符串
 * <p>
 * 1. 从右边第1个数字(校验数字)开始偶数位乘以2;<br>
 * 2. 把在步骤1种获得的乘积的各位数字与原号码中未乘2的各位数字相加;<br>
 * 3. 如果在步骤2得到的总和模10为0,则校验通过。
 * </p>
 * 
 * @param withCheckDigitString 含校验数字的字符串
 * @return true - 校验通过<br>
 *         false-校验不通过
 * @throws IllegalArgumentException 如果字符串为空或不是8~19位的数字
 */
public static boolean checkString(String withCheckDigitString) {
    if (withCheckDigitString == null) {
        throw new IllegalArgumentException();
    }
    // 6位IIN+最多12位自定义数字+1位校验数字
    // 注意ISO/IEC 7812-1:2017中重新定义8位IIN+最多10位自定义数字+1位校验数字
    // 这里为了兼容2017之前的版本,使用8~19位数字校验
    if (!withCheckDigitString.matches("^\\d{8,19}$")) {
        throw new IllegalArgumentException();
    }
    return sum(withCheckDigitString) % 10 == 0;
}

/**
 * 计算校验数字
 * <p>
 * 1. 从右边第1个数字(校验数字)开始偶数位乘以2;<br>
 * 2. 把在步骤1种获得的乘积的各位数字与原号码中未乘2的各位数字相加;<br>
 * 3. 用10减去在步骤2得到的总和模10,得到校验数字。
 * </p>
 * 
 * @param withoutCheckDigitString 不含校验数字的字符串
 * @return 校验数字
 * @throws IllegalArgumentException 如果字符串为空或不是7~18位的数字
 */
public static int computeCheckDigit(String withoutCheckDigitString) {
    if (withoutCheckDigitString == null) {
        throw new IllegalArgumentException();
    }
    // 6位IIN+最多12位自定义数字
    // 注意ISO/IEC 7812-1:2017中重新定义8位IIN+最多10位自定义数字
    // 这里为了兼容2017之前的版本,使用7~18位数字校验
    if (!withoutCheckDigitString.matches("^\\d{7,18}$")) {
        throw new IllegalArgumentException();
    }
    // 因为是不含校验数字的字符串,为了统一sum方法,在后面补0,不会影响计算
    return 10 - sum(withoutCheckDigitString + "0") % 10;
}

/**
 * 根据Luhn算法计算字符串各位数字之和
 * <p>
 * 1. 从右边第1个数字(校验数字)开始偶数位乘以2;<br>
 * 2. 把在步骤1种获得的乘积的各位数字与原号码中未乘2的各位数字相加。<br>
 * </p>
 * 
 * @param str
 * @return
 */
private static int sum(String str) {
    char[] strArray = str.toCharArray();
    int n = strArray.length;
    int sum = 0;
    for (int i = n; i >= 1; i--) {
        int a = strArray[n - i] - '0';
        // 偶数位乘以2
        if (i % 2 == 0) {
            a *= 2;
        }
        // 十位数和个位数相加,如果不是偶数位,不乘以2,则十位数为0
        sum = sum + a / 10 + a % 10;
    }
    return sum;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值