zoukankan      html  css  js  c++  java
  • 火车票上的星号暗藏玄机?!

    前言

    随着网络的发展,现在人手一部手机,大家别误会啊,我不是在定位女友了(前文回顾点我),我只是感慨一下网路的发展快。昨天回了一次老家,在车上无聊看着火车票,虽然火车票上的身份证打了四个星号,但是是否意味着安全啦?

    捕获.PNG

    通过百度简单的搜索一下

    点击我百度火车票搜索

    详细分析

    1.寻找数据源

    我们随便选择一个

    数据源

    就这位了

    2.四位星号分析

    现在我们来分析一下这四位星号,从身份证的构造上看 肯定是 月日,二个字节表示月或者日,假如四个星号为(ABCD)

    那么A 代表的是月 大家都知道月最多是12月 那么A 最大是1,

    那么只有二种选择(0,1),

    好现在我们开始判断一下B的取值范围:

    当A为0的时候B取值为(1-9)

     当A为1的时候B取值为(0-2)

    现在来判断C的范围,大家都知道一个月最多31天,

    那么C的范围(0-3)

    现在判断一下D的范围

    当C为0的时候D为1-9

    当C为1-2的时候D为0-9

    当C为3的时候D为0-1

    大家别嫌弃我分析麻烦,如果不分析,怎么写代码?

    3.写代码生成数据

    //月左位
    for (size_t iA = 0; iA < 2; iA++)
    {
    //月右位
    for (size_t iB = 0; iB < 10; iB++)
    {
    //当A为0的时候B取值为(1 - 9)
    if (iA==0)
    {
    if (iB==0)
    {
    
    continue;
    }
    }
    else if (iA == 1) //当A为1的时候B取值为(0-2)
    {
    if (iB > 2)
    {
    continue;
    }
    }
    
    //日的左边
    for (size_t iC = 0; iC < 4; iC++)
    {
    
    //日的右边
    for (size_t iD = 0; iD < 10; iD++)
    {
    //当C为0的时候D为1-9
    if (iC==0)
    {
    if (iD == 0)
    {
    continue;
    }
    }
    else if (iC == 3)//当C为3的时候D为0 - 1
    {
    if (iD > 1)
    {
    continue;
    }
    }
    
    
    
    sprintf(buffer, "%s%d%d%d%d%s", pFrist,iA, iB, iC, iD, pEnd);
    if (!Chk18PaperId(buffer))
    {
    WriteFile(hFile, buffer, strlen(buffer), &dwWrite, NULL);
    WriteFile(hFile, "
    ", 2, &dwWrite, NULL);
    }
    
    
    
    
    }
    }
    }
    }
    
    

    写代码生成数据

    4.数据进行过滤

    根据月大月小过滤一下数据,1.3.5.7.8.10.12 是月大 2月只有28天

    //开始遍历 //1 3 5 7 8 10 12 月大
    //进行月大月小的判断
    
    if (iA==0)
    {
    if (iB == 4 || iB == 6 || iB == 9 || iB == 11)
    {
    //月小
    if (iC == 3 && iD == 1)
    {
    continue;
    }
    }
    else if (iB==2)
    {
    //月小
    if (iC > 2)
    {
    continue;
    }
    else if (iC==2&&(iD>8))
    {
    continue;
    }
    }
    
    }
    else
    {
    if (iB==1)
    {
    //11月是月小
    if (iC==3&&iD==1)
    {
    continue;
    }
    }
    }

    数据进行过滤

    少了几条啊

    5.数据再次过滤

    一共有三百多条数据,我们需要进一步进行过滤,过滤原理如下

    校验规则是:

    (1)十七位数字本体码加权求和公式 

    S = Sum(Ai * Wi), i = 0, … , 16 ,先对前17位数字的权求和 

    Ai:表示第i位置上的身份证号码数字值 

    Wi:表示第i位置上的加权因子 

    Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 

    (2)计算模 

    Y = mod(S, 11) 

    (3)通过模得到对应的校验码 

    Y: 0 1 2 3 4 5 6 7 8 9 10 

    校验码: 1 0 X 9 8 7 6 5 4 3 2

    int Chk18PaperId(const char *sPaperId)
    {
    long lSumQT = 0;
    //加权因子  
    int R[] = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
    //校验码  
    char sChecker[11] = { '1','0','X', '9', '8', '7', '6', '5', '4', '3', '2' };
    //检验长度  
    if (18 != strlen(sPaperId)) return -1;
    //校验数字  
    for (int i = 0; i<18; i++)
    {
    if (!isdigit(sPaperId[i]) && !(('X' == sPaperId[i] || 'x' == sPaperId[i]) && 17 == i))
    {
    return -1;
    }
    }
    //验证最末的校验码  
    for (int i = 0; i <= 16; i++)
    {
    lSumQT += (sPaperId[i] - 48) * R[i];
    }
    if (sChecker[lSumQT % 11] != sPaperId[17])
    {
    return -1;
    }
    return 0;
    }

    看计算后的结果

    通过模得到对应的校验码

    这个结果还是比较满意的,只有三十多次了

    6.数据验证

    最后一步,数据验证

    数据验证

    根据姓名和上传生成的30多个身份证id取验证一下吧

    我随机选择了家的,代码如下 大同小异,关于最后身份证号码是多少?我在此保密,自己验证

    数据验证

    验证测试代码

    #include<Windows.h>
    #include<stdio.h>
    /***************************************************
    * 函 数 名: Chk18PaperId
    *
    * 函数功能: 校验18位身份证号码
    *
    * 输入参数:  sPaperId  身份证号
    *
    * 输出参数:
    *
    * 返回值:   0        成功
    *           其他     失败
    ****************************************************/
    int Chk18PaperId(const char *sPaperId)
    {
    long lSumQT = 0;
    //加权因子  
    int R[] = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
    //校验码  
    char sChecker[11] = { '1','0','X', '9', '8', '7', '6', '5', '4', '3', '2' };
    //检验长度  
    if (18 != strlen(sPaperId)) return -1;
    //校验数字  
    for (int i = 0; i<18; i++)
    {
    if (!isdigit(sPaperId[i]) && !(('X' == sPaperId[i] || 'x' == sPaperId[i]) && 17 == i))
    {
    return -1;
    }
    }
    //验证最末的校验码  
    for (int i = 0; i <= 16; i++)
    {
    lSumQT += (sPaperId[i] - 48) * R[i];
    }
    if (sChecker[lSumQT % 11] != sPaperId[17])
    {
    return -1;
    }
    return 0;
    }
    void CreateId(char * pFrist, char * pEnd)
    {
    char buffer[MAX_PATH] = { 0 };
    DWORD dwWrite = 0;
    HANDLE hFile = CreateFileA("1.txt", 
    FILE_WRITE_ACCESS, NULL, 
    NULL, OPEN_ALWAYS, NULL, NULL);
    //月左位
    for (size_t iA = 0; iA < 2; iA++)
    {
    //月右位
    for (size_t iB = 0; iB < 10; iB++)
    {
    //当A为0的时候B取值为(1 - 9)
    if (iA==0)
    {
    if (iB==0)
    {
    
    continue;
    }
    }
    else if (iA == 1) //当A为1的时候B取值为(0-2)
    {
    if (iB > 2)
    {
    continue;
    }
    }
    
    //日的左边
    for (size_t iC = 0; iC < 4; iC++)
    {
    
    //日的右边
    for (size_t iD = 0; iD < 10; iD++)
    {
    //当C为0的时候D为1-9
    if (iC==0)
    {
    if (iD == 0)
    {
    continue;
    }
    }
    else if (iC == 3)//当C为3的时候D为0 - 1
    {
    if (iD > 1)
    {
    continue;
    }
    }
    
    //开始遍历 //1 3 5 7 8 10 12 月大
    //进行月大月小的判断
    
    if (iA==0)
    {
    if (iB == 4 || iB == 6 || iB == 9 || iB == 11)
    {
    //月小
    if (iC == 3 && iD == 1)
    {
    continue;
    }
    }
    else if (iB==2)
    {
    //月小
    if (iC > 2)
    {
    continue;
    }
    else if (iC==2&&(iD>8))
    {
    continue;
    }
    }
    
    }
    else
    {
    if (iB==1)
    {
    //11月是月小
    if (iC==3&&iD==1)
    {
    continue;
    }
    }
    }
    
    sprintf(buffer, "%s%d%d%d%d%s", pFrist,iA, iB, iC, iD, pEnd);
    if (!Chk18PaperId(buffer))
    {
    WriteFile(hFile, buffer, strlen(buffer), &dwWrite, NULL);
    WriteFile(hFile, "
    ", 2, &dwWrite, NULL);
    }
    
    
    
    
    }
    }
    }
    }
    CloseHandle(hFile);
    }
    void main()
    {
    
    CreateId("2113241992", "3014");
    }

    最后总结

    希望大家注意火车票的隐私,千万别乱丢火车票,同时提醒12306给校验码去掉,这样就增加了难度

  • 相关阅读:
    反射
    left join 多个表关联时,将表值置换
    distinct 与 group by 去重
    常见错误
    字符串的处理
    排版样式
    VS低版本打开高版本解决方案(如08打开10、12、13版本vs编译的项目)
    Dw CS 破解
    VS2013如何避开安装时IE10的限制
    UVa540 Team Queue
  • 原文地址:https://www.cnblogs.com/h2zZhou/p/7337444.html
Copyright © 2011-2022 走看看