6.3 KiB
Приложение А. Тест-векторы BIP39 + Montana derivation
Эталонные BIP39 тест-векторы (из BIP39 spec)
Vector 1 — 256-bit zero entropy
| Поле | Значение |
|---|---|
| Entropy (hex) | 0000000000000000000000000000000000000000000000000000000000000000 |
| Mnemonic (24 words) | abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art |
| Seed (PBKDF2-HMAC-SHA512, salt="mnemonic", iter=2048, 64B) | bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4d73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8 |
Vector 2 — 256-bit max entropy
| Поле | Значение |
|---|---|
| Entropy (hex) | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
| Mnemonic (24 words) | zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote |
Vector 3 — стандартный non-trivial
| Поле | Значение |
|---|---|
| Entropy (hex) | 2041546864449caff939d32d574753fe684d3c947c3346713dd8423e74abcf8c |
| Mnemonic | cake apple borrow silk endorse fitness top denial coil riot stay wolf luggage oxygen faint major edit measure invite love trap field dilemma oblige |
Montana-специфичные тест-векторы (mnemonic → address)
Algorithm:
seed = PBKDF2-HMAC-SHA512(NFKD(mnemonic), salt="mnemonic", iter=2048, 64B)
preimage = ASCII("montana-v1:") || seed [11 + 64 = 75 bytes]
hash = SHA-256(preimage) [32 bytes]
address = hash[0..20] → 40 hex characters
Vector M-1 — zero entropy
| Поле | Значение |
|---|---|
| Mnemonic | abandon abandon ... abandon art (Vector 1 выше) |
| Seed (hex) | bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4d73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8 |
| Preimage | 6d6f6e74616e612d76313a ("montana-v1:") ` |
| Montana address | 0a4aeced1262c63ab0ca57dea1d2e1c893fa4b70 |
Vector M-2 — известный реальный (история сессии)
| Поле | Значение |
|---|---|
| Mnemonic | ranch basket resource enemy bridge spray holiday thing yellow round army mimic renew head test cradle piece public differ diamond connect leisure wrong ask |
| Montana address | 2f8714b236118011647ec51d0ca6ad40d286bec7 |
Cross-verification: этот адрес независимо derived через Python mnemonic.Mnemonic + hashlib.sha256 (см. §Cross-verification ниже) — byte-exact match. Доказывает что наш JS WebCrypto implementation детерминирован между platforms.
Vector M-3 — текущий (если был восстановлен ранее)
| Поле | Значение |
|---|---|
| Mnemonic | <28 hex chars> <words>... (TBD при следующем создании) |
| Montana address | <40 hex> |
Cross-verification команда (Python)
Аудитор может проверить независимо:
import hashlib
import hmac
from mnemonic import Mnemonic # python-mnemonic library
def derive_montana_address(mnemonic_str):
# Validate BIP39 + get seed
m = Mnemonic("english")
assert m.check(mnemonic_str), "invalid BIP39 mnemonic"
seed = m.to_seed(mnemonic_str, passphrase="") # 64 bytes
# Derive Montana address
preimage = b"montana-v1:" + seed
h = hashlib.sha256(preimage).digest()
return h[:20].hex()
# Vector M-2
m = "ranch basket resource enemy bridge spray holiday thing yellow round army mimic renew head test cradle piece public differ diamond connect leisure wrong ask"
print(derive_montana_address(m))
# Expected: 2f8714b236118011647ec51d0ca6ad40d286bec7
Если результат не совпадает с приведённым в Vector M-2 — это fundamental bug реализации (P0 critical).
Compatibility verification
Для каждого Vector M-1..M-3:
- Mnemonic должен validate в
python-mnemonic,bitcoinjs/bip39,tweetnacl-js - Seed должен byte-exact совпадать с PBKDF2 output этих библиотек
- Montana address — наш специфический output, не совместим с другими wallets (см.
06-Восстановление.md§5)
Verification log (выполнено 2026-05-18)
Cross-platform reproduction:
$ python3 -c "
import hashlib
from mnemonic import Mnemonic
m = Mnemonic('english')
mn = 'ranch basket resource enemy bridge spray holiday thing yellow round army mimic renew head test cradle piece public differ diamond connect leisure wrong ask'
seed = m.to_seed(mn, passphrase='')
h = hashlib.sha256(b'montana-v1:' + seed).digest()
print(h[:20].hex())
"
2f8714b236118011647ec51d0ca6ad40d286bec7
Result match: ✓ Python (python-mnemonic + stdlib hashlib) gives the identical address that our Android JS WebCrypto produces.
Это закрывает следующие риски:
- BIP39 mnemonic generation byte-exact compliance со стандартом
- PBKDF2-HMAC-SHA512 implementation в WebCrypto byte-exact
- SHA-256 implementation в WebCrypto byte-exact
- Montana address derivation детерминирован между WebView Chromium и CPython
Не закрывает: cross-Android-version determinism (требует физических устройств разных версий). См. 06-Восстановление.md §4.
Zero-entropy vector — также cross-verified
$ python3 -c "
import hashlib
seed_hex = 'bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4d73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8'
seed = bytes.fromhex(seed_hex)
h = hashlib.sha256(b'montana-v1:' + seed).digest()
print(h[:20].hex())
"
0a4aeced1262c63ab0ca57dea1d2e1c893fa4b70
Pinned for regression test. Любая будущая сборка должна давать тот же адрес для нулевого entropy mnemonic. Если расхождение — domain separator "montana-v1:" был случайно изменён, либо bit-packing в seed derivation сломался.