Захищене відео через наявний аналоговий відеотракт
Відтворення схеми ISITIA 2021 · демонстрація її меж · заміна на стандартній криптографії
з експериментальним порівнянням за фіксованого бюджету на синтетичних і природних кадрах
Швидкий старт · Як це працює · Формули · Результати · Завдання ISITIA 2021 · Road map · Висновки · Каталог схем · B2s: заміна · B2l: стала яскравість · Твердження · Межі застосовності · Словник · Карта документації
Завдання: відтворити схему захисту відеоканалу БпЛА зі статті ISITIA 2021, показати її межі й запропонувати вдосконалення.
Відповідь одним документом:
Документ читається окремо від решти репозиторію і містить чотири розділи:
Частина Що в ній Перевірити 1. Реконструкція будова B1: регістр зсуву з лінійним зворотним зв'язком (LFSR), сітка 12×16, таблиця перестановки; репліка таблиць I–III вихідної публікації для початкових станів 44257, 1234, 1111run.bat lab2. Випробування на зображеннях застосування реконструкції B1до чотирьох фрагментів аерофотографії: вихідне, скрембльоване та відновлене зображенняrun.bat lab3. Криптоаналіз пʼять атак із зазначенням моделі загроз, результату й часу; перебір визначає заданий початковий стан регістра 44257 за 5,13 с avsec attack4. Модифікації ланцюжок B1 → B2 → B3 → B4 → B4t/P: кожен крок відповідає конкретній вразливості з розділу 3, із зазначенням вартостіrun.bat researchОсновні числові результати:
- репліка таблиць вихідної публікації дає середню подібність 3,70 % проти 3,94 % у публікації; за незмінного початкового стану регістра розкид по чотирьох фрагментах аерофотографії становить 6,55 відсоткового пункту, тобто показник характеризує пару «алгоритм — набір зображень»;
- перебір реалізованого простору початкових станів визначає заданий стан 44257 за 5,13 с;
- збирання за сумісністю меж без знання ключа дає 94,94 % правильних сусідств при 0,00 % правильних абсолютних позицій, тобто витік структури, а не повне розкриття кадру.
Одна команда відтворює розділи 1–2 і записує результат у
results/lab/:run.bat lab # або ./run.sh lab
Important
Основний результат роботи — негативний.
Переналаштована проста база (B4t) перевершує запропоновану схему (P) у
кожному каналі кожного з трьох наборів даних. Два запропоновані механізми —
кілька описів і burst-aware розміщення — не покращують наскрізну якість і
навіть не вміщуються в бюджет без тих самих змін транспорту, які й дають
увесь виміряний виграш. Подробиці: ROADMAP,
висновки §6.
Вихідна стаття — Mardiyanto R., Suryoatmojo H., Setiawan F., Irfansyah A. N. Low Cost Analog Video Transmission Security of Unmanned Aerial Vehicle (UAV) based on Linear Feedback Shift Register (LFSR), ISITIA 2021, с. 414–419, DOI 10.1109/ISITIA52817.2021.9502241 — пропонує захищати відеоканал дрона перестановкою блоків кадру за послідовністю LFSR.
Цей репозиторій робить три речі:
- Відтворює цей алгоритм (метод
B1) і показує його межі: обраний кадр відновлює перестановку повністю за 1,3 мс; одна відома пара — теж повністю на гладкому й текстурному вмісті. А на гладкому вмісті — типовому для аерозйомки — впізнаване зображення (24,7 дБ) відновлюється взагалі без ключа і без відомої пари, лише з переданого зображення. - Будує заміну на стандартній криптографії (
B3,B4,P): дані шифруються AEAD і передаються через той самий аналоговий тракт як рівні яскравості. - Вимірює, що саме це дає і чого коштує — 183 600 моментів показу на трьох наборах даних (з них один — 24 незалежні знімки з БпЛА), 56 рисунків, і окремий розділ про те, де запропонована схема програє. Вона програє переналаштованій простій базі в кожному каналі кожного набору, і це головний результат, а не застереження до нього.
Гібридна архітектура. Аналоговими лишаються сигнал на композитному інтерфейсі та сам тракт передавання. Уся обробка до передавача і після приймача — цифрова:
flowchart LR
subgraph TX["Передавач (на борту)"]
A["Камера<br/>кадр 256×192"] --> B["Джерельне<br/>кодування"]
B --> C["AEAD<br/>ChaCha20-Poly1305"]
C --> D["Reed–Solomon<br/>GF(256)"]
D --> E["Розміщення<br/>в растрі"]
E --> F["Модулятор<br/>рівні яскравості"]
end
F --> G(["АНАЛОГОВИЙ ТРАКТ<br/>CVBS 625/50"])
subgraph RX["Приймач (на землі)"]
G --> H["Демодулятор<br/>+ синхронізація"]
H --> I["Reed–Solomon<br/>виправлення"]
I --> J["Перевірка AEAD<br/>тег 128 біт"]
J --> K["Складання<br/>кадру"]
K --> L["Показ<br/>+ карта віку"]
end
style G fill:#ffe0b2,stroke:#e65100,stroke-width:3px
style C fill:#c8e6c9,stroke:#2e7d32
style J fill:#c8e6c9,stroke:#2e7d32
Базові методи B0a, B1, B2 навпаки передають саме зображення аналоговим
растром — це опора для порівняння, а не захищений режим.
git clone https://github.com/RE22GDV/avsec.git
cd avsec
run.batgit clone https://github.com/RE22GDV/avsec.git
cd avsec
chmod +x run.sh
./run.shПерший запуск сам створює .venv, ставить залежності і відкриває веб-інтерфейс
на http://127.0.0.1:8765/. Більше нічого робити не треба.
| Команда | Що робить |
|---|---|
run.bat / ./run.sh |
веб-інтерфейс (за замовчуванням) |
run.bat demo |
один кадр через усі методи, із зображеннями |
run.bat test |
увесь набір тестів |
run.bat check |
перевірка датасету + 35 перевірок протоколу |
run.bat research |
повна програма досліджень (≈1 година, відновлювана) |
run.bat budget |
бюджет каналу, затримка, пам'ять |
python -m venv .venv
# Windows: .venv\Scripts\activate
source .venv/bin/activate
pip install -r requirements.txt # або requirements-dev.txt із тестами
pip install -e .
avsec infoПотрібен Python 3.10+. Без встановлення пакета теж працює:
PYTHONPATH=src python -m avsec.cli infoПро версію Python. Лаунчер свідомо обирає не найновіший інтерпретатор, а перший із 3.12 → 3.11 → 3.10. Найсвіжіший Python зазвичай випереджає наявність готових пакетів numpy/scipy, і тоді
pipнамагається збирати scipy з джерел — на звичайному ПК це падає через відсутній компілятор Fortran. Щоб примусово задати інтерпретатор:set AVSEC_PYTHON=py -3.12 run.batAVSEC_PYTHON=python3.12 ./run.sh
Залежності і навіщо кожна
| Пакет | Навіщо |
|---|---|
numpy |
увесь сигнальний тракт |
scipy |
фільтрація, вікна SSIM, ресемплінг |
cryptography |
ChaCha20-Poly1305 / AES-256-GCM, HKDF-SHA256 |
reedsolo |
Reed–Solomon над GF(256) |
opencv-python |
читання й масштабування зображень |
Pillow |
формати, яких не покриває OpenCV |
PyYAML |
конфігурації |
matplotlib |
рисунки PNG 300 dpi / SVG / PDF |
Жоден криптографічний примітив тут не написаний власноруч. AEAD береться з
cryptography (обгортка OpenSSL), Reed–Solomon — з reedsolo. Це свідоме
рішення: див. docs/threat_model.md.
|
Десять методів в одному бюджеті
Дві схеми з окремими стендами
Два рівні моделі каналу Рівень A — растрові спотворення; рівень B — справжня форма CVBS 625/50. Атаки на бази Обраний кадр, відома пара, складання за межами, багатокадрова, перебір seed. |
35 перевірок протоколу Мутація кожного семантичного поля, межі парсера, повтори, зрив стану сеансу. Відновлюваний матричний прогін
Веб-інтерфейс: 14 вкладок Усі експерименти, обидві схеми з окремими стендами, обчислена таблиця замін над GF(2⁸), шифрування зі сталою яскравістю, усі перевірки проєкту та перегляд збережених прогонів. |
Демонстрація на реальному кадрі з дрона: метрики всіх методів і чотири стадії тракту для кожного
Ще скріншоти
Схема B2l: панель 3 — весь сигнал, який дістається монохромного тракту (рівне сіре поле),
а нижче — наскрізний прогін за пʼятьма профілями каналу
Таблиця замін над GF(2⁸): звірка з опублікованою таблицею AES побайтово,
виміряні властивості та розгортка за всіма 30 незвідними многочленами степеня 8
Схема B2s: стадії перетворення, таблиця замін 16×16 і обернена до неї,
підсилення похибки та атаки на B2 і на B2s поруч
Усі перевірки в одному місці: протокол, паспорт набору даних, перерахунок
опублікованих чисел, посилання й формули документації
Перегляд збереженого прогону: фільтри, парні порівняння, окремі сцени, готовність рисунків
Бюджет каналу: точний облік накладних витрат, модельна затримка, три величини пам'яті
Одиниця захисту — не кадр, а сегмент. Кадр ріжеться на смуги, кожна смуга кодується, шифрується і захищається окремо, тож втрата однієї не руйнує решту:
flowchart TD
F["Кадр 256×192"] --> S["Нарізка на смуги<br/>по 24 рядки"]
S --> C1["Смуга 1"] & C2["Смуга 2"] & CN["… Смуга 8"]
C1 --> D1["DCT + квантування"]
D1 --> U1["Одиниця:<br/>заголовок 56 Б<br/>+ payload<br/>+ тег 16 Б"]
U1 --> R1["RS(k+nsym)"]
C2 --> D2["DCT"] --> U2["Одиниця"] --> R2["RS"]
CN --> DN["DCT"] --> UN["Одиниця"] --> RN["RS"]
R1 & R2 & RN --> P["Розміщення BAWP<br/>у растрі"]
P --> M["Модуляція:<br/>4 рівні, комірка 8×2 px"]
M --> T(["Аналоговий тракт"])
style U1 fill:#c8e6c9,stroke:#2e7d32
style T fill:#ffe0b2,stroke:#e65100,stroke-width:3px
┌────────────────────────────────────┬──────────────────┬──────────┐
│ ЗАГОЛОВОК (56 Б, автентифікований) │ ШИФРОТЕКСТ │ ТЕГ 16 Б │
├────────────────────────────────────┤ (payload 320 або │ │
│ magic 2 · version 1 · algo 1 │ 640 байт) │ Poly1305 │
│ session_id 8 · session_epoch 4 │ │ ніколи │
│ stream 1 · dir 1 · frame_id 4 │ │ не │
│ seg_id 2 · desc_id 1 · n_desc 1 │ │ урізаний │
│ counter 8 · geometry 8 · CRC 4 │ │ │
└────────────────────────────────────┴──────────────────┴──────────┘
↑ входить в AAD цілком ↑ ChaCha20-Poly1305
Заголовок передається у відкритому вигляді (приймачу треба знати, куди складати смугу), але цілком входить до AAD: змінити в ньому хоч один біт — означає не пройти перевірку тега.
flowchart TD
A["Вхід: растр R×C комірок,<br/>D описів, очікуваний пакет B рядків"] --> B["Розбити вікно W на смуги:<br/>G = max(1, min(D, ⌊W/B⌋))"]
B --> C["Висота смуги h = ⌊W/G⌋"]
C --> D{"Для кожної одиниці<br/>з описом d"}
D --> E["Смуга = d mod G"]
E --> F{"Є місце<br/>у смузі?"}
F -->|так| G["l-й символ →<br/>рядок = r₀ + (l mod h)<br/>стовпець = ((l div h) + σ·(l mod h)) mod C"]
F -->|ні, strict_isolation| X["ВІДМОВА<br/>PlacementError"]
F -->|ні, звичайний режим| Y["Перелив у наступну смугу<br/>+ позначка spilled=True<br/>ГАРАНТІЯ ІЗОЛЯЦІЇ НЕ ДІЄ"]
G --> D
Y --> D
style X fill:#ffcdd2,stroke:#b71c1c
style Y fill:#fff9c4,stroke:#f9a825
style G fill:#c8e6c9,stroke:#2e7d32
Межа гарантії: умова «пакет зачіпає не більше двох смуг» виконується лише поки немає переливу. Контрприклад, за якого вона порушується, знайдено, відтворено в тесті й описано в docs/revision_history.md (дефект F12).
flowchart TD
A["Символи з демодулятора<br/>+ прапорці стирань"] --> B["RS-декодування заголовка"]
B -->|невдача| R1["ВІДХИЛИТИ<br/>header_fec_failed"]
B --> C["Розбір заголовка"]
C -->|version ≠ 2| R2["ВІДХИЛИТИ<br/>unknown_version"]
C --> D["RS-декодування даних"]
D -->|невдача| R3["ВІДХИЛИТИ<br/>payload_fec_failed"]
D --> E["Пошук сеансу<br/>(ТІЛЬКИ читання кешу)"]
E --> F["Перевірка AEAD<br/>тег + AAD = заголовок"]
F -->|тег не збігся| R4["ВІДХИЛИТИ<br/>auth_failed"]
F --> G{"Лічильник<br/>у вікні?"}
G -->|ні| R5["ВІДХИЛИТИ<br/>replay"]
G --> H["ЗАРАХУВАТИ сеанс у кеш<br/>(лише тут!)"]
H --> I["Смуга → буфер складання<br/>вік = 0"]
style F fill:#c8e6c9,stroke:#2e7d32
style H fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px
style R4 fill:#ffcdd2,stroke:#b71c1c
Порядок «перевірити → потім змінити стан» — не деталь. У першій версії кеш сеансів змінювався до автентифікації, тож вісім підроблених заголовків витісняли справжній сеанс і далі приймався повтор (дефект F01, критичний).
flowchart LR
MS["Майстер-секрет<br/>32 Б"] --> HKDF["HKDF-SHA256<br/>info = 'avsec/v2' ‖ session_id ‖ epoch ‖ stream ‖ dir"]
HKDF --> K["Ключ сеансу<br/>32 Б"]
HKDF --> NP["Префікс nonce<br/>4 Б"]
NP --> N["Nonce 12 Б =<br/>префікс ‖ лічильник 8 Б"]
K --> AEAD["ChaCha20-Poly1305"]
N --> AEAD
style MS fill:#ffcdd2,stroke:#b71c1c
style AEAD fill:#c8e6c9,stroke:#2e7d32
Лічильник монотонний і резервується наперед у довговічному стані: після перезапуску передавач продовжує з зарезервованої позиції, а не з нуля. Плюс 32-бітова епоха сеансу входить і в AAD, і в KDF — повторне використання nonce неможливе навіть після втрати стану (дефекти F02, F03).
flowchart LR
P["configs/*.yaml<br/>план"] --> M["avsec matrix<br/>завдання = кліп×метод×<br/>канал×повтор"]
M --> RAW[("runs/RUN/<br/>frames.csv<br/>units.csv<br/>channel_traces.jsonl")]
RAW --> A["avsec analyze<br/>кластерний bootstrap<br/>поправка Holm"]
A --> TAB[("summary.csv<br/>paired_effects.csv<br/>operability.csv")]
TAB --> F["avsec plots<br/>K01–K13 + G01–G43"]
TAB --> PUB["scripts/publish.py"]
F --> FIG[("figures/<br/>PNG+SVG+PDF<br/>+CSV +JSON")]
PUB --> DOC["docs/results.md<br/>docs/figures.md<br/>README"]
style RAW fill:#e3f2fd
style TAB fill:#e8f5e9
style FIG fill:#fff3e0
Кожне опубліковане число походить з одного run_id, який записано у файл
разом із ним. Слова «значуще» і «перевага» вибирає код за фактичним довірчим
інтервалом, а не автор.
Note
Формули записані простим текстом у моноширинному блоці — так вони видно в будь-якому переглядачі Markdown, а не лише там, де працює LaTeX. Під кожною згорнуто джерело LaTeX: його можна скопіювати в статтю.
Якість і покриття
Середньоквадратична похибка і PSNR по всьому показаному кадру:
1 H-1 W-1 2
MSE = ─────── ∑ ∑ ( I(y,x) − Î(y,x) )
H·W y=0 x=0
255²
PSNR = 10 · log₁₀ ───────
MSE
LaTeX
За MSE = 0 PSNR нескінченний. Такі кадри рахуються окремо (bit_exact), а
не підмінюються скінченною сталою на кшталт 99 дБ.
Поточне автентифіковане покриття — головна метрика захищеного тракту:
| { (y,x) : піксель з одиниці, що пройшла AEAD у ЦЬОМУ кадрі } |
cov = ───────────────────────────────────────────────────────────────
H · W
LaTeX
Старі пікселі (з попереднього кадру) і домальовані інтерполяцією не входять.
Для B0a, B1, B2 значення cov = 1 означає лише «зображення відображено».
Розміщення BAWP
Вікно висотою W символьних рядків ділиться на смуги:
G = max( 1, min( D, ⌊ W / B ⌋ ) ) h = ⌊ W / G ⌋
де D — число описів, B — очікувана висота пакета пошкодження.
Усередині смуги з рядками [r₀, r₀+h) і C стовпцями l-й символ потрапляє
у комірку:
row = r₀ + ( l mod h )
col = ( ⌊ l / h ⌋ + σ · ( l mod h ) ) mod C
LaTeX
Це бієкція на комірки смуги для l < h·C. Пакет висотою b ≤ h символьних
рядків руйнує щонайбільше
b · ⌈ n / h ⌉
символів будь-якого кодового слова довжини n — за умови, що слово лежить
усередині однієї смуги. Фактичний максимум рахується вичерпним перебором усіх
початкових позицій пакета, а не за цією межею.
Одиниці виміру пакета — де ховається помилка
Чотири різні «одиниці» плутати не можна. Саме на цьому переході стався дефект R03, і він змінив висновок роботи:
L рядків растру ──▶ ⌊ L / h_симв ⌋ + 1 ──▶ символи ──▶ байти
символьних рядків модуляції RS
└──── канал ────┘ └───── модем ──────┘ └ 2 біти ┘ └ GF(256) ┘
кожен
- Додаткова одиниця в другому переході — бо пакет, що не починається на межі комірки, зачіпає на один символьний рядок більше.
- Чотири клітинки модема — один байт, а не чотири: за 2 біт на клітинку ділення на 4 обов'язкове.
- Одиниця транспорту — не одне кодове слово, а п'ять: заголовок плюс блоки payload, кожен зі своїм бюджетом виправлення.
Порахувати клітинки, назвати їх байтами і порівняти суму з бюджетом одного
слова — це три помилки поспіль. Саме так і було до
R03; тепер перерахунок робить
avsec.damage, а його вирок звірено зі справжнім
декодуванням Ріда — Соломона.
LaTeX
Reed–Solomon і бюджет
Код RS(k + nsym, k) над GF(256) виправляє t помилок і e стирань, поки
2·t + e ≤ nsym
Стирання (позиція відома з прапорця демодулятора) коштує вдвічі дешевше за помилку — тому модем позначає непевні комірки, а не вгадує їх.
Розмір одиниці «на дроті» і корисна швидкість:
wire = RS_hdr(56) + RS_pay(payload + 16)
└заголовок┘ └─── дані + тег ───┘
u · payload · 8
R_корисна = ──────────────────────
T_растру
LaTeX
де u — скільки одиниць реально вміщується в растр після розміщення (не за
сирою місткістю).
Затримка — різниця, а не сума
latency( f ) = t_display( f ) − t_capture( f )
LaTeX
Саме різниця позначок часу на віртуальному годиннику. Сума тривалостей
етапів дала б завищену оцінку, бо етапи перекриваються: поки серіалізується
растр k, смуга k+1 уже накопичується. Для поточного профілю різниця між
цими двома числами — 175 мс зі 334 (дефект F16).
Статистика
Порядок усереднення зафіксований, і канали в нього не входять:
кадри ──mean──▶ повтори ──mean──▶ кліпи ──mean──▶ сцени ──mean──▶ джерела
Одиниця незалежності оголошується у плані: scene узагальнює на нову сцену тих
самих записів, source — на новий запис.
Парне порівняння двох методів — кластерний bootstrap за одиницями незалежності (10⁴ ресемплів):
1 S
Δ̂ = ─── ∑ ( x̄ᴬ_s − x̄ᴮ_s )
S s=1
CI₉₅ = [ Δ⁽²·⁵﹪⁾ , Δ⁽⁹⁷·⁵﹪⁾ ]
LaTeX
Одиниці, де немає результату одного з методів, виключаються й перелічуються, а не обрізаються за індексом. p-value походить з двобічного bootstrap-тесту на самих парних різницях, а не з ширини інтервалу; для наперед оголошеної сім'ї застосовується поправка Holm, а відсутність значущості окремо відрізняється від доведеної еквівалентності (TOST).
| Джерело | Curonian Spit NP, аерофотознімок біля дюни Ефа, 12.05.2017 |
| Автор | A.Savin, Wikimedia Commons |
| Камера | DJI FC6310 (сенсор Phantom 4 Pro) — справжній дрон |
| Роздільність | 4213 × 2633, повний кадр камери, не перекодований у цьому репозиторії |
| Ліцензія | Free Art License 1.3 — вільне використання з атрибуцією |
Це JPEG, бо саме його записала камера і саме він доступний під вільною ліцензією; вільного RAW з дрона зіставної якості не існує. Тому у звітах написано «оригінал камери», а не «нестиснений».
17 послідовностей зі штучним рухом вікна. Вікно кадрування панорамує фотографією між оголошеними наперед прямокутниками. Це справжній вміст, але рух — наш: паралакса, скошування рядків, адаптації експозиції й руху в сцені тут немає, і жодне твердження в репозиторії на них не спирається.
Контент навмисно різний: гладке море й небо (майже плоскі), крона сосон (найважча текстура кадру), берегова лінія і край дюни (довгі контрастні межі), село (поле дрібних яскравих об'єктів).
Це один запис, а не сімнадцять. Усі 17 кліпів мають спільний
source_id: спільний сенсор, об'єктив, година доби, погода й місцевість. Bootstrap по цих сценах оцінює невизначеність усередині цієї фотографії і не узагальнюється на новий запис. Тому весь знімок тримається як test: ділити одну фотографію на calibration/validation/test не має сенсу, іavsec dataset validateтепер позначає таку спробу як помилку. Нічого на цьому знімку не налаштовувалося — конфігурації взято з синтетичного набору. Перекриття вирізок вимірюється геометрично і записується в маніфест (crop_overlaps); 63 пари зі 136 справді перетинаються, і ми цього не приховуємо.
python scripts/fetch_drone_photo.py # перевірити або завантажити фотоЩоб висновок міг стосуватися нового запису, а не нової вирізки з того
самого, потрібні різні записи. Реєстр data/real/sources.json містить 24
аерофотознімки з Wikimedia Commons: 24 різні автори, 9 моделей камер DJI
(Phantom 3 Pro, Phantom 4, Phantom 4 Pro, Mavic Pro, Mavic Air, Mavic Air 2,
Mini 2, Mini 3 Pro, Inspire 2/X5S), різні місця, вільні ліцензії (CC0,
CC BY-SA). З кожної фотографії береться один кліп, тож «більше даних» тут
означає «більше знімків».
| Одиниця незалежності | вихідна фотографія (source_id) |
| Розподіл | 14 test / 5 calibration / 5 validation — за джерелом |
| Категорії | призначені за виміряною градієнтною енергією знімка, до будь-якого результату |
| Файли | рендери Wikimedia з камерних оригіналів (не самі оригінали — сервіс просить не тягнути оригінали пакетно); у реєстрі записано URL, ліцензію, автора, камеру й sha256 того файла, з якого рахувалися числа |
| У репозиторії | лише реєстр; 63 МБ знімків завантажуються командою нижче |
python scripts/fetch_natural_sources.py # завантажити й звірити хеші
avsec dataset validate --config configs/research_natural.yamlПовний перелік усіх 24 знімків — автор, апарат, ліцензія, роздільність, split і sha256 — у паспорті наборів даних.
34 процедурні сцени (20 тестових, 8 калібрувальних, 6 валідаційних) — горизонт, дорога, цілі, текстура, краї, хмари, сітка, слабке освітлення, текст. Кожна має власну точку зйомки й експозицію, тож це різні сцени, а не одна двічі.
avsec dataset validate --config configs/research_main.yamlПеревага запропонованої схеми залежить від каналу. P значуще краща за B4 на bursty і значуще гірша на clean, mild. Загального виграшу немає, і це головний результат прогону, а не застереження до нього. Покроковий розклад цієї різниці (E13) показує, що її дають параметри транспорту (+4.18 дБ), тоді як самі запропоновані механізми — кілька описів і BAWP — дають -1.00 дБ. Пройдений у зворотному порядку, цей розклад не існує взагалі: при вихідному розмірі одиниці механізми не вміщуються в бюджет, тобто вони не є самостійним доповненням до базової схеми. Переналаштована база B4t — та сама схема з транспортом P, але без обох механізмів — значуще перевершує P в усіх 4 каналах, де різниця встановлена (-1.19…-1.53 дБ).
Усі числа нижче походять з одного прогону: run_id=fe45d509310b99d4, commit 25534623fc247da4a07c7238f46cae4b068b68b3, Windows-11-10.0.26200-SP0, Python 3.12.10, NumPy 2.5.3. Матеріал: 34 кліпів / 34 сцен усього, з них 20 у цьому прогоні (split test); синтетичні дані.
- Обсяг: 72000 оброблених кадрів, 20 незалежних сцен, 5 профілів каналу, 9 методів.
clean: P − B4 = -3.45 дБ [-3.89; -2.93] за 18 сценами — значуще, перевірене покриття 1.000 проти 1.000.mild: P − B4 = -3.45 дБ [-3.89; -2.93] за 18 сценами — значуще, перевірене покриття 1.000 проти 1.000.moderate: P − B4 = -0.27 дБ [-0.72; +0.23] за 18 сценами — різниця не встановлена, перевірене покриття 0.956 проти 0.875.bursty: P − B4 = +1.50 дБ [+0.65; +2.44] за 18 сценами — значуще, перевірене покриття 0.809 проти 0.742.harsh: жоден метод не дав жодного придатного моменту показу — порівнювати нічого.- Перевірки протоколу: 35/35 пройдено.
- Бюджет: B4 — 0.512 Мбіт/с корисних даних (ефективність 0.485), P — 0.384 Мбіт/с (0.363); модельна затримка 159 мс, логічний буфер 68.5 кБ.
- Рисунки: 56 з 56 (вісім основних, решта — додаткові матеріали) — усі побудовано.
- Апаратних вимірювань немає (E11 не виконано): усе нижче — модель.
Повні таблиці: docs/results.md · аналіз і висновки: docs/conclusions.md · курована добірка з усіма рисунками: results/.
Вісім, бо стільки несе аргумент. Решта — 5 ключових і 43 каталожні — це додаткові матеріали для перевірки: docs/figures.md. Біля кожного лежить його CSV з даними і JSON з параметрами побудови.
Конфігурації не переналаштовувались під природні дані — вони ті самі, що й для синтетичних. Це перевірка перенесення, а не новий добір.
Різниця P − B4, PSNR усього показаного кадру (жирним — встановлено після
поправки Holm):
| Канал | Синтетичні, 20 сцен | Одна фотографія, 17 вирізок | 24 незалежні знімки, 14 тестових |
|---|---|---|---|
clean |
-3,45 дБ [-3,89; -2,93] | -2,33 дБ [-2,46; -2,19] | -2,39 дБ [-2,55; -2,24] |
mild |
-3,45 дБ [-3,89; -2,93] | -2,33 дБ [-2,46; -2,19] | -2,39 дБ [-2,55; -2,24] |
moderate |
-0,27 дБ [-0,72; +0,23] | -0,18 дБ [-0,52; +0,22] | +0,08 дБ [-0,27; +0,42] |
bursty |
+1,50 дБ [+0,65; +2,44] | +0,91 дБ [+0,48; +1,40] | +1,30 дБ [+0,86; +1,69] |
harsh |
немає даних | немає даних | немає даних |
Знак, набір каналів і висновок збігаються на всіх трьох наборах: виграш лише на пакетних пошкодженнях, програш на чистому каналі.
Але B4 тут — вихідна схема, зі слабшим транспортом. Ось те саме
порівняння з базою, якій дано ті самі параметри транспорту й не дано жодного
з двох запропонованих механізмів:
| Канал | Синтетичні | Одна фотографія | 24 незалежні знімки |
|---|---|---|---|
clean |
-1,53 дБ [-1,95; -1,09] | -1,07 дБ [-1,16; -0,98] | -1,18 дБ [-1,32; -1,02] |
mild |
-1,53 дБ [-1,95; -1,09] | -1,07 дБ [-1,16; -0,98] | -1,18 дБ [-1,32; -1,02] |
moderate |
-1,48 дБ [-1,89; -1,06] | -0,91 дБ [-1,02; -0,79] | -1,02 дБ [-1,23; -0,80] |
bursty |
-1,19 дБ [-1,64; -0,80] | -0,76 дБ [-0,98; -0,56] | -0,36 дБ [-0,64; -0,06] |
harsh |
немає даних | немає даних | немає даних |
Переналаштована база перевершує запропоновану схему в кожному каналі кожного з трьох наборів. Це і є головний результат, і він тримається тоді, коли невизначеність рахується не по вирізках з однієї фотографії, а по чотирнадцяти різних знімках різних камер — тобто коли інтервал справді має право стосуватися нового запису.
run.bat test # або ./run.sh test
PYTHONPATH=src python -m pytest tests -q| Набір | Що перевіряє |
|---|---|
tests/test_crypto.py |
AEAD, HKDF, nonce, епохи, вікно повторів |
tests/test_pipeline.py |
наскрізний тракт, складання кадру, FEC |
tests/test_regressions.py |
по одній регресії на дефекти F01–F13 |
tests/test_regressions_f09_f18.py |
дефекти F09–F18 + знайдені під час прогонів |
Кожна регресія падає на коді до виправлення — це не тести-заглушки. Зведений журнал обох раундів рецензування з відтвореними експлойтами: docs/revision_history.md.
Окремо — 35 перевірок протоколу (мутація кожного семантичного поля, межі парсера, повтори, зрив стану). Поле, мутація якого не змінює AAD, вважається провалом, а не пропуском:
avsec protocol-check --config configs/research_main.yamlПовний аналіз результатів, що з цього випливає і чого не випливає: docs/conclusions.md.
Коротко:
- Схема 2021 року не дає захисту і додатково погіршує стійкість до пакетних пошкоджень порівняно з простим аналоговим передаванням.
- Гібридна архітектура працює: AEAD над аналоговим трактом дає автентифіковане відео за модельної затримки 159 мс і буфера 68 кБ.
- Перевага запропонованої схеми обмежена режимом пакетних пошкоджень і здебільшого пояснюється параметрами транспорту, а не двома запропонованими механізмами.
- Компроміс розміщення спостерігається в усіх досліджених конфігураціях.
- Апаратних вимірювань немає — усе вище є модель.
avsec/
├─ run.bat, run.sh запуск без налаштування
├─ requirements*.txt залежності
├─ configs/ плани прогонів (YAML)
│ ├─ analysis_plan.yaml статистичний план, зафіксований ДО прогону
│ ├─ research_main.yaml E02: 20 синтетичних сцен
│ ├─ research_drone.yaml E12: 17 вирізок з ОДНІЄЇ фотографії
│ └─ research_natural.yaml E14: 24 НЕЗАЛЕЖНІ фотографії, по 1 кліпу
├─ data/real/
│ ├─ curonian_spit_epha_dune.jpg камерний оригінал (Free Art License)
│ └─ sources.json реєстр 24 джерел: URL, ліцензія, автор, sha256
├─ src/avsec/
│ ├─ crypto/ AEAD, HKDF, стан сеансу, епохи
│ ├─ framing/ заголовок v2, CRC, розбір
│ ├─ source_coding/ DCT/JPEG, смуги, кілька описів
│ ├─ fec/ Reed–Solomon, блокування, стирання
│ ├─ damage.py клітинки → байти → RS-слова; звірка з декодером
│ ├─ interleaving/ sequential | block | diagonal | random | BAWP
│ ├─ modem/ растровий модем + модель CVBS 625/50
│ ├─ channel/ спотворення рівня A, траси каналу
│ ├─ transmitter.py тракт передавача
│ ├─ receiver/
│ │ ├─ __init__.py тракт приймача
│ │ └─ sessions.py реєстр допустимості сеансів + кеш ключів
│ ├─ sources/
│ │ ├─ drone.py 17 послідовностей з однієї фотографії
│ │ └─ natural.py 24 незалежні джерела, по одному кліпу
│ ├─ baselines/ B0a…B4, B4t, P
│ ├─ attacks/ криптоаналіз перестановок
│ ├─ matrix.py матричний runner (resume, повнота, усі моменти)
│ ├─ statistics.py єдиний шлях агрегування
│ ├─ analysis.py ефекти, CI, тести, Holm по оголошеній сім'ї
│ ├─ verify.py перерахунок кожного твердження з таблиць
│ ├─ figures.py, figures_key.py G01–G43, K01–K13
│ ├─ publish.py генерація документації
│ └─ ui/ веб-інтерфейс
├─ scripts/ довгі прогони, добір джерел, скріншоти, курація
├─ tests/ регресії на кожен дефект (F01–F18, R01–R12)
├─ docs/
│ ├─ claims.md кожне твердження → таблиця, що його підтримує
│ ├─ related_work.md чотири напрями, і що саме тут нове
│ └─ ... протокол, архітектура, висновки, журнал дефектів
└─ results/{main,drone,natural}/ курована добірка: таблиці + усі рисунки
- Немає жодного вимірювання на фізичному обладнанні. Немає передавача, приймача, плати захоплення. Слова «дешевий», «низька наскрізна затримка на реальному тракті» до цієї роботи не застосовні.
- Немає моделі радіочастотного FM-тракту; рівень B — композитний сигнал у основній смузі.
- Переналаштована база
B4tперевершує запропоновану схему в кожному каналі кожного з трьох наборів даних. Це виміряно і показано, а не обійдено. - Запропоновані механізми (MDC + BAWP) не покращують наскрізну якість у перевіреному бюджеті — і не є самостійним доповненням до базової схеми: при вихідному розмірі одиниці вони взагалі не вміщуються в бюджет, тобто застосовні лише після тих самих змін транспорту, які й дають увесь виграш. Заявка звужується до виміряних меж, контрприкладів і карти умов.
- Дві з двадцяти синтетичних сцен (
grid_fast,text_fast) не вміщуються у спільний бюджет для цифрових методів; це властивість обраного профілю, і такі моменти показу тепер рахуються проти методу, а не зникають з обліку. - Перевага BAWP над глибоким блочним перемежуванням не однозначна, а в перевіреному бюджеті ще й ні на що не впливає: на 16-рядковому пакеті обидві схеми відновлюються повністю.
- Карта умов (§E15) описує цю модель каналу і цей бюджет. Одного універсального порога не існує: він залежить і від частоти пакетів, і від їхньої довжини.
- Правильна інтеграція AEAD, підтверджена перевірками, не доводить відсутності інших помилок протоколу.
- Ані низька кореляція, ані висока ентропія, ані NPCR/UACI не є доказом конфіденційності — і тут вони так не використовуються.
Повний перелік обмежень, згрупований за розділами дослідження, — docs/limitations.md.
| Документ | Про що |
|---|---|
| docs/README.md | карта документації — усі файли за групами і рекомендований порядок читання |
| ROADMAP.md | стан реалізації, програма досліджень, відкриті задачі |
Постановка задачі та об'єкт дослідження
| Документ | Призначення |
|---|---|
| docs/reconstruction_2021.md | основний документ завдання: реконструкція, випробування на зображеннях, криптоаналіз, модифікації |
| docs/methods.md | каталог усіх схем: будова, параметри й результати кожної — десяти схем спільного прогону та двох з окремими стендами |
| docs/related_work.md | суміжні напрями та визначення внеску роботи |
| docs/threat_model.md | модель загроз і межі гарантій |
| docs/substitution_b2s.md | схема B2s: заміна значень пікселів разом із перестановкою блоків |
| docs/galois_sbox.md | обчислювана таблиця замін над GF(2⁸): звірка з AES, виміряні властивості |
| docs/luma_balance.md | схема B2l: стала яскравість шифротексту — місткість палітри, обидва шляхи, витік за площинами, механізм відмови, прогін через аналоговий тракт |
Будова системи
| Документ | Призначення |
|---|---|
| docs/architecture.md | рівні моделі, зіставлення A↔B, спільний бюджет |
| docs/protocol.md | формат кадру, AEAD, епохи, реєстр сеансів |
Організація експерименту
| Документ | Призначення |
|---|---|
| docs/datasets.md | паспорт трьох наборів даних: походження, ліцензії, межі узагальнення |
| docs/experiments.md | протокол експериментів і статистична обробка |
| docs/programme.md | стан досліджень E01–E15, зокрема невиконаних |
| docs/hardware.md | вимоги до стенда для E11 |
Результати
| Документ | Призначення |
|---|---|
| docs/results.md | усі таблиці, згенеровані з одного run_id |
| docs/figures.md | вісім основних рисунків і повний каталог зі статусом |
| docs/conclusions.md | висновки за дослідницькими питаннями |
| docs/claims.md | реєстр перевірюваних тверджень: вид і джерело перевірки |
Обмеження, термінологія, історія
| Документ | Призначення |
|---|---|
| docs/limitations.md | зведені межі застосовності результатів |
| docs/glossary.md | терміни, скорочення та програмні ідентифікатори |
| docs/revision_history.md | журнал двох раундів рецензування: 30 дефектів і їхній вплив |
| docs/historical_results.md | числа попередніх редакцій, окремо від поточних |
| CHANGELOG.md | версійована історія змін |
Код — MIT.
Фотографія data/real/curonian_spit_epha_dune.jpg — © A.Savin,
Free Art License 1.3,
джерело Wikimedia Commons.
Атрибуція подорожує з даними в кожному маніфесті, який пише цей репозиторій.
Криптографічні примітиви беруться з cryptography, Reed–Solomon — з reedsolo;
вони тут не переписуються.











