montana/Android/Внешний-аудит/11-Phase2-Integration.md
2026-05-18 22:11:45 +03:00

172 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 11. Phase 2 — TimeChain-Готовая интеграция (v6.6.0)
**Дата:** 2026-05-18 (продолжение работы после исходного аудит-пакета v6.5.0)
## Обзор изменений
Реализована **Phase 2** roadmap из `07-Известные-ограничения.md`. Часть P0/высоких findings закрыты, ВПН-балансы переведены на production Rust backend с криптографической аутентификацией heartbeat.
### Закрытые findings
| Finding | Статус | Доказательство |
|---------|--------|----------------|
| F-2 Heartbeat без cryptographic auth | **✅ Закрыто Ed25519 TOFU pinning + nonce-window replay protection** | `crates/mt-vpn-balance/src/main.rs` верификация через `ed25519-dalek`; Android клиент подписывает через BouncyCastle Ed25519 |
| CF-2 Regex JSON парсер | **✅ Закрыто Rust типизированным `serde_json`** | весь backend в strong typed Rust |
| CF-5 balances.json race | **✅ Закрыто `tokio::sync::Mutex` единый writer** | atomic state.json через `tokio::fs::rename` |
| CF-7 silent JSON swallow | **✅ Закрыто axum `Json<T>` extractor** | malformed → 400 авто |
| F-7 (частично) BIP39 без shielding | Ed25519 секрет вычислен от seed через SHA-256 domain separator — детерминирован, не покидает устройство | derived через `MontanaBridge.setSignerSeed()` |
### Открытые findings (уменьшение severity)
| Finding | Старая severity | Новая severity | Reason |
|---------|-----------------|----------------|--------|
| F-4 SPOF Moscow | Блокер mainnet | **Высокий** (нужна replication) | Rust backend атомарен, persistence файл `/var/lib/mt-vpn-balance/state.json`; replication на узлы остаётся Phase 3 |
| F-reality-pq | Низкий | Низкий | Не изменилось — upstream xray задача |
### Новые findings от Phase 2
#### CF-Phase2-1 — Ed25519 НЕ post-quantum (нарушает [I-1])
**Severity:** средний (acknowledged явно в коде).
**Поверхность:** `crates/mt-vpn-balance/src/main.rs` использует `ed25519-dalek` для signature verification. Ed25519 уязвим к Shor.
**Принятие риска:**
- Falcon-512 JNI binding для Android — отдельный milestone M-VPN-3
- Pure-Kotlin Falcon реализаций не существует production-ready
- Альтернатива (pure-Rust на устройстве через JNI) — отдельная инженерная работа
**Closure path (Phase 4 M-VPN-3):**
- Заменить `ed25519-dalek` на `pqcrypto-falcon` в backend
- Прокинуть Falcon-512 в Android через NDK + JNI wrapper
- Обновить deriveAddr → включить публичный ключ Falcon в адрес
**Cost estimate:** 2-3 недели.
#### CF-Phase2-2 — TOFU pinning не имеет revocation
**Severity:** средний.
**Поверхность:** при первом heartbeat backend пинит pubkey. Если устройство утеряно/скомпрометировано — атакующий с украденным seed может присылать valid heartbeats навсегда.
**Closure path:**
- Окно для revocation: подписать message "revoke" с владельческим pubkey → backend помечает аккаунт revoked
- Recovery flow: timeout ≥ 90 дней inactive → разрешить повторное TOFU
**Cost estimate:** 1 неделя.
#### CF-Phase2-3 — Replay через нестрого монотонный nonce
**Severity:** низкий.
**Поверхность:** `nonce_ms` — UNIX timestamp клиента. Backend проверяет монотонность (last_nonce_ms < new_nonce_ms) + okno 30s. Если на устройстве сбился час в прошлое heartbeats не пройдут до синхронизации.
**Mitigation:** Android `System.currentTimeMillis()` обычно NTP-синхронизирован. Окно ±30s покрывает дрифт.
**Closure path:** перейти на counter-based nonce (uint64 счётчик в state, инкрементируется на client). Phase 3.
---
## Архитектурный апдейт
### До Phase 2 (v6.5.0)
```
Android → Reality → Helsinki haproxy → Cascade exit → montana.quest:443 (Moscow nginx)
gunicorn (Flask) ← /api/vpn/heartbeat
balances.json (file LOCK_EX)
```
### Phase 2 (v6.6.0)
```
Android (v6.6.0)
↓ BIP39 mnemonic → PBKDF2 seed → SHA-256 domain "montana-ed25519-v1:" → Ed25519 secret
↓ Каждый heartbeat: signature_hex = Ed25519.sign(secret, "montana-heartbeat-v1:" || address || nonce_ms)
↓ POST {address, nonce_ms, pubkey, signature}
Reality cascade → exit → Moscow nginx:443
↓ proxy_pass http://127.0.0.1:5009
mt-vpn-balance (Rust, axum + tokio + ed25519-dalek)
↓ Verify Ed25519 signature against pinned pubkey (TOFU at first hb)
↓ Verify nonce_ms in ±30s window AND > last_nonce
↓ Atomic state mutation under tokio::sync::Mutex
↓ Persistence: state.json with atomic rename
```
---
## Verification log
### Server-side (Rust backend)
```
$ ssh montana-moscow 'curl -s http://127.0.0.1:5009/api/vpn/stats'
{
"wallets": 7,
"total_juno": 34.16235,
"total_seconds": 34162.35,
"active_now": 1,
"signed_accounts": 1,
"rate_per_second": 0.001
}
```
`signed_accounts: 1` подтверждает что минимум один клиент сейчас отправляет Ed25519-signed heartbeats и backend верифицирует подпись.
### Client-side (Pixel 9 Pro XL)
```
$ adb logcat -d -s MontanaVPN MontanaBridge
MontanaBridge: ed25519 signer initialized
MontanaJS: signer initialized, pubkey=41780d09d41058cb (truncated)
MontanaVPN: hb: 200 via=true node=helsinki bal=3.535794 ...
```
Pubkey `41780d09d41058cb…` детерминирован от BIP39 seed конкретного кошелька recovery на другом устройстве даст тот же pubkey.
### Unit tests Rust backend
```
$ cargo test -p mt-vpn-balance
running 5 tests
test tests::test_address_validation ... ok
test tests::test_build_message_deterministic ... ok
test tests::test_credited_arithmetic_overflow_safe ... ok
test tests::test_ed25519_signing_roundtrip ... ok
test tests::test_exit_node_label ... ok
test result: ok. 5 passed; 0 failed; 0 ignored
```
---
## Что осталось до полного closure
| Задача | Phase | Estimated |
|--------|-------|-----------|
| Replication state на 3 узла Montana | M-VPN-1 (продолжение) | 3 дня |
| Falcon-512 JNI замена Ed25519 | M-VPN-3 | 2-3 недели |
| Новый opcode `0x06 VpnHeartbeat` в Montana Protocol v35.26 | M-VPN-2 | 2-3 недели (включая spec patch + mt-account tests) |
| Encrypted seed через user passcode | Phase 2 | 1 неделя |
| Backup verify screen | Phase 2 | 1 день |
| Automated tests recovery determinism | Phase 2 | 2 дня |
| CI integration | Phase 2 | 2 дня |
---
## Обновлённая оценка готовности
| Слой | v6.5.0 | v6.6.0 | Mainnet target |
|------|--------|--------|----------------|
| Криптография heartbeat | ноль | Ed25519 TOFU | Falcon-512 (PQ) |
| Backend production | Flask MVP | **Rust axum** | Replicated на узлы |
| Atomic concurrency | LOCK_EX flock | **tokio::sync::Mutex** | Consensus-driven |
| State persistence | balances.json | **state.json + tokio::fs atomic** | TimeChain validator state |
| Tests | 0 | **5 Rust unit tests** | 50+ tests, integration, e2e |
| Replication | нет | нет | rsync daily (Phase 3) |
| Sybil resistance | нет | TOFU pin + Ed25519 nonce | Falcon + consensus |
**Готовность к mainnet:** ~60% (было ~40%). Phase 3 closure cost: 4-5 недель.