""" MontanaSign — Сервис подписи iOS приложений efir.org/install Модель как LazyShop: 1. Пользователь регистрирует UDID 2. Мы выдаём сертификат (или подписываем своим) 3. .ipa скачивается и устанавливается 4. Apple не контролирует """ from flask import Flask, request, jsonify, send_file, render_template_string from flask_cors import CORS import os import subprocess import hashlib import json import sqlite3 from datetime import datetime, timedelta import secrets app = Flask(__name__) CORS(app) # Конфигурация UPLOAD_FOLDER = '/var/montana/ipa' SIGNED_FOLDER = '/var/montana/signed' CERTS_FOLDER = '/var/montana/certs' DATABASE = '/var/montana/montanasign.db' # IPA файлы Montana (беззнаковые) MONTANA_APPS = { 'wallet': { 'name': 'Montana Wallet', 'bundle_id': 'network.montana.wallet', 'version': '1.0.0', 'ipa': 'MontanaWallet.ipa', 'icon': 'wallet_icon.png', 'description': 'Кошелёк Ɉ — баланс и переводы' }, 'junona': { 'name': 'Junona AI', 'bundle_id': 'network.montana.junona', 'version': '1.0.0', 'ipa': 'JunonaAI.ipa', 'icon': 'junona_icon.png', 'description': 'Чат с ИИ Montana Protocol' }, 'contracts': { 'name': 'Montana Contracts', 'bundle_id': 'network.montana.contracts', 'version': '1.0.0', 'ipa': 'MontanaContracts.ipa', 'icon': 'contracts_icon.png', 'description': 'Контракты Bitcoin Pizza Style' } } def init_db(): """Инициализация базы данных""" conn = sqlite3.connect(DATABASE) c = conn.cursor() c.execute(''' CREATE TABLE IF NOT EXISTS devices ( udid TEXT PRIMARY KEY, user_id TEXT, device_name TEXT, model TEXT, registered_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, expires_at TIMESTAMP, certificate_id TEXT ) ''') c.execute(''' CREATE TABLE IF NOT EXISTS certificates ( cert_id TEXT PRIMARY KEY, udid TEXT, cert_data BLOB, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, expires_at TIMESTAMP, revoked BOOLEAN DEFAULT FALSE ) ''') c.execute(''' CREATE TABLE IF NOT EXISTS installations ( id INTEGER PRIMARY KEY AUTOINCREMENT, udid TEXT, app_id TEXT, installed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, version TEXT ) ''') conn.commit() conn.close() # ═══════════════════════════════════════════════════════════════ # LANDING PAGE # ═══════════════════════════════════════════════════════════════ LANDING_HTML = ''' Montana Install — Установка без App Store

Montana Install

Установка без App Store. Apple не контролирует.

1

Зарегистрируй устройство

Открой Настройки → Основные → Об этом устройстве → UDID
Или используй get.udid.io

💰
Montana Wallet
Кошелёк Ɉ — баланс и переводы
🤖
Junona AI
Чат с ИИ Montana Protocol
📄
Montana Contracts
Контракты Bitcoin Pizza Style
2

После установки

Настройки → Основные → VPN и управление устройством → Доверять сертификату Montana

