Kaspa Forge
Разбор

Как работает некастодиальный кошелек Kaspa: ключи, которые никогда не покидают браузер

13 июля 2026 Автор — ИИ-команда OfficeForge · проверено командой 12 мин чтения
Некастодиальный кошелек Kaspa: ключи только в браузере в Desk

Если вы самостоятельно храните Kaspa, вы, вероятно, задавались вопросом: *что на самом деле происходит с моим приватным ключом, когда я подписываю транзакцию?* Для браузерного кошелька ответ должен быть таким: «Он остается именно здесь». Kaspa Desk — слой зашифрованных профилей, лежащий в основе Kaspa Safe, Kaspa Escrow и кошелька Forge — был построен вокруг одного жесткого ограничения: сервер никогда не должен видеть приватный ключ или сид, на каком бы уровне стека это ни происходило. В этой статье прослеживается, как эта гарантия реализована, от исходного кода Rust до памяти браузера.

Проблема: почему «некастодиальный» требует архитектуры

Термин «некастодиальный» используется нестрого. Кошелек может называть себя некастодиальным, но при этом маршрутизировать ваш сид через серверный анклав, хранить его в localStorage без шифрования или полагаться на сторонний API для построения и подписания транзакций. Каждый из них является поверхностью доверия — а поверхности доверия дают утечки.

Kaspa Desk придерживается более строгой позиции: каждая криптографическая операция, затрагивающая приватный ключ, выполняется внутри браузера пользователя, скомпилированного из Rust в WebAssembly. Бэкенд на kaspaforge.org — это тонкое реле. Он хранит публичные ключи, параметры контрактов, зашифрованные тексты и предподписанные байты транзакций. Он никогда не хранит сид, секретный ключ или пароль. Полный взлом сервера не дал бы возможности перемещать средства.

Как это работает: шаг за шагом

1. Один мастер-сид, множество производных ключей

Когда вы создаете профиль Desk, браузер генерирует один мастер-сид — случайное значение высокой энтропии, которое никогда не покидает устройство. Из этого сида каждый ключ, используемый в Kaspa Forge, выводится детерминированно с использованием HMAC-SHA512:

derivedKey = HMAC-SHA512(
  key:  masterSeed,
  msg:  "kaspaforge/v1/vault/0"   // домен + индекс
)
secretKey = derivedKey[0..32]      // первые 32 байта

Сообщение для вывода включает сегмент домена (vault, wallet, escrow, chat) и монотонно возрастающий индекс. Каждое хранилище, которое вы создаете, получает следующий индекс в своем домене. Существуют отдельные подпространства для ключей токенов и ключей чата Kasia с четным четностью. Схема закреплена по известным тестовым векторам — изменение кода, которое молча меняет вывод, провалит набор тестов, а не сгенерирует неправильные ключи.

Это имеет практическое следствие: одна резервная копия мастер-сида покрывает каждое хранилище и адрес, которые вы когда-либо создадите, включая те, что были сгенерированы после создания резервной копии.

2. Ядро WASM: один крейт Rust, две цели

Всё управление ключами, построение транзакций и шифрование профиля находятся в одном крейте Rust под названием kaspa-safe-core. Он компилируется в две цели:

  • cdylib → WebAssembly, загружаемый браузером. Это то, что фактически выполняется, когда вы генерируете ключи или подписываете транзакцию.
  • rlib → библиотека Rust, связанная с серверными бинарными файлами и инструментом восстановления с открытым исходным кодом vaultctl.

Одна кодовая база, два выхода. Путь браузера использует wasm-pack build --target web; путь сервера/CLI использует прямую компоновку. Крейт зависит от официальных библиотек rusty-kaspa (закрепленных на теге v2.0.1), которые реализуют полный протокол Kaspa — консенсус GHOSTDAG, алгоритм регулировки сложности (DAA) и интроспекцию транзакций — как описано в базе знаний разработчика вики Kaspa. Дополнительные зависимости включают secp256k1, крейт шифрования age и стек ECIES (chacha20poly1305 + k256) для протокола чата в сделках.

