火车票上身份证脱敏的漏洞可以暴露你的身份证号

火车票大家都非常熟悉了,都做过火车,现在都是实名制购票,火车票上有你的身份证号和姓名等实名信息,其中身份证号被星号隐藏了四位,你以为就可以安全的丢弃吗?作为程序员的我想告诉你,其实通过程序可以很快的计算出你可能的身份证号码。

身份证号的构成

首先,我们需要了解身份证号是如何构成的。左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。六位地址码表明你是哪个省哪个市哪个区县的人,然后是生日,三个顺序码可以认为随机数,最后一位是校验位。校验位可以对前面的信息进行算法计算以后得出一个校验数字。

校验算法

根据前17位计算最后一位校验位的Java代码逻辑:

package net.renfei.util;

public class IDNumberUtil {
    private int[] weight = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};           //十七位数字本体码权重
    private char[] validate = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};      //mod11,对应校验码字符值
    public char getValidateCode(String id17) {
        int sum = 0;
        int mode = 0;
        for (int i = 0; i < id17.length(); i++) {
            sum = sum + Integer.parseInt(String.valueOf(id17.charAt(i))) * weight[i];
        }
        mode = sum % 11;
        return validate[mode];
    }
}

穷举脱敏部分

火车票

火车票上被脱敏的四位数是月份和日期,那么一年中大约有365天,就是365种可能性,我们先全部穷举出365种可能的前17位身份证号码,也就是从 0101到1231 的日期,通过程序很容易就可以遍历,然后计算最后一位校验位,如果满足就标记为疑似的身份证号,以上图”刘大明“的火车票为例,我的代码是:

package net.renfei.util;

import lombok.extern.slf4j.Slf4j;
import net.renfei.TestApplication;
import org.junit.Test;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Slf4j
public class IDNumberUtilTest extends TestApplication {
    @Test
    public void idNumberTest() throws ParseException {
        String idPre = "6221261980", idPost = "314", idCheck = "4";
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date birthDate = dateFormat.parse("1980-01-01");
        List<String> allID = new ArrayList<>();
        for (; ; ) {
            Calendar c = Calendar.getInstance();
            c.setTime(birthDate);
            c.add(Calendar.DAY_OF_MONTH, 1);// 今天+1天
            birthDate = c.getTime();
            if (c.get(Calendar.YEAR) == 1981) {
                break;
            }
            int month = c.get(Calendar.MONTH)+1;
            int day = c.get(Calendar.DAY_OF_MONTH);
            allID.add(idPre + (month < 10 ? "0" + month : month) + (day < 10 ? "0" + day : day) + idPost);
        }
        IDNumberUtil idNumberUtil = new IDNumberUtil();
        List<String> suspectedID = new ArrayList<>();
        for (String id : allID
        ) {
            log.info("== 检查:{}", id + idCheck);
            if (idCheck.equals(idNumberUtil.getValidateCode(id) + "")) {
                suspectedID.add(id + idCheck);
            }
        }
        for (String id : suspectedID
        ) {
            log.info("== 发现疑似ID:{}", id);
        }
    }
}

执行的结果是发现34个疑似身份证:

  • == 发现疑似ID:622126198001023144
  • == 发现疑似ID:622126198001103144
  • == 发现疑似ID:622126198001293144
  • == 发现疑似ID:622126198002093144
  • == 发现疑似ID:622126198002173144
  • == 发现疑似ID:622126198002253144
  • == 发现疑似ID:622126198003053144
  • == 发现疑似ID:622126198003133144
  • == 发现疑似ID:622126198003213144
  • == 发现疑似ID:622126198004013144
  • == 发现疑似ID:622126198004283144
  • == 发现疑似ID:622126198005083144
  • == 发现疑似ID:622126198005163144
  • == 发现疑似ID:622126198005243144
  • == 发现疑似ID:622126198006043144
  • == 发现疑似ID:622126198006123144
  • == 发现疑似ID:622126198006203144
  • == 发现疑似ID:622126198007193144
  • == 发现疑似ID:622126198007273144
  • == 发现疑似ID:622126198008073144
  • == 发现疑似ID:622126198008153144
  • == 发现疑似ID:622126198008233144
  • == 发现疑似ID:622126198008313144
  • == 发现疑似ID:622126198009033144
  • == 发现疑似ID:622126198009113144
  • == 发现疑似ID:622126198010093144
  • == 发现疑似ID:622126198010173144
  • == 发现疑似ID:622126198010253144
  • == 发现疑似ID:622126198011053144
  • == 发现疑似ID:622126198011133144
  • == 发现疑似ID:622126198011213144
  • == 发现疑似ID:622126198012013144
  • == 发现疑似ID:622126198012283144

验证身份证号和姓名

我们计算出疑似的身份证号以后,还是无法确定哪一个对应”刘大明“的身份证号,这时候12306网站还有个漏洞可以利用,那就是添加常用联系人功能,我们把身份证号和姓名都尝试一遍,很快就可以找到正确的身份证号和姓名的组合。

12306

分享此页面

Comments

  • Posted by 任霏 Verified Website Owner

    「更正」这里有个BUG,Calendar.MONTH ,这是一个特殊于日历的值,在格里高利历和罗马儒略历中一年中的第一个月是 JANUARY,它为 0,我忘记加一了。感谢今日头条网友”ChloeGu “提出的质疑,目前文章内容已更新为正确内容。