[安全开发]日志敏感信息检测-2-银行卡
Posted 白夜鸦羽
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[安全开发]日志敏感信息检测-2-银行卡相关的知识,希望对你有一定的参考价值。
前言
接上一篇文章:[安全开发]日志敏感信息检测-1-身份证
银行卡号码格式
银行卡号码由14至19位数字组成,储蓄卡一般是19位、17位和16位,信用卡一般是16位,其中:
- 前n位:发卡行识别码,用来标识哪个银行发行的卡,在本文中统一简称为“卡bin”
- 中间位:个人账户标识,由发卡行自己定义,最多12位
- 末位:校验码,由前面的数字采用Luhn算法计算得出
正则提取
首先通过正则,进行简单的筛选,从日志中提取疑似银行卡号码的数字。
\\W\\d14,19\\W
正则说明
\\W
:匹配非单词字符,与"[^A-Za-z0-9_]"等效\\d14,19
:匹配14至19位数字
宽进:在上面的正则表达式里,我们用了十分宽松的正则来匹配银行卡号码,只要是14至19位的数字,就都匹配上,这样能保证所有疑似银行卡号码的数字都被找出来。
严出:通过上面正则命中的数字误报会很多,但没关系,再对这些数字进行银行码和校验码校验,能过滤掉绝大部分误报,筛选出真正的银行卡号码。
卡bin校验
银行卡卡bin的长度不固定,一般是6位,但也有短至2位,长至12位的。
我们可以将正则命中的数字,从卡bin长度、卡bin值、银行卡长度三个维度,与卡bin库进行对比,三个值都符合的情况下,最后进行校验码的校验。
银行卡卡bin库搬运:银行卡卡bin数据
校验码校验
前面说了,银行卡最后一位是校验码,由银行卡最后一位前面的所有数字计算得到,具体的计算算法这里不深究,感兴趣的读者,可以参考这篇博客:银行卡号的编码规则及校验
这里我们直接给出,银行卡校验码的校验算法的Java代码实现:
/**
* 银行卡校验码Luhm校验算法,校验成功则为银行卡卡号
*
* @param bankCardNo 银行卡号码
* @return true-校验成功;false-校验失败
*/
public static boolean bankCardNoCheck(String bankCardNo)
String num = bankCardNo.substring(0, bankCardNo.length() - 1);
char[] numArray = num.toCharArray();
int luhmSum = 0;
for (int i = numArray.length - 1, j = 0; i >= 0; i--, j++)
int k = numArray[i] - '0';
if (j % 2 == 0)
k *= 2;
k = k / 10 + k % 10;
luhmSum += k;
char checkNo = (luhmSum % 10 == 0) ? '0' : (char) ((10 - luhmSum % 10) + '0');
return bankCardNo.charAt(bankCardNo.length() - 1) == checkNo;
优化思考
通过上面的 正则提取+卡bin校验+校验码校验 三部曲,从日志中检测出的数字,基本99%是银行卡号码,准确率极高。但在海量日志的检测过程中,各种奇葩数据都有,还是会存在1%的误报的。
对于这1%的误报,有两个处理思路:
- 误报为偶然出现,且只出现过一两次,也没有其他类似特征的误报,则直接忽略即可
- 误报具有一定的特征,且多次出现,为同一类误报,则可以提取特征,针对性的制定白名单过滤。白名单推荐采用正则匹配进行过滤
以上是关于[安全开发]日志敏感信息检测-2-银行卡的主要内容,如果未能解决你的问题,请参考以下文章