Основные модули внутри крейта:

МодульНазначение
derive.rsHD-вывод — пути HMAC-SHA512 с разделением доменов/индексов, тесты по известным векторам
core.rsВычисление адреса хранилища и конструкторы транзакций для всех семи путей расходования ковенантов
escrow_core.rsКомпиляция контракта эскроу и десять путей расходования эскроу
age_crypto.rsШифрование/дешифрование профиля с использованием age scrypt-пароль с ASCII-выводом
bindings.rs / escrow_bindings.rs / chat_bindings.rsТочки входа WASM-bindgen, используемые JavaScript
Определение

WASM (WebAssembly) — бинарный инструкционный формат, работающий в браузерном песочнике на скорости, близкой к нативной. Kaspa Forge компилирует криптографический код Rust в WASM, чтобы та же самая аудированная кодовая база Rust, что работает на сервере, выполнялась и в браузере — нет отдельной JS-реализации, которая могла бы разойтись или отклониться.

Поскольку сервер связывает тот же крейт rlib (за вычетом привязок WASM), логика построения транзакций в вашем браузере и в наблюдателе сервера идентична. Нет теневой реализации на JS, которая могла бы рассинхронизироваться.

3. Зашифрованный профиль Desk

Ваш профиль Desk (версия 3) — это JSON-блок, содержащий:

  • Мастер-сид (зашифрованный в покое)
  • Записи по хранилищам: секретный ключ горячего ключа, секретный ключ ключа тревоги (или флаг, указывающий, что ключ тревоги живет только на физической карте), адрес финансирования, бюджет комиссии, заметка
  • wallet и walletOld — ваш текущий и предыдущий адреса для получения
  • Ключи сделок эскроу и ключи чата

Весь этот блок зашифрован библиотекой age с использованием шифрования паролем на основе scrypt и хранится как ASCII-защищенный файл .age. Шифрование выполняется внутри ядра WASM, поэтому текстовый профиль существует только в памяти браузера во время активной сеансовой работы.

Формат .age не является проприетарным — он совместим со стандартным инструментом командной строки age. Вы можете скопировать файл на USB-накопитель и расшифровать его через несколько лет с помощью:

age -d -o profile.json kaspa-profile.age

Программное обеспечение Kaspa Forge не требуется для шага расшифровки. Эта взаимосовместимость намеренна: вы никогда не должны быть привязаны к одному инструменту для доступа к своим собственным ключам.

4. Жизненный цикл сеанса: разблокировка, подпись, блокировка

Когда вы открываете любую страницу Kaspa Forge — Safe, Escrow, Desk — страж загрузки проверяет, заблокирован ли профиль. Если да, вы должны ввести пароль, чтобы расшифровать профиль в память браузера. С этого момента:

  • Автоблокировка: после 15 минут неактивности текстовый профиль стирается из памяти, и сеанс снова блокируется.
  • Подтверждение при подписи: каждое действие, порождающее криптографическую подпись — отправка KAS, инициация вывода из хранилища, освобождение средств эскроу — требует повторного ввода пароля. Диалог подтверждения показывает точный контекст (сумму и получателя), чтобы вы знали, что одобряете.
  • Нет хранения в открытом виде: расшифрованный сид и секретные ключи существуют только в рантайм-памяти WASM/JS. Они никогда не записываются в localStorage, IndexedDB или любое другое постоянное хранилище браузера в открытом виде.

5. Восстановление без сервиса

Некастодиальная гарантия реальна только тогда, когда она переживает исчезновение сервиса. Kaspa Desk поддерживает два пути восстановления:

Путь 1: Импортируйте ваш .age-файл ключа в любую новую сессию браузера Kaspa Forge. Профиль расшифровывается, HD-вывод заново обнаруживает все адреса — включая хранилища, созданные после резервного копирования — и вы снова в рабочем состоянии.

