# =============================
# ✅ 脚本功能：分别解析 PKCS#1 格式的 RSA 私钥 和 公钥 PEM 文件，
#              提取它们的 DER 格式二进制数据，并按指定格式打印（每行16字节，0xXX,）
#              新增：生成数组文件（保存到程序目录）、显示数据长度
# =============================

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
import tkinter as tk
from tkinter import filedialog
import os  # 新增：用于获取程序目录

# =============================
# ✅ 核心工具函数：将二进制 DER 数据按指定格式打印（每行16字节，0xXX,）
# =============================
def print_der_hex_bytes(der_bytes, label=""):
    if label:
        print(f"[{label}]")
    # 新增：显示数据长度
    print(f"[长度] {len(der_bytes)} 字节")
    hex_list = [f"0x{b:02X}" for b in der_bytes]
    for i in range(0, len(hex_list), 16):
        line = hex_list[i:i+16]
        print(", ".join(line) + ("," if i + 16 < len(hex_list) else ""))
    print()  # 空行分隔
    return hex_list  # 返回十六进制列表用于生成文件

# =============================
# ✅ 新增：生成数组文件函数（保存到程序所在目录）
# =============================
def generate_array_file(hex_list, data_type):
    # 获取程序所在目录（当前脚本文件的目录）
    program_dir = os.path.dirname(os.path.abspath(__file__))
    # 定义保存文件名
    file_name = f"{data_type}_der_array.txt"
    save_path = os.path.join(program_dir, file_name)
    
    try:
        with open(save_path, 'w') as f:
            # 写入数组定义头部
            f.write(f"unsigned char {data_type}_der[] = {{\n")
            # 按每行16字节写入
            for i in range(0, len(hex_list), 16):
                line = hex_list[i:i+16]
                f.write("    " + ", ".join(line) + (",\n" if i + 16 < len(hex_list) else "\n"))
            # 写入数组长度
            f.write(f"}};\nunsigned int {data_type}_der_len = {len(hex_list)};\n")
        
        print(f"[+] ✅ {data_type}数组文件已保存至: {save_path}")
    except Exception as e:
        print(f"[-] ❌ 生成{data_type}数组文件失败: {e}")

# =============================
# ✅ 文件选择函数
# =============================
def select_file(title, file_types):
    # 创建隐藏的Tkinter根窗口
    root = tk.Tk()
    root.withdraw()  # 隐藏主窗口
    
    # 打开文件选择对话框
    file_path = filedialog.askopenfilename(
        title=title,
        filetypes=file_types
    )
    
    root.destroy()  # 关闭Tkinter根窗口
    return file_path

# =============================
# ✅ 主函数
# =============================
def main():
    # ===========================
    # === 选择私钥和公钥文件 ===
    # ===========================
    # 定义文件类型过滤器
    pem_file_types = [("PEM文件", "*.pem"), ("所有文件", "*.*")]
    
    # 选择私钥文件
    private_key_pem_path = select_file("选择PKCS#1格式私钥PEM文件", pem_file_types)
    if not private_key_pem_path:
        print("[-] 未选择私钥文件，跳过私钥解析")
    else:
        print(f"[*] 已选择 PKCS#1 格式私钥 PEM 文件: {private_key_pem_path}")

    # 选择公钥文件
    public_key_pem_path = select_file("选择PKCS#1格式公钥PEM文件", pem_file_types)
    if not public_key_pem_path:
        print("[-] 未选择公钥文件，跳过公钥解析")
    else:
        print(f"[*] 已选择 PKCS#1 格式公钥 PEM 文件: {public_key_pem_path}")

    # ===========================
    # === 1. 解析 PKCS#1 私钥 PEM 文件 ===
    # ===========================
    if private_key_pem_path:
        try:
            with open(private_key_pem_path, 'rb') as f:
                private_pem_data = f.read()

            private_key = serialization.load_pem_private_key(
                private_pem_data,
                password=None,
                backend=default_backend()
            )

            # 导出为 DER 格式 (PKCS#1 = TraditionalOpenSSL)
            private_der_bytes = private_key.private_bytes(
                encoding=serialization.Encoding.DER,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption()
            )

            print("[+] ✅ 成功解析为 PKCS#1 格式私钥")
            # 获取十六进制列表并打印
            private_hex_list = print_der_hex_bytes(private_der_bytes, label="私钥 DER (PKCS#1)")
            # 生成数组文件（保存到程序目录）
            generate_array_file(private_hex_list, "private_key")

        except Exception as e:
            print("[-] ❌ 解析 PKCS#1 私钥失败！请确认：")
            print("    - 文件格式为：-----BEGIN RSA PRIVATE KEY-----")
            print("    - 文件内容为有效的 PKCS#1 格式私钥")
            print(f"    - 错误详情: {e}")
            print()

    # ===========================
    # === 2. 解析 PKCS#1 公钥 PEM 文件 ===
    # ===========================
    if public_key_pem_path:
        try:
            with open(public_key_pem_path, 'rb') as f:
                public_pem_data = f.read()

            public_key = serialization.load_pem_public_key(
                public_pem_data,
                backend=default_backend()
            )

            # 导出为 DER 格式 (PKCS#1 = PublicFormat.PKCS1)
            public_der_bytes = public_key.public_bytes(
                encoding=serialization.Encoding.DER,
                format=serialization.PublicFormat.PKCS1
            )

            print("[+] ✅ 成功解析为 PKCS#1 格式公钥")
            # 获取十六进制列表并打印
            public_hex_list = print_der_hex_bytes(public_der_bytes, label="公钥 DER (PKCS#1)")
            # 生成数组文件（保存到程序目录）
            generate_array_file(public_hex_list, "public_key")

        except Exception as e:
            print("[-] ❌ 解析 PKCS#1 公钥失败！请确认：")
            print("    - 文件格式为：-----BEGIN RSA PUBLIC KEY-----")
            print("    - 文件内容为有效的 PKCS#1 格式公钥")
            print(f"    - 错误详情: {e}")
            print()

    print("[*] 所有操作完成。")

# =============================
# ✅ 入口
# =============================
if __name__ == "__main__":
    main()