Metadata-Version: 2.4
Name: module_bank
Version: 0.3.1
Summary: Add your description here
License-File: LICENSE
Requires-Python: >=3.7
Requires-Dist: cryptography>=45.0.7
Requires-Dist: pyarmor>=9.2.4
Description-Content-Type: text/markdown

# Python Module Bank - SQLite 模块打包系统

一个将 Python 模块打包到 SQLite 数据库，并支持从数据库直接导入模块的工具系统。支持 **AES 字节码加密** 和 **PyArmor 代码混淆** 双重保护机制。

## 🌟 特性

- **单文件分发** - 将所有模块打包到单个 SQLite 数据库文件
- **AES 字节码加密** - 编译后的字节码使用 Fernet (AES-128-CBC) 加密存储
- **PyArmor 代码混淆** - 支持使用 PyArmor 对 Python 源代码进行混淆保护
- **双层保护** - 可同时使用 PyArmor 混淆 + AES 字节码加密，提供双重安全保障
- **动态导入** - 运行时直接从数据库加载模块，无缝集成 Python 导入系统
- **完整包支持** - 支持包结构和子模块导入
- **CLI 工具** - 提供完整的命令行接口

## 📦 安装

### 从源码安装

```bash
git clone http://124.71.68.6:3000/chakcy/module_bank.git
cd module-bank
pip install -e .
```

### 使用 uv（推荐）

```bash
git clone http://124.71.68.6:3000/chakcy/module_bank.git
cd module-bank
uv sync
```

### 可选依赖

- **PyArmor** (强烈推荐): `uv add pyarmor` 或 `pip install pyarmor`
  - 为模块提供 Python 源代码级别的混淆保护
  - 商业版可去除试用版水印

## 🚀 快速开始

### 1. 创建示例模块

```python
# my_package/__init__.py
def hello():
    print("Hello from my_package!")
    return "success"

VERSION = "1.0.0"
```

```python
# my_package/utils.py
def add(a, b):
    return a + b
```

### 2. 打包模块到数据库

#### 使用 AES 加密（推荐）

```bash
# 生成密钥并打包
mbank pack my_package --db my_package.mbank --key "$(python -c "from module_bank.encryption import Encryption; print(Encryption.generate_key())")"
```

#### 使用 PyArmor 混淆

```bash
# 使用 PyArmor 保护源代码
mbank pack my_package --db my_package.mbank --pyarmor
```

#### 使用双层保护

```bash
# PyArmor 混淆 + AES 加密
mbank pack my_package --db my_package.mbank --pyarmor --key "your-encryption-key"
```

### 3. 从数据库导入

```python
# import_example.py
from module_bank.python_to_sqlite import PythonToSQLite

packer = PythonToSQLite("my_package.mbank")
finder = packer.install_importer(key="your-encryption-key")  # 如果加密了需要提供密钥

from my_package import utils
from my_package import hello

print(hello())
print(utils.add(3, 4))
```

## 🛡️ 安全保护机制

### 第一层：PyArmor 代码混淆

PyArmor 对 Python 源代码进行混淆，将代码转换为难以阅读和逆向的形式：

- 混淆后的代码依赖运行时二进制文件（`.pyd`/`.so`），无法直接运行
- 支持混淆级别控制（代码混淆、模块混淆）
- 运行时文件会自动存储在数据库中，加载时自动部署

```bash
# 高级混淆选项
mbank pack my_module.py --name my_module --db modules.db \
    --pyarmor \
    --pyarmor-obf-code 1 \
    --pyarmor-obf-mod 1
```

### 第二层：AES 字节码加密

编译后的字节码使用 Fernet (AES-128-CBC) 加密：

```bash
# 生成密钥
python -c "from module_bank.encryption import Encryption; print(Encryption.generate_key())" > my_key.key

# 使用密钥打包
mbank pack my_module.py --name my_module --db modules.db --key "$(cat my_key.key)"

# 使用时提供密钥
mbank install --db modules.db --key "$(cat my_key.key)"
```

### 安全建议

1. **密钥管理**：加密密钥不要硬编码在代码中，使用环境变量或密钥管理服务
2. **删除源代码**：打包后可从数据库删除源代码，仅保留混淆后的代码：

```bash
# 删除所有模块的源代码
mbank delete_source --db modules.db

# 删除指定模块的源代码
mbank delete_source --db modules.db --module my_module
```

## 📖 详细使用

### 命令行工具

```bash
# 打包单个模块
mbank pack my_module.py --name my_module --db modules.db

# 打包整个目录（自动识别包结构）
mbank pack my_package/ --db modules.db

# 使用 PyArmor 混淆打包
mbank pack my_module.py --name my_module --db modules.db --pyarmor

# 使用 AES 加密打包
mbank pack my_module.py --name my_module --db modules.db --key "your-key"

# 双层保护
mbank pack my_module.py --name my_module --db modules.db --pyarmor --key "your-key"

# 列出数据库中的模块
mbank list --db modules.db

# 删除源代码
mbank delete_source --db modules.db
mbank delete_source --db modules.db --module my_module

# 安装导入器并进入交互模式
mbank install --db modules.db
mbank install --db modules.db --key "your-key"
```

### 编程接口

#### 打包模块

```python
from module_bank import PythonToSQLite
from module_bank.encryption import Encryption

# 生成加密密钥
key = Encryption.generate_key()

# 使用 AES 加密打包
packer = PythonToSQLite("modules.mbank", key=key)

# 或使用 PyArmor 混淆打包
packer = PythonToSQLite(
    "modules.mbank",
    pyarmor_obfuscate=True,
    pyarmor_obf_code=1,
    pyarmor_obf_mod=1,
)

# 打包单个模块
packer.pack_module("module.py", "module_name")

# 打包整个目录（自动识别包结构）
packer.pack_directory("my_package/")

# 验证包结构
packer.verify_package_structure()
```

