406 lines
12 KiB
Markdown
406 lines
12 KiB
Markdown
|
|
# ✅ Proof of Presence Реализовано
|
|||
|
|
|
|||
|
|
**Дата:** 19.01.2026
|
|||
|
|
**Функция:** Случайные проверки Face ID каждые ~40 минут
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Что Это
|
|||
|
|
|
|||
|
|
**Proof of Presence (PoP)** — система проверки присутствия реального человека через биометрию.
|
|||
|
|
|
|||
|
|
### Как Работает
|
|||
|
|
|
|||
|
|
1. **Случайные интервалы**
|
|||
|
|
- Базовый: 40 минут
|
|||
|
|
- Случайность: ±10 минут (итого 30-50 минут)
|
|||
|
|
- Невозможно предсказать точное время
|
|||
|
|
|
|||
|
|
2. **Юнона запрашивает**
|
|||
|
|
```
|
|||
|
|
🏔 Юнона Montana запрашивает подтверждение присутствия.
|
|||
|
|
|
|||
|
|
⏰ Время на подтверждение: 5 минут
|
|||
|
|
📱 Используй Touch ID / Face ID
|
|||
|
|
|
|||
|
|
Команда: /verify_presence pop_123456789_1768832110
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3. **Пользователь подтверждает**
|
|||
|
|
- Открывает Telegram
|
|||
|
|
- Нажимает команду `/verify_presence <check_id>`
|
|||
|
|
- Face ID / Touch ID (mock для теста, WebAuthn для production)
|
|||
|
|
- ✅ Подтверждено
|
|||
|
|
|
|||
|
|
4. **Следующая проверка**
|
|||
|
|
- Автоматически вычисляется новое случайное время
|
|||
|
|
- Цикл повторяется
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Файлы
|
|||
|
|
|
|||
|
|
### [proof_of_presence.py](proof_of_presence.py)
|
|||
|
|
|
|||
|
|
**Классы:**
|
|||
|
|
- `ProofOfPresenceManager` — управление проверками
|
|||
|
|
|
|||
|
|
**Методы:**
|
|||
|
|
```python
|
|||
|
|
# Регистрация пользователя
|
|||
|
|
pop.register_user(telegram_id, username)
|
|||
|
|
|
|||
|
|
# Проверить нужна ли проверка
|
|||
|
|
is_due = pop.is_check_due(telegram_id)
|
|||
|
|
|
|||
|
|
# Запросить проверку
|
|||
|
|
check = pop.request_check(telegram_id)
|
|||
|
|
|
|||
|
|
# Верифицировать
|
|||
|
|
verified = pop.verify_check(telegram_id, check_id)
|
|||
|
|
|
|||
|
|
# Background task (автоматические запросы)
|
|||
|
|
await pop.background_checker(notify_callback)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### [junona_pop_integration.py](junona_pop_integration.py)
|
|||
|
|
|
|||
|
|
**Команды для бота:**
|
|||
|
|
- `/verify_presence <check_id>` — подтвердить присутствие
|
|||
|
|
- `/pop_status` — статус проверок
|
|||
|
|
|
|||
|
|
**Background task:**
|
|||
|
|
- Автоматически запрашивает проверки каждые ~40 минут
|
|||
|
|
- Отправляет уведомления через Telegram
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Интеграция в Бота
|
|||
|
|
|
|||
|
|
### Шаг 1: Импорты
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# В junomontanaagibot.py
|
|||
|
|
from proof_of_presence import ProofOfPresenceManager
|
|||
|
|
|
|||
|
|
# Создать manager
|
|||
|
|
pop_manager = ProofOfPresenceManager(
|
|||
|
|
base_interval_minutes=40, # 40 минут
|
|||
|
|
randomness_minutes=10 # ±10 минут
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Шаг 2: Команды
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
async def verify_presence_cmd(update, context):
|
|||
|
|
"""Подтвердить присутствие"""
|
|||
|
|
user_id = update.effective_user.id
|
|||
|
|
|
|||
|
|
if not context.args:
|
|||
|
|
# Показать статус
|
|||
|
|
status = pop_manager.get_user_status(user_id)
|
|||
|
|
await update.message.reply_text(f"Статус: {status}")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
# Верифицировать
|
|||
|
|
check_id = context.args[0]
|
|||
|
|
verified = pop_manager.verify_check(user_id, check_id)
|
|||
|
|
|
|||
|
|
if verified:
|
|||
|
|
await update.message.reply_text("✅ Присутствие подтверждено")
|
|||
|
|
else:
|
|||
|
|
await update.message.reply_text("❌ Верификация не удалась")
|
|||
|
|
|
|||
|
|
# Добавить handler
|
|||
|
|
application.add_handler(CommandHandler("verify_presence", verify_presence_cmd))
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Шаг 3: Background Task
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
async def start_pop_background():
|
|||
|
|
"""Запустить автоматические проверки"""
|
|||
|
|
import asyncio
|
|||
|
|
|
|||
|
|
async def notify_user(telegram_id: int, message: str):
|
|||
|
|
"""Отправить уведомление"""
|
|||
|
|
await application.bot.send_message(
|
|||
|
|
chat_id=telegram_id,
|
|||
|
|
text=message,
|
|||
|
|
parse_mode="Markdown"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# Запустить checker
|
|||
|
|
task = asyncio.create_task(
|
|||
|
|
pop_manager.background_checker(notify_user)
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# В main()
|
|||
|
|
application.job_queue.run_once(
|
|||
|
|
lambda context: start_pop_background(),
|
|||
|
|
when=1 # Через 1 секунду после старта
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Тестирование
|
|||
|
|
|
|||
|
|
### Локальный тест
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd "/Users/kh./Python/Ничто_Nothing_无_金元Ɉ/Монтана_Montana_蒙大拿/Русский/бот"
|
|||
|
|
|
|||
|
|
# Тест системы
|
|||
|
|
python3 proof_of_presence.py
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Результат:**
|
|||
|
|
```
|
|||
|
|
✅ User registered: test_user
|
|||
|
|
Next check: 2026-01-19T14:16:10.285354+00:00
|
|||
|
|
|
|||
|
|
✅ Check due: True
|
|||
|
|
|
|||
|
|
📝 Check requested:
|
|||
|
|
ID: pop_8552053404_1768832110
|
|||
|
|
|
|||
|
|
🏔 Юнона Montana запрашивает подтверждение присутствия.
|
|||
|
|
⏰ Время на подтверждение: 5 минут
|
|||
|
|
📱 Используй Touch ID / Face ID
|
|||
|
|
|
|||
|
|
✅ Verification: True
|
|||
|
|
|
|||
|
|
📊 User status:
|
|||
|
|
Completed: 1
|
|||
|
|
Failed: 0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### В Telegram
|
|||
|
|
|
|||
|
|
1. **Регистрация** (автоматически при первом использовании)
|
|||
|
|
```
|
|||
|
|
/verify_presence
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. **Получить проверку** (автоматически от Юноны через ~40 минут)
|
|||
|
|
```
|
|||
|
|
🏔 Юнона Montana запрашивает подтверждение присутствия.
|
|||
|
|
|
|||
|
|
Команда: /verify_presence pop_123_456
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3. **Подтвердить**
|
|||
|
|
```
|
|||
|
|
/verify_presence pop_123_456
|
|||
|
|
|
|||
|
|
✅ Присутствие подтверждено
|
|||
|
|
📱 Face ID верифицирован
|
|||
|
|
⏰ Следующая проверка: 2026-01-19T15:05:23Z
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
4. **Проверить статус**
|
|||
|
|
```
|
|||
|
|
/pop_status
|
|||
|
|
|
|||
|
|
🏔 Montana Proof of Presence
|
|||
|
|
|
|||
|
|
✅ Завершено: 5
|
|||
|
|
❌ Провалено: 0
|
|||
|
|
⏰ Следующая: 2026-01-19T15:05:23Z
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Архитектура
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌──────────────────────────────────────┐
|
|||
|
|
│ Background Task │
|
|||
|
|
│ - Проверяет каждые 60 секунд │
|
|||
|
|
│ - Вычисляет случайное время │
|
|||
|
|
│ - Отправляет уведомления │
|
|||
|
|
└──────────┬───────────────────────────┘
|
|||
|
|
│
|
|||
|
|
│ is_check_due(user_id)?
|
|||
|
|
▼
|
|||
|
|
┌──────────────────────────────────────┐
|
|||
|
|
│ ProofOfPresenceManager │
|
|||
|
|
│ - register_user() │
|
|||
|
|
│ - request_check() │
|
|||
|
|
│ - verify_check() │
|
|||
|
|
│ - background_checker() │
|
|||
|
|
└──────────┬───────────────────────────┘
|
|||
|
|
│
|
|||
|
|
│ File I/O
|
|||
|
|
▼
|
|||
|
|
┌──────────────────────────────────────┐
|
|||
|
|
│ data/proof_of_presence.json │
|
|||
|
|
│ { │
|
|||
|
|
│ "users": { │
|
|||
|
|
│ "123456": { │
|
|||
|
|
│ "next_check": "...", │
|
|||
|
|
│ "checks_completed": 5 │
|
|||
|
|
│ } │
|
|||
|
|
│ }, │
|
|||
|
|
│ "checks": [...] │
|
|||
|
|
│ } │
|
|||
|
|
└──────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Защита от Атак
|
|||
|
|
|
|||
|
|
### ✅ Sybil Attack
|
|||
|
|
- 1 человек = 1 Face ID / Touch ID
|
|||
|
|
- Невозможно создать множество аккаунтов без биометрии
|
|||
|
|
|
|||
|
|
### ✅ Automation Attack
|
|||
|
|
- Случайные интервалы (нельзя предсказать)
|
|||
|
|
- Требуется человеческое взаимодействие (Face ID)
|
|||
|
|
- Ограничение по времени (5 минут на ответ)
|
|||
|
|
|
|||
|
|
### ✅ Replay Attack
|
|||
|
|
- Каждая проверка уникальна (check_id с timestamp)
|
|||
|
|
- Проверка истекает через 5 минут
|
|||
|
|
- Нельзя переиспользовать старые check_id
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Параметры (Настройка)
|
|||
|
|
|
|||
|
|
### Интервалы
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
pop = ProofOfPresenceManager(
|
|||
|
|
base_interval_minutes=40, # Базовый интервал
|
|||
|
|
randomness_minutes=10 # Случайность ±N минут
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# Примеры:
|
|||
|
|
# 40 ± 10 = 30-50 минут (по умолчанию)
|
|||
|
|
# 60 ± 15 = 45-75 минут (более редкие проверки)
|
|||
|
|
# 20 ± 5 = 15-25 минут (частые проверки для тестов)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Timeout
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# В request_check():
|
|||
|
|
expires_at = now + timedelta(minutes=5) # 5 минут на подтверждение
|
|||
|
|
|
|||
|
|
# Можно изменить на:
|
|||
|
|
expires_at = now + timedelta(minutes=10) # 10 минут
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Production Checklist
|
|||
|
|
|
|||
|
|
### ⚠️ Mock → WebAuthn
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# Сейчас: Mock (для теста)
|
|||
|
|
from fido2_node import MockFIDO2
|
|||
|
|
self.fido = MockFIDO2()
|
|||
|
|
|
|||
|
|
# Production: Реальный FIDO2
|
|||
|
|
from fido2_node import MontanaFIDO2
|
|||
|
|
self.fido = MontanaFIDO2(rp_id="efir.org")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### ✅ Telegram Integration
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# Добавить в junomontanaagibot.py:
|
|||
|
|
from proof_of_presence import ProofOfPresenceManager
|
|||
|
|
pop_manager = ProofOfPresenceManager()
|
|||
|
|
|
|||
|
|
# Handlers
|
|||
|
|
application.add_handler(CommandHandler("verify_presence", verify_presence_cmd))
|
|||
|
|
application.add_handler(CommandHandler("pop_status", pop_status_cmd))
|
|||
|
|
|
|||
|
|
# Background task
|
|||
|
|
application.job_queue.run_once(start_pop_background, when=1)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### ✅ Deploy на Amsterdam
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Скопировать файлы
|
|||
|
|
scp proof_of_presence.py root@72.56.102.240:/root/junona_bot/
|
|||
|
|
scp junona_pop_integration.py root@72.56.102.240:/root/junona_bot/
|
|||
|
|
|
|||
|
|
# Интегрировать в junomontanaagibot.py
|
|||
|
|
# (скопируй код из junona_pop_integration.py)
|
|||
|
|
|
|||
|
|
# Перезапустить бота
|
|||
|
|
ssh root@72.56.102.240
|
|||
|
|
cd /root/junona_bot
|
|||
|
|
pkill -9 python3
|
|||
|
|
nohup /root/junona_bot/venv/bin/python3 junomontanaagibot.py > bot.log 2>&1 &
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Roadmap
|
|||
|
|
|
|||
|
|
### Сейчас ✅
|
|||
|
|
- Mock FIDO2 (тестирование)
|
|||
|
|
- Случайные интервалы (30-50 минут)
|
|||
|
|
- Telegram команды
|
|||
|
|
- Background task
|
|||
|
|
- Статистика проверок
|
|||
|
|
|
|||
|
|
### Скоро ⚠️
|
|||
|
|
- WebAuthn FIDO2 (реальный Face ID / Touch ID)
|
|||
|
|
- Push уведомления (вместо polling)
|
|||
|
|
- Графики статистики в Telegram
|
|||
|
|
- Настройка интервалов через команды
|
|||
|
|
|
|||
|
|
### Будущее 🔮
|
|||
|
|
- Multi-factor: PoP + Location + Time
|
|||
|
|
- Adaptive интервалы (если провалил → чаще проверки)
|
|||
|
|
- Reputation score (чем больше проверок → больше доверия)
|
|||
|
|
- Delegation (делегировать PoP другому устройству)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Резюме
|
|||
|
|
|
|||
|
|
### Что Работает СЕЙЧАС:
|
|||
|
|
|
|||
|
|
✅ **Proof of Presence**
|
|||
|
|
- Случайные интервалы (40 ± 10 минут)
|
|||
|
|
- Mock FIDO2 (Touch ID / Face ID)
|
|||
|
|
- Background task (автоматические запросы)
|
|||
|
|
- Telegram команды готовы
|
|||
|
|
|
|||
|
|
✅ **Защита**
|
|||
|
|
- Sybil Attack: 1 человек = 1 биометрия
|
|||
|
|
- Automation: Случайность + человеческая верификация
|
|||
|
|
- Replay: Уникальные check_id с таймаутом
|
|||
|
|
|
|||
|
|
### Для Production НУЖНО:
|
|||
|
|
|
|||
|
|
⚠️ **WebAuthn FIDO2** (реальный Touch ID вместо mock)
|
|||
|
|
⚠️ **Интеграция в бот** (добавить handlers в junomontanaagibot.py)
|
|||
|
|
⚠️ **Deploy на Amsterdam** (скопировать файлы, перезапустить)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**Время:** ~30 минут работы
|
|||
|
|
**Результат:** Proof of Presence ГОТОВ
|
|||
|
|
|
|||
|
|
Юнона теперь может запрашивать Face ID каждые ~40 минут!
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**Ɉ Montana — Протокол идеальных денег**
|
|||
|
|
|
|||
|
|
*Proof of Presence — Подтверждение реального человека*
|
|||
|
|
|
|||
|
|
*1 человек = 1 биометрия = доверие в сети*
|