''' @app.route('/') def landing(): return render_template_string(LANDING_HTML) # ═══════════════════════════════════════════════════════════════ # API # ═══════════════════════════════════════════════════════════════ @app.route('/api/register', methods=['POST']) def register_device(): """Регистрация устройства по UDID""" data = request.json udid = data.get('udid', '').strip() if not udid or len(udid) < 20: return jsonify({'success': False, 'error': 'Invalid UDID'}) conn = sqlite3.connect(DATABASE) c = conn.cursor() # Проверяем существует ли c.execute('SELECT * FROM devices WHERE udid = ?', (udid,)) existing = c.fetchone() if existing: conn.close() return jsonify({'success': True, 'message': 'Already registered'}) # Регистрируем expires_at = datetime.now() + timedelta(days=365) cert_id = secrets.token_hex(16) c.execute(''' INSERT INTO devices (udid, expires_at, certificate_id) VALUES (?, ?, ?) ''', (udid, expires_at, cert_id)) conn.commit() conn.close() return jsonify({ 'success': True, 'message': 'Device registered', 'expires': expires_at.isoformat() }) @app.route('/api/manifest/') def get_manifest(app_id): """Генерация manifest.plist для установки""" udid = request.args.get('udid') if app_id not in MONTANA_APPS: return 'App not found', 404 app = MONTANA_APPS[app_id] # Генерируем manifest manifest = f''' items assets kind software-package url {request.host_url}api/download/{app_id}?udid={udid} kind display-image url {request.host_url}static/icons/{app['icon']} metadata bundle-identifier {app['bundle_id']} bundle-version {app['version']} kind software title {app['name']} ''' return manifest, 200, {'Content-Type': 'application/xml'} @app.route('/api/download/') def download_ipa(app_id): """Скачивание подписанного IPA""" udid = request.args.get('udid') if app_id not in MONTANA_APPS: return 'App not found', 404 app = MONTANA_APPS[app_id] # Путь к подписанному IPA для этого UDID signed_path = os.path.join(SIGNED_FOLDER, udid, app['ipa']) # Если ещё не подписан — подписываем if not os.path.exists(signed_path): sign_ipa_for_udid(app_id, udid) if os.path.exists(signed_path): # Логируем установку conn = sqlite3.connect(DATABASE) c = conn.cursor() c.execute(''' INSERT INTO installations (udid, app_id, version) VALUES (?, ?, ?) ''', (udid, app_id, app['version'])) conn.commit() conn.close() return send_file(signed_path, as_attachment=True, download_name=app['ipa']) return 'Signing failed', 500 def sign_ipa_for_udid(app_id: str, udid: str): """Подписать IPA для конкретного UDID""" app = MONTANA_APPS[app_id] unsigned_path = os.path.join(UPLOAD_FOLDER, app['ipa']) output_dir = os.path.join(SIGNED_FOLDER, udid) os.makedirs(output_dir, exist_ok=True) output_path = os.path.join(output_dir, app['ipa']) # Используем zsign или ldid для подписи # zsign -k cert.p12 -m profile.mobileprovision -o output.ipa input.ipa cert_path = os.path.join(CERTS_FOLDER, 'montana.p12') profile_path = os.path.join(CERTS_FOLDER, f'{udid}.mobileprovision') try: subprocess.run([ 'zsign', '-k', cert_path, '-m', profile_path, '-o', output_path, unsigned_path ], check=True) return True except subprocess.CalledProcessError as e: print(f"Signing failed: {e}") return False @app.route('/api/apps') def list_apps(): """Список приложений""" return jsonify(MONTANA_APPS) @app.route('/api/stats') def stats(): """Статистика""" conn = sqlite3.connect(DATABASE) c = conn.cursor() c.execute('SELECT COUNT(*) FROM devices') devices = c.fetchone()[0] c.execute('SELECT COUNT(*) FROM installations') installs = c.fetchone()[0] conn.close() return jsonify({ 'registered_devices': devices, 'total_installations': installs }) # ═══════════════════════════════════════════════════════════════ # MAIN # ═══════════════════════════════════════════════════════════════ if __name__ == '__main__': os.makedirs(UPLOAD_FOLDER, exist_ok=True) os.makedirs(SIGNED_FOLDER, exist_ok=True) os.makedirs(CERTS_FOLDER, exist_ok=True) init_db() print("🏔 MontanaSign — iOS Distribution Service") print(" efir.org/install") print("") print(" Модель: LazyShop-style") print(" 1. Пользователь регистрирует UDID") print(" 2. Мы подписываем IPA") print(" 3. Apple не контролирует") print("") app.run(host='0.0.0.0', port=8080, debug=True)