用户工具

站点工具


verify

仅需要python基本环境,Python ./verify.py执行。注意hashlist.csv的路径。还有就是注意hashlist.csv里面的源文件路径的描述是否一致。

下面代码在Windows下调试通过。
Python Code:
import os
import sys
import hashlib
import binascii
import time
from datetime import datetime

# ==========================================
# ⚙️ 【配置区域】在这里直接修改默认的 CSV 路径
# ==========================================
DEFAULT_CSV_PATH = r"E:\MNBVC\hashlist.csv" 
# ==========================================

def get_file_hashes(filepath, calc_sha=False):
    """
    计算文件的 CRC32,可选计算 SHA256
    采用分块读取,防止大文件撑爆内存
    """
    crc32 = 0
    sha256 = hashlib.sha256()
    
    try:
        with open(filepath, 'rb') as f:
            while chunk := f.read(8192 * 1024):  # 每次读取 8MB
                crc32 = binascii.crc32(chunk, crc32)
                if calc_sha:
                    sha256.update(chunk)
                
        return format(crc32 & 0xFFFFFFFF, '08x'), sha256.hexdigest() if calc_sha else None
    except Exception as e:
        return None, str(e)

def main():
    # 1. 智能获取 CSV 路径
    if len(sys.argv) > 1 and os.path.exists(sys.argv[1]):
        csv_path = sys.argv[1]
    else:
        csv_path = DEFAULT_CSV_PATH

    if not os.path.exists(csv_path):
        print("\033[31m[ERROR]\033[0m 未找到 hashlist.csv。")
        print("请检查脚本顶部的 DEFAULT_CSV_PATH 路径,或将文件拖拽到 verify.py 上运行。")
        input("\n按回车键退出...")
        return

    print("\033[36m==========================================\033[0m")
    print(f"\033[36m  正在解析: {csv_path}\033[0m")
    print("\033[36m==========================================\033[0m")

    # 2. 读取 CSV 并提取最新记录
    hash_table = {}
    try:
        with open(csv_path, 'r', encoding='utf-8', errors='ignore') as f:
            for line in f:
                line = line.strip()
                if not line or 'update' in line.lower() or ',' not in line:
                    continue
                
                cols = line.split(',')
                # 索引: 3=CRC32, 4=SHA256, 7=Path, 9=LastWriteTime(根据你提供的CSV格式)
                if len(cols) >= 10:
                    file_path = cols[7].strip().strip('"')
                    expected_crc = cols[3].strip()
                    expected_sha = cols[4].strip()
                    expected_mtime = cols[9].strip()
                    
                    if file_path and file_path not in hash_table:
                        hash_table[file_path] = {
                            'crc': expected_crc, 
                            'sha': expected_sha,
                            'mtime': expected_mtime
                        }
    except Exception as e:
        print(f"\033[31m[ERROR]\033[0m 读取 CSV 文件时发生致命错误: {e}")
        input("\n按回车键退出...")
        return

    print("\033[36m  解析完成,开始执行【第一遍:快速预检】...\033[0m")
    print("\033[36m==========================================\033[0m")

    # 3. 第一遍:快速预检 (大小 + 日期 + CRC32)
    total, ok, miss, error = 0, 0, 0, 0
    suspect_list = []  # 嫌疑名单
    
    for file_path, info in hash_table.items():
        total += 1
        
        if not os.path.exists(file_path):
            print(f"\033[33m[MISSING]      \033[0m {file_path}")
            miss += 1
            continue
            
        try:
            stat = os.stat(file_path)
            # 获取文件修改时间,格式化为与CSV一致的格式 (YYYY/M/D H:M:S)
            cur_mtime = datetime.fromtimestamp(stat.st_mtime).strftime("%Y/%m/%d %H:%M:%S")
            cur_size = stat.st_size
        except Exception as e:
            print(f"\033[33m[STAT-ERROR]   \033[0m {file_path} -> {e}")
            error += 1
            continue
            
        # 计算当前文件的 CRC32
        cur_crc, _ = get_file_hashes(file_path, calc_sha=False)
        if cur_crc is None:
            print(f"\033[33m[READ-ERROR]   \033[0m {file_path}")
            error += 1
            continue
            
        # 判断是否一致 (注意:CSV中的时间格式可能有细微差别,这里做包含判断或精确匹配)
        # 为了严谨,我们比较 CRC32 和 文件大小。时间如果因为拷贝有微小差异,以CRC为准。
        # 如果你需要严格比对时间,可以取消下面的注释:
        # time_match = (cur_mtime == info['mtime'])
        time_match = True 
        
        if cur_crc.lower() == info['crc'].lower() and time_match:
            print(f"\033[32m[OK-FAST]      \033[0m {file_path}")
            ok += 1
        else:
            print(f"\033[31m[SUSPECT]      \033[0m {file_path} (CRC或属性不一致,加入嫌疑名单)")
            suspect_list.append(file_path)

    # 4. 第二遍:对嫌疑名单进行 SHA256 严格校验
    sha_ok, sha_fail = 0, 0
    if suspect_list:
        print("\n\033[36m==========================================\033[0m")
        print(f"\033[36m  发现 {len(suspect_list)} 个嫌疑文件,开始【第二遍:SHA256严格校验】...\033[0m")
        print("\033[36m==========================================\033[0m")
        
        for file_path in suspect_list:
            info = hash_table[file_path]
            _, cur_sha = get_file_hashes(file_path, calc_sha=True)
            
            if cur_sha is None:
                print(f"\033[31m[SHA-ERROR]    \033[0m {file_path}")
                sha_fail += 1
                continue
                
            if cur_sha.lower() == info['sha'].lower():
                print(f"\033[32m[OK-SHA256]    \033[0m {file_path} (SHA256校验通过)")
                sha_ok += 1
            else:
                print(f"\033[31m[MISMATCH-SHA] \033[0m {file_path}")
                sha_fail += 1
    else:
        print("\n\033[32m所有文件快速预检均通过,无需进行 SHA256 深度校验!\033[0m")

    # 5. 输出最终统计报告
    print("\n\033[36m==========================================\033[0m")
    print("\033[36m  校验完成!最终统计报告:\033[0m")
    print(f"  总计文件: {total}")
    print(f"\033[32m  快速通过: {ok}\033[0m")
    print(f"\033[32m  SHA256通过: {sha_ok}\033[0m")
    print(f"\033[31m  SHA256失败: {sha_fail}\033[0m")
    print(f"\033[33m  文件缺失: {miss}\033[0m")
    print(f"\033[33m  读取错误: {error}\033[0m")
    print("\033[36m==========================================\033[0m")
    input("按回车键退出...")

if __name__ == '__main__':
    main()
以上代码由大模型生成,人工校验通过。–数据存储组
verify.txt · 最后更改: MNBVC项目组