利用身份证号行政区划代码 + 顺序码 + 校验码反推生日的实现及可行性探讨

通过特殊渠道已知人物身份证号中的前六位(行政区划编码)和后四位(顺序码 + 校验码),如何反推该人生日,效果如何?可行性多大?请看站长表演。

前言

今某于粤高中生综合素质评价系统中,偶然发现一处亮点,乃之研究性学习指导老师处,可显师之名并身份证号。

为匿私,平台仅献行政区划代码与顺序码、校验码(乃前六后四)。

奈何吾人小鬼大,竟妄利其反推吾师生日,于是,,,装不下去了,大家还是看我骚操作吧!

正文

本文照例用 Python。

首先我们需要导入以下模块中的部分方法,代码如下:

from datetime import timedelta as td, datetime as dt
from time import time
from timeit import timeit

其中,datetime 用于日期处理,time.time 用于获取时间戳,timeit.timeit 用于计时。

另外,这里还需要用到一个站长写的模块 ChinaIDAnalyLib,你可以通过 Github 下载并导入它,它主要用来判断身份证是否合法:

from ChinaIDAnalyLib import verify

接下来利用一点点小技巧找到并修改完善一个生成指定范围所有日期(指定格式)的功能代码:

def get_date_list(start: str = None, end: str = None) -> list:
    """
    Generate dates list.
    :param start: The starting date, format in yyyymmdd.
    :param end: The ending date, format in yyyymmdd.
    """
    print("Generating dates...")
    dt_start = dt.strptime(start, "%Y%M%d") if start else dt(1970, 1, 1)
    dt_end = dt.strptime(end, "%Y%M%d") if end else dt.now()
    data = [d for d in ((dt_start + td(days=1) * i).strftime("%Y%M%d")
                        for i in range((dt_end - dt_start).days))]
    print("Generated successfully! Count: " + str(len(data)))
    return data

这里,我们为了可以详细看清运行过程,加了一点输出处理,让运行效果更有逼格。

然后是一个判断函数和一个筛选函数:

def judge(id_num: str) -> bool:
    """Judge if the id is legal."""
    return str(verify(id_num[0:17])).replace("10", "X") == id_num[-1]

def filtrate(loc: str, tail: str, data: list):
    """Find all data, filter out all illegal."""
    print("Judging, Wait a moment...")
    return [d for d in data if judge(loc + d + tail)]

莫怪站长代码简短精湛但是生晦难懂,因为我重构时使用了大量生成式写法。

最后乱写一个主函数:

def main():
    loc = input("Enter the first 6 digits of ID: ")
    tail = input("Enter the last 4 digits of ID: ")

    try:
        result = filtrate(loc, tail, get_date_list())
        filename = f'data_{str(int(time()))}.txt'
        with open(filename, 'w', encoding='utf-8') as f:
            f.write("\n".join(result))
        print(f"Output successfully! Total: {str(len(result))}")
        print(f"See detail in {filename}")
    except:
        print("Operated Error!")

if __name__ == "__main__":
    t = timeit('main()', 'from __main__ import main', number=1)
    print(f'All operations finished in {t} s.')

写完吧咔把 F5 一按,输入一下目标身份证前六位和后四位,回车——

Generating dates...
Generated successfully! Count: 19531
Judging, Wait a moment...
Output successfully! Total: 1716
See detail in data_1687521875.txt
All operations finished in 2.072044100000312 s.

可见 Python 效率果然高,两秒就给我把一千七百多个数据处理好了。

燃鹅

没错这里有个小转折,,

盯紧这一句:Output successfully! Total: 1716

我设置的时间范围是 1970 年元旦至今,但是符合要求(检验码计算结果合法)的就有这么多个,也就是说任意一年内的可能概率为 1716 / 53 ≈ 30,每个月则有 2 - 3 个可能,这样本空间可太大了。

而且实际操作中,我也监测到了有时候一个月接近 10 天符合要求的情况。

这时要在这么多数据里找出目标人物的生日(如果),基本只能通过估测年龄慢慢排除,但是终将也是个麻烦事。

所以,通过身份证号上的行政区划编码和顺序码、校验码反推生日,几乎没有可行性

相关建议:若要查之人属公众人物,上网直接查;非特殊人物,我觉得可以跟 TA 捞近关系,找机会问 TA。

除非你是要获取 TA 的完整身份证,但是我得说:Be careful of the cops

阅读剩余
THE END