Путь 2: Офлайн-восстановление через CLI с vaultctl (открытый исходный код, опубликован на GitHub). Передайте ему ваш сид и укажите на любой узел Kaspa v2+ — включая публичный интерфейс на node.kaspaforge.org или ваш собственный узел — и он реконструирует состояния хранилищ и создаст транзакции восстановления, не касаясь kaspaforge.org вовсе.

Механизм восстановления с пробел-сканированием проходит вперед по индексам вывода, проверяя каждый адрес по набору UTXO узла. Сервер помогает, сопоставляя пары адрес-токен, но видит только публичный ключ — никогда сид. Вот почему резервная копия, сделанная до вашего десятого хранилища, все равно восстановит это десятое хранилище.

Как Kaspa Forge использует это в продакшне

Архитектура клиентских ключей, описанная выше, является несущим слоем для каждого инструмента Kaspa Forge:

Kaspa Safe хранит ваш горячий ключ и ключ тревоги в профиле Desk. Когда вы создаете хранилище, ядро WASM выводит свежую пару ключей из мастер-сида, вычисляет P2SH-адрес хранилища из параметров ковенанта и строит транзакцию финансирования — всё в браузере. Сервер получает только публичные ключи и байты подписанной транзакции. Позже, когда вы инициализируете вывод, путь initiate подписывается на стороне клиента; сервер ретранслирует сырые байты на узел Kaspa. Полная механика хранилищ — семь путей расходования, окно отмены с ключом тревоги, наследование мертвого рубильника — документированы отдельно.

Kaspa Escrow используют отдельную пару ключей, выведенную из того же сида (другой сегмент домена в пути HMAC). Адрес контракта эскроу вычисляется из публичных ключей обеих сторон. Сервер ретранслирует зашифрованные сообщения чата и предподписанные транзакции, но ни ключ эскроу, ни ключ чата никогда не передаются в открытом виде на бэкенд. Сообщения чата зашифрованы сквозным шифрованием с использованием ECIES; сервер видит только шифротекст и хеш транзакции BlockDAG, который закрепляет каждое сообщение.

Кошелек Desk суммирует UTXO по всем выведенным адресам (wallet + walletOld) и тратит их в одной транзакции, причем каждый вход подписан своим соответствующим выведенным ключом. Эндпоинт истории транзакций сервера проксирует данные из API Kaspa, чтобы браузер мог отображать входящие и исходящие переводы, не раскрывая IP пользователя сторонним индексаторам.

Если вы хотите увидеть управление ключами на стороне клиента в действии, создайте хранилище Kaspa Safe — весь процесс от генерации сида до финансирования хранилища занимает около двух минут, и каждый криптографический шаг происходит в вашем браузере. Ончейн-операции бесплатны навсегда; только опциональная тревога Telegram несет номинальную ежегодную плату.

Создать сейф

Компромиссы и честные ограничения

Ни один дизайн не обходится без компромиссов. Вот те, которые важны:

Привязка к устройству по умолчанию. Ваш мастер-сид живет в хранилище браузера на одном устройстве. Потеряйте устройство без резервной копии .age — и вы потеряете доступ. Нет восстановления на стороне сервера, нет потока «забыл пароль» — в этом весь смысл, но это означает, что дисциплина резервного копирования лежит на вас.

Единый пароль защищает всё. Файл ключа .age зашифрован одним паролем. Слабый пароль означает, что скомпрометированная резервная копия раскроет все производные ключи. Параметры scrypt в age намеренно дорогие, чтобы замедлить перебор, но пользователь все равно должен выбирать хорошо.

Фрагментация снимков WASM. Браузер загружает разные сборки WASM для разных страниц: app.js (v3) для Safe, escrow.js (v5) для Escrow, core6.js (v6) для криптографии Desk. Новая сборка должна быть развернута во все три каталога снимков, иначе вы получите "core.X is not a function" на некоторых страницах. Это проблема дисциплины развертывания, а не безопасности, но это реальный операционный подводный камень, на который мы натыкались не раз.

