NOXYDocs
GitHub
Docs/Разработчикам/Кошельки и keystore

Кошельки и keystore

Создание кошелька NOXY из BIP-39 мнемоники, деривация ключа аккаунта ML-DSA-44 и зашифрованный keystore.

Обновлено 2026-08-03Статус ReferenceИсточник content/wiki/ru/developers/wallet.mdx

Кошельки и keystore

Кошелёк выводит ключ аккаунта ML-DSA-44 из BIP-39 мнемоники и хранит расширенный секретный ключ в keystore, зашифрованном AES-256-GCM. Сегодня публичны две реализации этой деривации: браузерный кошелёк и TypeScript-пакет @noxy/core. Мнемоника, созданная в одном, восстанавливает тот же аккаунт в другом.

Создание и восстановление

Кошелёк генерирует BIP-39 мнемонику (по умолчанию 24 слова), выводит ключ аккаунта ML-DSA-44 по пути по умолчанию m/44'/8800'/0'/0/0 и шифрует расширенный секретный ключ паролем. Пустой пароль отвергается.

Восстановление из мнемоники повторяет ту же деривацию, поэтому всегда даёт тот же ключ аккаунта. Восстановленный keystore получает свежие id, salt и nonce — байты отличаются от исходного файла, но ключ внутри идентичен.

Деривация

Путь состоит из шести сегментов и имеет фиксированную форму:

m/44'/8800'/account'/change/index

44' и 8800' обязательны (8800 — coin type NOXY). account hardened; change и index — обычные u32. Любая другая форма отвергается.

Из seed в ключ аккаунта:

bip39_seed   = BIP39(mnemonic, bip39_passphrase)          # 64 байта
account_seed = HKDF-SHA256(
                 salt = "NOXY-L0/wallet-seed/v1",
                 ikm  = bip39_seed,
                 info = derivation_path,
                 len  = 32)
keypair      = ML-DSA-44.KeyGen_internal(xi = account_seed)  # FIPS 204

Размеры ML-DSA-44: открытый ключ 1312 байт, подпись 2420 байт. Keystore хранит каноничный расширенный секретный ключ — 2560 байт.

Одна мнемоника и один путь всегда дают один и тот же ключ аккаунта. Изменение пути — включая change или index — даёт другой ключ и, значит, другой аккаунт.

account_id

ID аккаунта выводится из открытого ключа, не хранится:

account_id = HASH("account-id/v1",
                  BLAKE3(public_key) || account_type_u16_le || salt)

HASH(domain, msg) — это BLAKE3("NOXY-L0/v0.1/" || domain || 0x00 || msg). Кошельки используют account_type = 1 (User) и пустой salt.

ID аккаунта стабилен при ротации ключа: ротация подписывающего ключа его не меняет. Полная модель — на странице Аккаунты.

Адрес и verifier

32-байтный ID аккаунта рендерится тремя способами. Hex — каноничная wire-форма; bech32m и verifier — для отображения.

hex      f63052cfff6e7141bf90b7f9170a589f0674771a2d44173549fe60ba6aebf251
bech32m  tnxy17cc99nlldec5r0usklu3wzjcnur8gac694zpwd2flest56ht7fg…
verifier general · leisure · vote · 97

bech32m использует HRP noxy на mainnet и tnxy на testnet, с контрольной суммой BIP-350, отвергающей опечатки и смешанный регистр. Адрес, закодированный под одним HRP, не декодируется под другим.

Verifier — три слова BIP-39 плюс двузначное число, выведенные из ID аккаунта:

digest = BLAKE3("NOXY-L0/v0.1/account-verifier/v1\0" || account_id)
word_i = u16_le(digest[2i .. 2i+2]) & 0x07ff   для i = 0,1,2
number = u16_le(digest[6..8]) % 100

Прочитайте четыре токена вслух, чтобы подтвердить получателя, вместо сравнения 64 hex-символов. Verifier — только отображение, транзакции связывают сырой ID аккаунта.

Имена аккаунтов

К аккаунту можно обращаться и по зарегистрированному имени вида alice@veylith. Имена живут в on-chain реестре с арендой (lease): имя регистрируется на срок, его можно продлить, перенацелить, передать или освободить. Кошелёк и SDK @noxy/core разрешают имена напрямую из состояния; публичного HTTP-эндпоинта резолва пока нет.

Формат keystore

{
  "version": 1,
  "id": "<uuid v4>",
  "algorithm": "ML-DSA-44",
  "public_key_hex": "…",
  "derivation_path": "m/44'/8800'/0'/0/0",
  "crypto": {
    "cipher": "aes-256-gcm",
    "ciphertext": "<hex>",
    "nonce": "<hex, 12 байт>",
    "kdf": "argon2id",
    "kdfparams": {
      "salt": "<hex, 16 байт>",
      "memory_cost_kib": 19456,
      "time_cost": 3,
      "parallelism": 1,
      "output_len": 32
    }
  }
}

Ключ шифрования — Argon2id (v1.3) над паролем с параметрами выше: 19 МиБ памяти, 3 прохода, 1 lane, 32-байтный выход. AES-256-GCM связывает метаданные keystore как associated data:

NOXY-L0/keystore/v1|id={id}|algorithm=ML-DSA-44|public_key={public_key_hex}|path={derivation_path}

Изменение id, public_key_hex или derivation_path ломает расшифровку. Plaintext — это 2560-байтный расширенный секретный ключ ML-DSA-44.

Расшифровка падает при неверном пароле, любом изменении ciphertext или поля AAD, либо при output_len != 32.

Что не входит

Это материал ключа аккаунта, а не готовый кастодиальный продукт. Нет guardian recovery, поддержки аппаратных кошельков или WalletConnect. Создание аккаунта в сети всё ещё требует отправки подписанной транзакции — кошелёк только производит ключ.