- [x] Total own audit surface (Layer 1 + Layer 2) **1280 строк** (662 Rust shim + 49 FFI bindings + 457 C wrapper + 67 C header + 45 build script) — small enough для thorough review. Точные числа: `wc -l crates/mt-crypto/src/lib.rs crates/mt-crypto-native/src/lib.rs crates/mt-crypto-native/csrc/mt_crypto.{c,h} crates/mt-crypto-native/build.rs`.
- [x] No `serde` auto-derive в consensus-critical types (custom `CanonicalEncode` trait)
## C. Memory safety + secret hygiene (Pass 17 enforcement)
- [x]**Drop+zeroize** для `SecretKey` (4032B) и `MlkemSecretKey` (2400B)
- [x]**Heap-allocated через Box** — secret bytes живут в heap, не stack inline (verified `secret_key_is_heap_allocated` test: `size_of::<SecretKey>() == 8` pointer)
- [x]**mlock applied** на heap pages для secret bytes (best-effort через `alloc_locked_secret_box`); fallback assumption: encrypted swap (FileVault macOS / LUKS Linux)
- [x]**Stack hygiene при FFI** — `keypair_from_seed*` пишет напрямую в heap-locked Box; никаких stack temporary buffers с secret bytes (verified в [crates/mt-crypto/src/lib.rs](../crates/mt-crypto/src/lib.rs) — функции `keypair_from_seed` и `keypair_from_seed_mlkem`, search by name)
- [x]**munlock в Drop** перед heap dealloc (best-effort, errno ignored)
- [x] No `Clone`/`Copy` derive на secret types (compile-time enforced via security_invariants test)
- [x] No `PartialEq`/`Eq` на secret types (предотвращает timing leak через ==)
- [x] No secret bytes в logs / stdout / stderr (file-content scan через `no_println_or_log_on_secret_bytes_in_lib_code` test)
- [x]`mt-examples/m1_crypto.rs::print_sk` gated через env var (`M1_DUMP_SK=1` opt-in; по умолчанию SK bytes redacted; механизм: `dump_sk_enabled()` функция в [m1_crypto.rs](../crates/mt-examples/examples/m1_crypto.rs#L39-L41) проверяется в `print_sk` строка 76)
- [x] FFI buffer sizes match contract (PUBLIC_KEY_SIZE / SECRET_KEY_SIZE / SIGNATURE_SIZE constants used consistently)
- [x]**13 security invariants automated** в [crates/mt-crypto/tests/security_invariants.rs](../crates/mt-crypto/tests/security_invariants.rs) — regression detection
- [x]**FIPS 204 Algorithm 2 deterministic Sign** через `OSSL_SIGNATURE_PARAM_DETERMINISTIC=1`
- [x] No `f32`/`f64` в crypto path (consensus determinism per Montana [I-3] + [I-9])
- [x] No `HashMap`/`HashSet` iteration order dependency
- [x] No `SystemTime::now`/`Instant::now` в consensus path (только в test/tool helper `keypair()` который gated `#[cfg(any(test, feature = "testing"))]`)
## F. Misuse resistance
- [x]**`SecretKey::from_array(arbitrary_bytes)`** при последующем `sign()` возвращает `Err(CryptoError::InvalidSecretKey)`, не panic (F-7 closure через F-2 Result API)
- [x]`keypair()` (weak entropy test helper) **не доступен** в production binary (cfg-gate)
- [x] Public type fields private (no struct literal construction обходящая validation)
- [x] No `Default` impl для types requiring real crypto material
## G. Build & reproducibility
- [x]**`Cargo.lock`** committed
- [x]**Точные версии всех dependencies** (`=X.Y.Z`)
- [x]**`rust-toolchain.toml`** pinned
- [x]**Docker reproducible build**с pinned base image digest
- [x]**CI gate `reproducible_release`** проверяет byte-identity между двумя независимыми runs
- [x]**Cross-compile correctness** через `CARGO_CFG_TARGET_OS` env var
## H. Dependencies
- [x]**Crypto deps** все production-grade (OpenSSL 3.5.5 LTS, sha2 0.10.9, no pre-1.0 в consensus path)
- [x]**No "USE AT YOUR OWN RISK" libraries** в production paths
Список всех `panic!`/`assert!` в lib коде Montana с обоснованием. Все они — **controlled halts при protocol-invariant violation**, НЕ attacker-triggered, НЕ silent failures. Auditor должен verify что каждый panic site:
- (a) reachable только при invariant violation от trusted source (Genesis params, frozen const)
- (b) imeет explicit comment с обоснованием
- (c) не открыт для attacker-controlled input
| Site | Файл:строка | Trigger | Обоснование |
|------|-------------|---------|-------------|
| `apply_transfer*` balance underflow | [crates/mt-account/src/lib.rs](../crates/mt-account/src/lib.rs) `fn apply_transfer{,_activation}` | `sender.balance.checked_sub(amount)` returns None | Protocol invariant breach: `validate_transfer*` гарантирует `balance >= amount` ДО apply. Halt = caller вызвал apply без validate (programmer error либо memory corruption). Не attacker-triggered: validate-then-apply pattern enforced. |
| `apply_transfer*` receiver/operator balance overflow | [crates/mt-account/src/lib.rs](../crates/mt-account/src/lib.rs) `fn apply_transfer/apply_emission` | `balance.checked_add(amount)` returns None at u128::MAX | Encoded arithmetic horizon — суммарный баланс per-account достиг u128::MAX (~3.4×10³⁸ nɈ). Не достижим под const emission `EMISSION_moneta = 13 × 10⁹ nɈ` per окно. Documented halt. |
| `apply_*` op_height/account_chain_length overflow | [crates/mt-account/src/lib.rs](../crates/mt-account/src/lib.rs) `fn apply_*` | `u32` field counters достигли u32::MAX (~4.29 млрд operations per account) | Encoded arithmetic horizon: 4.29 млрд operations per account, не достижим в реалистичный срок. Documented halt. |
| `window_w_to_u32` cast overflow | [crates/mt-account/src/lib.rs](../crates/mt-account/src/lib.rs) `fn window_w_to_u32` | `window_w: u64 > u32::MAX` при cast в AccountRecord field | AccountRecord использует u32 для window-полей (encoded size optimization 4B vs 8B). Horizon = ~4.29 млрд окон ≈ 8000 лет at 60 sec/window. Documented halt. |
**Все sites:**
- ✅ Имеют explicit panic message с обоснованием
- ✅ Reachable только при achieved arithmetic horizon либо protocol invariant breach
- ✅ Не attacker-triggered
- ✅ Halt = correct behavior per spec — protocol upgrade required либо validate-then-apply violated (programmer error)
`mt-crypto` panics gated через `assert_eq!(r, MT_OK, ...)` уже converted в `Result<_, CryptoError>` в M1-F closure (commit `e1164ad`) — там panic-в-lib больше нет.
`mt-examples` test helpers могут panic через `.expect("...")` — это test scaffolding, вне production audit scope (per critic role Scope §«НЕ входит в scope: mt-examples test helpers»). Production binary вызовы из mt-examples (m1_crypto demo) panicи через `.expect("HKDF-derived seed cannot fail KeyGen")` — internal invariant, не attacker-triggered.
## L0. Test strength augmentations (Pass 22)
**Mutation testing (recommended, не block для audit):**
*Альтернатива без Docker prerequisite:* верифицировать через CI history — каждый push в `main` запускает CI job `reproducible_release` (см. .github/workflows/ci.yml), который выполняет тот же двойной build с byte-identity assertion. Auditor может проверить green CI runs за период как evidence.