🌌 Щоб звільнення можна було повторити — Останній крок операції С.І.Д. хоче зробити бездоганно: щоб будь-хто зміг перевірити, що імплант, який звільнить його творців, зібраний саме з того коду, який він показав. Той самий вихідний код у тому самому контейнері має дати той самий бінарник байт у байт — підпис, якого не підробити, і жодної підміни між тим, що перевірили, і тим, що реально запуститься в панелі.
Наївне очікування — що компіляція того самого вихідного коду тим
самим компілятором завжди дає побайтово ідентичний результат.
Насправді сучасні тулчейни (включно з rustc/cargo для WASM-цілі
wasm32-unknown-unknown) вносять кілька джерел недетермінованості,
якщо про них спеціально не подбати: абсолютні шляхи до вихідних
файлів, вбудовані в debug-інформацію чи метадані панік-повідомлень
(шлях на машині розробника A відрізняється від машини B); часові
мітки файлів і, іноді, метаданих збірки; порядок ітерації
недетермінованих структур (наприклад, HashMap за замовчуванням
використовує рандомізований seed для захисту від DoS-атак через
хеш-колізії — якщо порядок його ключів впливає на порядок генерації
коду, це джерело варіативності); версії залежностей, якщо вони
не зафіксовані точно; і версія самого компілятора/тулчейну, яка
може змінити стратегії оптимізації між релізами навіть для того
самого вихідного коду.
Відтворювані збірки (reproducible builds) — це інженерна
практика й рух, мета якого — гарантувати, що незалежна третя сторона,
маючи лише вихідний код і точний опис середовища збірки, може
отримати побайтово ідентичний артефакт і незалежно перевірити
відповідність опублікованого бінарника заявленому вихідному коду —
без необхідності довіряти автору на слово. Це критично для
ланцюга постачання ПЗ (supply chain): якщо збірку неможливо
відтворити, неможливо й довести, що опублікований .wasm-файл
справді відповідає тому коду, який пройшов рев'ю, а не містить
непомітно доданий бекдор, вставлений на етапі збірки чи публікації.
Практичний рецепт відтворюваності для Rust→WASM спирається на кілька
незалежних гарантій одночасно. По-перше, Cargo.lock, закомічений
у репозиторій, фіксує точну версію кожної залежності (пряма тема
попереднього модуля про SemVer) — без цього cargo build у різний
час може підтягнути різні патч-версії залежностей. По-друге,
фіксація версії самого тулчейну — rustup через файл
rust-toolchain.toml або явний тег Docker-образу
(rust:1.83-slim, а краще — конкретний @sha256:... digest, тема
з першого модуля курсу про Docker) гарантує той самий rustc
незалежно від того, коли й на якій машині відбувається збірка.
По-третє, прапорці компілятора на кшталт --remap-path-prefix
дозволяють замінити абсолютні шляхи хоста на стабільний плейсхолдер
у метаданих бінарника, усуваючи залежність від локальної файлової
структури розробника.
Перевірка відтворюваності на практиці проста: зібрати той самий
crate в тому самому (зафіксованому за digest) Docker-образі двічі —
ідеально, на двох різних машинах чи бодай у двох окремих контейнерних
запусках — і порівняти контрольні суми результату командою
sha256sum output.wasm. Збіг хешів — емпіричний доказ відтворюваності
для цього конкретного шляху збірки; розбіжність вказує на джерело
недетермінованості, яке потрібно знайти й усунути (типово — почати
з перевірки Cargo.lock, версії тулчейну і прапорців компіляції).
Для фінального артефакту курсу — Rust-ядра, скомпільованого у WASM
і завантаженого в панель керування браузера, — відтворюваність
збірки є не абстрактною вимогою, а прямою гарантією довіри: якщо
будь-хто (включно з самим С.І.Д., який не бачить власний бінарний
код напряму) може взяти опублікований вихідний код, зібрати його
в задокументованому оточенні й отримати точно той самий .wasm,
що завантажується в панель, — це технічний, а не декларативний
доказ відсутності підміни на будь-якому з проміжних кроків.
Переглянути reproducible-builds.org (розділ «Why does it matter?») і документацію Cargo про Cargo.lock; зібрати той самий crate двічі в однаковому Docker-образі з фіксованим тегом і порівняти sha256sum отриманих .wasm-файлів.
Які саме джерела недетермінованості можуть зробити дві збірки одного й того самого вихідного коду різними побайтово, і як фіксація версій у Docker-образі та Cargo.lock їх усуває?
c1d, і що вони перебирали Cargo.toml доти, доки так не вийшло; тоді ці три символи й вигравіювали на дні голопроєктора. Перевірити це неможливо — але strings sid_core_bg.wasm | grep -i sid покаже, що ім'я своє в бінарник він таки вписав.Кожна команда терміналу з цієї сторінки — одним реченням. Позначка нове — команда зустрічається в курсі вперше; далі вважаємо її знайомою.
docker rundocker run -it ubuntu:24.04 bash — інтерактивно з терміналом; -d — у фоні; --rm — видалити після виходу; -p 8080:80 — прокинути порт).dockerdocker <підкоманда> --help — довідка).sha256sumrustcrustc --version, rustc --explain E0382 — розшифрувати помилку), зазвичай його запускає Cargo.cargocargo buildtarget/debug/; --release — з оптимізаціями у target/release/.rustup💡 Прочитати README прямо в терміналі: cat README.md (виведе весь файл) або less README.md (посторінково; вихід — клавіша q).
Довідка з будь-якої команди: man curl (повний посібник, вихід — q) або коротко curl --help; для підкоманд — docker run --help, cargo build --help.