#### 导入模块

```python
from module_bank import PythonToSQLite

# 如果数据库中的模块被 AES 加密了，需要提供密钥
packer = PythonToSQLite("modules.mbank")

# 安装导入器到 sys.meta_path
finder = packer.install_importer(key="your-key")

# 列出所有可用模块
modules = packer.list_modules()
for module in modules:
    package_flag = " [包]" if module["is_package"] else ""
    print(f"  - {module['module_name']}{package_flag}")

# 直接导入数据库中的模块（就像普通模块一样）
import my_package
import my_package.submodule

print(my_package)
my_package.hello()
```

## 🏗️ 架构设计

### 核心组件

```python
src/module_bank/
├── python_to_sqlite.py         # 主打包类
├── sqlite_module_importer.py   # 数据库存储管理器
├── sqlite_meta_path_finder.py  # 元路径查找器
├── sqlite_module_loader.py     # 模块加载器
├── encryption.py               # AES 密钥管理
├── pyarmor_encryption.py       # PyArmor 混淆封装
├── cli.py                      # 命令行接口
└── __init__.py                 # 模块导出
```

### 数据流

```text
1. 打包阶段:
   .py 文件 → (可选: PyArmor 混淆) → 编译为字节码 → (可选: AES 加密) → 存储到 SQLite

2. 导入阶段:
   导入请求 → MetaPathFinder 查找 → ModuleLoader 加载 → (AES 解密) → (PyArmor 运行时部署) → 执行模块
```

### 数据库模式

```sql
-- 模块表
CREATE TABLE python_modules (
    module_name TEXT PRIMARY KEY,
    source_code TEXT,               -- 源代码（PyArmor 混淆后）
    bytecode BLOB,                  -- 编译后的字节码（可选 AES 加密）
    is_package BOOLEAN,             -- 是否是包
    metadata TEXT,                  -- 元数据（JSON 格式）
    encrypted INTEGER DEFAULT 0,    -- AES 是否已加密
    pyarmor_protected INTEGER DEFAULT 0,  -- 是否已 PyArmor 混淆
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- PyArmor 运行时存储表
CREATE TABLE pyarmor_runtime (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    runtime_name TEXT UNIQUE NOT NULL,
    pyd_data BLOB,                  -- 原生二进制文件（.pyd/.so）
    init_data TEXT,                 -- __init__.py 内容
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```

## 🔧 高级功能

### 排除模式

```python
# 打包时排除特定文件
packer.pack_directory(
    "my_project/",
    exclude_patterns=["*_test.py", "*.pyc", "__pycache__"],
)
```

### 元数据存储

```python
# 为模块添加元数据
packer.importer.add_module(
    "my_module",
    source_code,
    is_package=False,
    metadata={"version": "1.0", "author": "me"},
)
```

### 混合导入

```python
# 数据库导入器默认插入到 meta_path 开头，优先级高于文件系统
import sys
from module_bank import PythonToSQLite

packer = PythonToSQLite("modules.db")
finder = packer.install_importer()

# 如果需要文件系统优先，将查找器追加到末尾
sys.meta_path.remove(finder)
sys.meta_path.append(finder)
```

### 验证运行时完整性

```python
from module_bank.sqlite_module_importer import SQLiteModuleImporter

importer = SQLiteModuleImporter("modules.db")
runtimes = importer.list_runtimes()
for rt in runtimes:
    print(f"运行时: {rt['runtime_name']} (创建于: {rt['created_at']})")
```

## ⚠️ 注意事项

### 安全性

- 模块字节码直接执行，确保数据库来源可信
- AES 加密密钥必须安全保管，丢失后将无法解密模块
- PyArmor 混淆提供源代码级别的保护，但商业版才能去除试用版水印
- 生产环境建议 PyArmor 混淆 + AES 加密同时使用

### 兼容性

- 字节码不跨 Python 版本兼容（3.12 编译的模块无法在 3.11 加载）
- 不支持 C 扩展模块
- PyArmor 运行时文件与操作系统相关（Windows 用 `.pyd`，Linux 用 `.so`）
- 运行时文件需在目标系统上重新打包

### 性能

- **启动时**：有一次性数据库查询和反序列化/运行时部署开销
- **运行时**：与传统导入性能相同（使用 sys.modules 缓存）
- **最佳适用**：长期运行的服务、桌面应用

### 更新模块

```python
# 重新打包会自动更新
packer.pack_module("updated_module.py", "module_name")
```

### 删除模块

```sql
-- 直接从数据库删除
DELETE FROM python_modules WHERE module_name = 'module_to_remove';
```

### 备份与恢复

```bash
# 数据库是单个文件，易于备份
cp modules.mbank modules.backup.mbank

# 恢复
cp modules.backup.mbank modules.mbank
```

## 📚 应用场景

1. **商业软件分发** - PyArmor 混淆保护源代码知识产权
2. **安全敏感环境** - AES 加密确保即使数据库泄露也无法还原代码
3. **插件系统** - 动态加载数据库中的加密/混淆插件模块
4. **教育平台** - 安全分发练习代码，防止学生抄袭
5. **微服务** - 打包多个服务模块到单个加密文件
6. **嵌入式系统** - 减少文件系统依赖，提高安全性

---

**注意**: 本工具主要用于模块分发和部署场景，不适合开发阶段的频繁修改。

**许可证**: MIT License
