montana/Formal-Docs/02-Spec/SSOT-Rust.md
2026-05-26 21:14:51 +03:00

6.3 KiB
Raw Blame History

SSOT — Rust как единственный источник истины криптографии и протокола

Статус: обязательный архитектурный инвариант Montana. Применяется ко всему коду, выпускаемому под именем Montana. Нарушение блокирует релиз.

Правило

Любая криптографическая, ключевая или протокольная операция — мнемоника → master_seed, derive_account_id, derive_node_id, ML-DSA-65 / ML-KEM-768 keygen / sign / verify / encap / decap, Transaction encoding и подпись, state-root computation, проверка балансов и переводов — определена ровно в одном месте: Rust-крейтах Montana/Montana-Protocol/Code/crates/.

Канонические крейты:

  • mt-mnemonic — 24 слова → master_seed (PBKDF2-HMAC-SHA-256, 2²⁰ итераций, salt "mt-seed"); HKDF-Expand для ролей.
  • mt-crypto — ML-DSA-65 (FIPS 204), ML-KEM-768 (FIPS 203), детерминированные keypair/sign/verify через OpenSSL FIPS provider (через mt-crypto-native).
  • mt-codec — domain separators (b"mt-seed", b"mt-account-key", b"mt-node-key", …), canonical byte encoding.
  • mt-statederive_account_id(suite_id, pubkey) = SHA-256("mt-account" || suite_id_LE || pubkey); AccountTable, NodeTable.
  • mt-account — Transaction (Transfer / ChangeKey / Anchor / TransferActivation), правила signed_scope, settlement.

Все эти крейты экспортируются через единственный фасад: crates/mt-bindings — стабильный C ABI (для iOS/macOS staticlib и Android cdylib) + WASM-binding (для веба).

Запреты

Нативный клиент Montana (iOS Swift, Android Kotlin/Java, веб JS/TS, macOS Swift, любой будущий) не имеет права:

  1. Реализовывать PBKDF2 / HMAC / HKDF / SHA-256 на месте — должен вызывать через FFI.
  2. Реализовывать ML-DSA-65 / ML-KEM-768 / Ed25519-substitute для генерации ключей или подписи Montana-операций.
  3. Иметь свою формулу address derivation — только mt_derive_account_id.
  4. Кодировать Transaction своим способом — только через mt-account или его экспорт.
  5. Хранить дублирующие константы (PUBKEY_SIZE, KDF_ITER, salts, suite_id) — все берутся из mt_bindings.h / Kotlin MtBindings.* / WASM exports.

Эталонный KAT-вектор

crates/mt-bindings/tests/kat_cross_client.rs фиксирует:

entropy   = 32 × 0x00
mnemonic  = "abandon abandon abandon abandon abandon abandon abandon abandon
             abandon abandon abandon abandon abandon abandon abandon abandon
             abandon abandon abandon abandon abandon abandon abandon art"
master[..8]  = 38a1421ac3ce191f
acc_seed     = 08ce5c19768c679fda24c0d3360e57ce03d00c94c175e59f50e9c77894c20818
pubkey[..16] = c1b89f8277a6cec0818419e69add3892
account_id   = 9f199584ed120b987b617ba5bff829e176f23e5465dd70cfac5c141dfb131a21

Каждый клиент (Swift через MontanaBindings, Kotlin через libmontana.so, JS через mt_bindings.wasm) обязан содержать конформанс-тест, который:

  1. Принимает мнемонику-эталон.
  2. Вызывает свой биндинг.
  3. Сравнивает байт-в-байт с account_id = 9f199584ed120b987b617ba5bff829e176f23e5465dd70cfac5c141dfb131a21.

Расхождение хоть в одном бите = клиент сломан, релиз блокируется.

Сборка артефактов

Цель Команда Артефакт
macOS arm64 (host) cargo build -p mt-bindings --release target/release/libmt_bindings.{a,dylib}
iOS sim arm64 cargo build -p mt-bindings --release --target aarch64-apple-ios-sim target/aarch64-apple-ios-sim/release/libmt_bindings.a
iOS device arm64 cargo build -p mt-bindings --release --target aarch64-apple-ios (требует iOS-OpenSSL cross — отдельная задача)
Android arm64 cargo ndk -t arm64-v8a build -p mt-bindings --release libmt_bindings.so
Android x86_64 cargo ndk -t x86_64 build -p mt-bindings --release libmt_bindings.so
Web wasm-pack build crates/mt-bindings --target web --features wasm pkg/mt_bindings.js + .wasm

C-заголовок: crates/mt-bindings/include/mt_bindings.h.

Жизненный цикл изменений

  1. Меняется крипто-параметр (например, KDF_ITER или новый suite_id) → меняется Rust + обновляется KAT-вектор.
  2. После изменения Rust — пересобирается mt-bindings, переразлитваются артефакты для iOS/Android/Web.
  3. CI прогоняет KAT во всех клиентах. Любое расхождение = abort.
  4. ABI breaking changes — bump MT_ABI_VERSION в lib.rs; клиенты должны проверить mt_abi_version() до использования.

История

  • 2026-05-24 — введение инварианта. До этого: iOS, Android, веб реализовывали PBKDF2 / address / signing самостоятельно с расходящимися параметрами (600k итераций vs 2²⁰, "mt+SHA256(pk)[:20]" vs canonical SHA256-with-domain, Ed25519 vs ML-DSA). Это блокировало байт-точные переводы между клиентами. Mt-bindings и эта спека закрывают расхождение.