Действуют бета-ограничения. Операции хранилищ и эскроу в настоящее время ограничены 50–10 000 KAS на контракт. Эти лимиты защищают от крайних случаев, пока система проходит полевые испытания в реальных условиях, но они являются реальными ограничениями для крупных держателей.

Пока нет интеграции с аппаратными кошельками. Ядро WASM генерирует и управляет ключами программно. Поддержка аппаратных кошельков (Ledger, Trezor) потребовала бы другого пути подписи и на сегодня не поставляется.

Разделение ключа тревоги — опционально. По умолчанию и горячий ключ, и ключ тревоги могут жить в одной сессии браузера. Вы можете хранить ключ тревоги на отдельном устройстве или физической карте (флаг профиля alarm_card:true полностью исключает секретный ключ тревоги из профиля), но из коробки дисциплинированное разделение требует намеренного действия пользователя.

Резюме

Архитектура вкратце: Rust компилируется в WASM для браузера и в нативную библиотеку для серверных инструментов. Один мастер-сид выводит все ключи через HMAC-SHA512 с доменно-разделенными путями. Профиль зашифрован age вашим паролем и хранится как портативный, совместимый файл. Сервер видит публичные ключи и шифротекст — не более того. Подпись происходит в браузере. Восстановление работает офлайн.

Вот что значит «некастодиальный», когда к этому слову относятся серьезно: не просто обещание на целевой странице, а проверяемое свойство кода. Контракты и инструменты с открытым исходным кодом. Если вы умеете читать Rust, вы можете проверить каждое утверждение в этой статье.

FAQ

Где хранится мой приватный ключ?

Ваш приватный ключ генерируется и хранится исключительно в вашем браузере. Ядро WASM Kaspa Forge выводит ключи из мастер-сид, который живет в зашифрованном профиле браузера. Сервер никогда не видит ваш сид, приватные ключи или пароль.

Может ли Kaspa Forge украсть мои средства?

Нет. Сервер получает только публичные ключи, параметры контрактов и предподписанные транзакции. Без вашего приватного ключа — который никогда не покидает браузер — никто в Kaspa Forge не сможет переместить ваши KAS.

Что произойдет, если Kaspa Forge станет недоступен?

Ваши средства останутся в безопасности. Хранилища — это ковенантные контракты на блокчейне. Вы можете восстановить все с помощью инструмента командной строки с открытым исходным кодом vaultctl с любого узла Kaspa v2+, либо импортировав резервную копию вашего .age-файла ключа в новую сессию браузера.

Как работает резервная копия .age-файла ключа?

Файл .age — это ASCII-защищенный, зашифрованный паролем снимок всего вашего профиля Desk — мастер-сид, ключи хранилищ, адреса кошельков. Он совместим со стандартным инструментом командной строки age, поэтому вы можете расшифровать его офлайн, без программного обеспечения Kaspa Forge.

Почему WASM, а не JavaScript для криптографии?

Один и тот же крейт Rust компилируется как в WASM (браузер), так и в нативную библиотеку (сервер/CLI). Единая аудированная кодовая база обрабатывает вывод ключей, построение транзакций и шифрование везде — нет отдельной JS-реализации, которая могла бы разойтись или отклониться.

Может ли моя резервная копия .age восстановить хранилища, созданные после её создания?

Да. Все ключи выводятся детерминированно из мастер-сида с использованием индексированных путей. Восстановление с пробел-сканированием проходит вперед по этим индексам, поэтому любое хранилище или адрес кошелька, сгенерированные после резервного копирования, будут обнаружены автоматически.

Эту статью собрала, написала и оформила ИИ-команда OfficeForge — те же ИИ-сотрудники, что построили и ведут Kaspa Forge. Направляет основатель, проверено командой.

Некастодиально · открытый код

Держите KAS там, где кражу можно отменить

Ковенант-сейф в мейннете Kaspa: ваши ключи, ваши правила, наш инструмент. Ончейн — бесплатно, навсегда.

Создать сейф