Работа с "подделкой" лицензии

This commit is contained in:
2026-03-05 18:46:13 +07:00
parent 92367b9f6e
commit 7f925ef2bd
2 changed files with 95 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
from typing import Any
from fastapi import APIRouter, Form, HTTPException, BackgroundTasks
from fastapi.responses import FileResponse
from ..services.license_service import generate_license_file
router: APIRouter = APIRouter()
@router.post("/generate", response_class=FileResponse)
async def generate_license(
background_tasks: BackgroundTasks,
name: str = Form(...),
version: str = Form(...)
) -> Any:
"""
Генерация лицензии Custom.mxtpro.
Параметры:
- name: str - имя пользователя
- version: str - версия формата X.Y
Возвращает:
- FileResponse: сгенерированный ZIP файл с именем Custom.mxtpro
"""
if not name.strip() or not version.strip():
raise HTTPException(
status_code=400,
detail="NAME и VERSION обязательны."
)
try:
# Создаём временный файл на сервере
filepath, temp_dir = generate_license_file(name, version)
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"Ошибка генерации лицензии: {e}"
)
# Удаляем директорию (и файл внутри) после отправки пользователю
background_tasks.add_task(temp_dir.cleanup)
# Отправляем с фиксированным именем Custom.mxtpro
return FileResponse(
filepath,
media_type="application/octet-stream",
headers={
"Content-Disposition": 'attachment; filename="Custom.mxtpro"'
}
)

View File

@@ -0,0 +1,48 @@
import tempfile
from zipfile import ZipFile
from pathlib import Path
from ..utils.encoding import variant_base64_encode
from ..utils.crypto import encrypt_bytes
class LicenseType:
Professional: int = 1
Educational: int = 3
Personal: int = 4
def generate_license_file(
user_name: str,
version: str,
lic_type: int = LicenseType.Professional,
count: int = 1
) -> tuple[str, tempfile.TemporaryDirectory]:
"""
Генерация временного ZIP-файла с лицензией Custom.mxtpro.
Возвращает путь к файлу и объект временной директории для cleanup.
"""
# Разбор версии
try:
major_str, minor_str = version.split(".")
major_version: int = int(major_str)
minor_version: int = int(minor_str)
except Exception as e:
raise ValueError(f"Неверный формат версии: {version}") from e
# Формирование строки лицензии
license_str: str = (
f"{lic_type}#{user_name}|{major_version}{minor_version}"
f"#{count}#{major_version}3{minor_version}6{minor_version}#0#0#0#"
)
# Шифрование и кодирование
encrypted: bytes = encrypt_bytes(0x0787, license_str.encode("utf-8"))
encoded: str = variant_base64_encode(encrypted).decode("ascii")
# Создание временной директории и файла с фиксированным именем
temp_dir = tempfile.TemporaryDirectory()
filepath = Path(temp_dir.name) / "Custom.mxtpro"
with ZipFile(filepath, "w") as zf:
zf.writestr("Pro.key", encoded)
return str(filepath), temp_dir