#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
专门测试密码解密
"""

import sys
import os
import traceback
import json

print("="*60)
print("  密码解密测试")
print("="*60)
print()

# 加载配置
print("加载配置...")
if not os.path.exists("config.json"):
    print("❌ config.json 不存在")
    sys.exit(1)

with open("config.json", "r", encoding="utf-8") as f:
    config = json.load(f)

password_file = config.get('password_file', 'password.enc')
print(f"密码文件: {password_file}")
print(f"文件大小: {os.path.getsize(password_file)} bytes")
print()

# 测试 1: 尝试 dpapi 库
print("[测试 1] 尝试使用 dpapi 库...")
try:
    import dpapi
    print("  ✅ dpapi 库已安装")

    with open(password_file, 'rb') as f:
        encrypted_bytes = f.read()

    print(f"  加密数据长度: {len(encrypted_bytes)} bytes")
    print(f"  前10个字节: {encrypted_bytes[:10].hex()}")

    decrypted_bytes = dpapi.decrypt(encrypted_bytes)
    password = decrypted_bytes.decode('utf-8')

    print(f"  ✅ 解密成功!")
    print(f"  密码长度: {len(password)} 字符")
    print(f"  密码前3位: {password[:3]}***")
    print()
    sys.exit(0)

except ImportError:
    print("  ⚠ dpapi 库未安装，尝试 ctypes 方法")
    print()
except Exception as e:
    print(f"  ❌ dpapi 解密失败: {e}")
    traceback.print_exc()
    print()
    # 继续尝试 ctypes
    print()

# 测试 2: 尝试 ctypes 方法
print("[测试 2] 尝试使用 ctypes DPAPI...")
try:
    import ctypes
    from ctypes import wintypes

    crypt32 = ctypes.windll.crypt32

    class DATA_BLOB(ctypes.Structure):
        _fields_ = [
            ("cbData", wintypes.DWORD),
            ("pbData", ctypes.POINTER(ctypes.c_byte))
        ]

    with open(password_file, 'rb') as f:
        encrypted_bytes = f.read()

    print(f"  加密数据长度: {len(encrypted_bytes)} bytes")

    # 创建输入 blob
    buffer_type = ctypes.c_byte * len(encrypted_bytes)
    buffer = buffer_type.from_buffer_copy(encrypted_bytes)

    input_blob = DATA_BLOB()
    input_blob.cbData = len(encrypted_bytes)
    input_blob.pbData = buffer

    output_blob = DATA_BLOB()

    print("  调用 CryptUnprotectData...")

    result = crypt32.CryptUnprotectData(
        ctypes.byref(input_blob),
        None,
        None,
        None,
        None,
        0
    )

    if not result:
        error_code = ctypes.get_last_error()
        print(f"  ❌ DPAPI 解密失败")
        print(f"  错误代码: {error_code}")

        # 常见错误代码
        if error_code == 5:
            print("  错误描述: ACCESS DENIED")
            print("  可能原因: 密码文件是在其他计算机上创建的")
        elif error_code == 13:
            print("  错误描述: INVALID DATA")
            print("  可能原因: 密码文件损坏或格式不正确")
        else:
            print(f"  错误描述: 未知错误 (代码 {error_code})")

        sys.exit(1)

    print(f"  解密数据长度: {output_blob.cbData} bytes")

    # 提取解密数据
    decrypted_buffer = (ctypes.c_byte * output_blob.cbData)()
    ctypes.memmove(decrypted_buffer, output_blob.pbData, output_blob.cbData)
    decrypted_bytes = bytes(decrypted_buffer)

    ctypes.windll.kernel32.LocalFree(output_blob.pbData)

    password = decrypted_bytes.decode('utf-8')

    print(f"  ✅ 解密成功!")
    print(f"  密码长度: {len(password)} 字符")
    print(f"  密码前3位: {password[:3]}***")
    print()
    sys.exit(0)

except Exception as e:
    print(f"  ❌ ctypes 解密失败: {e}")
    traceback.print_exc()
    print()

# 测试 3: 检查密码文件内容
print("[测试 3] 检查密码文件...")
try:
    with open(password_file, 'rb') as f:
        data = f.read()

    print(f"  文件大小: {len(data)} bytes")
    print(f"  前20个字节 (hex): {data[:20].hex()}")
    print(f"  是否为空: {len(data) == 0}")

    if len(data) == 0:
        print("  ❌ 密码文件为空!")
        print("  解决方法: 重新运行配置向导")
        print("    del config.json password.enc")
        print("    python mdp_termination.py --config")

except Exception as e:
    print(f"  ❌ 读取文件失败: {e}")

print()
print("="*60)
print("  测试完成")
print("="*60)
