Каждый браузерный кошелёк по-своему отвечает на один и тот же вопрос: *где хранятся приватные ключи и кто может их прочитать?* Desk от Kaspa Forge занимает чёткую позицию: ключи генерируются в вашем браузере, при хранении шифруются утилитой age и находятся в памяти только во время активной сессии, которая автоматически блокируется через 15 минут. Ни один сервер никогда не видит открытый текст. А один единственный файл резервной копии, расшифрованный только вашим паролем, восстанавливает все ключи, которые вы когда-либо будете использовать в Kaspa Safe, Escrow, Deposit и Marketplace.
В этом разборе мы подробно пройдём через конверт шифрования, формат профиля, модель безопасности сессии и пути восстановления — с честными замечаниями о том, от чего эта конструкция защищает и от чего — нет.
Где хранятся ключи — и пространство компромиссов
Существует три распространённых подхода к хранению ключей в браузерных кошельках, каждый с известным недостатком:
- Зашифрованные ключи на сервере. Удобно, но вы доверяете оператору, что он не будет логировать ваш пароль или отвечать на запросы о данных.
- Открытый текст в браузере (
localStorage/IndexedDB). Быстро, но любая инъекция JavaScript — XSS, скомпрометированная зависимость, вредоносное расширение — может вытащить ключ. - Аппаратный подписантер (Ledger, Trezor). Ключи никогда не попадают в браузер. Надёжно, но добавляет стоимость и неудобство в использовании.
Desk от Kaspa Forge выбирает четвёртый путь: зашифровать весь профиль парольной фразой пользователя с помощью .age (современного, прошедшего аудит инструмента шифрования файлов), хранить шифротекст в браузере и расшифровывать в память только внутри активной сессии. Сама парольная фраза нигде не сохраняется.
Что такое шифрование .age
age (читается как английское слово «эйдж») — утилита шифрования файлов, разработанная Филиппо Вальсорда. Её цели — простота и современная криптография: одна команда для шифрования, одна для дешифрования, без связок ключей и PKI. Режим парольной фразы использует scrypt — ресурсоёмкую функцию вывода ключей, которая делает полный перебор с ускорением на GPU крайне затратным.
Kaspa Forge реализует тот же протокол на Rust внутри WASM-ядра (age_crypto.rs). Две публичные функции отвечают за работу с конвертом:
pub fn encrypt_armored(passphrase: &str, plaintext: &[u8]) -> String
pub fn decrypt_armored(passphrase: &str, armored: &str) -> Result<Vec<u8>>
Обе выполняются полностью в браузере — модуль WASM работает в изолированной песочнице, парольная фраза никогда не покидает клиент, а в localStorage сохраняется только шифротекст (или экспортируется как .age файл для резервного копирования).
.age файл — файл, зашифрованный утилитой age-encryption.org. Kaspa Forge использует режим парольной фразы scrypt: ваш пароль — единственный ключ. На выходе получается ASCII-армированный формат, который переживёт вставку в буфер обмена, отправку по почте и любой текстовый транспорт.
Критически важное свойство: .age файл, который вы скачиваете как резервную копию, побайтово совместим с оригинальным CLI. На любом компьютере с установленным age вы можете расшифровать профиль Kaspa Forge самостоятельно:
age -d -o profile.json my-backup.age
# введите парольную фразу
# → расшифрованный profile.json с вашим мастер-сидом HD, ключами и метаданными хранилища
Никакого ПО Kaspa Forge. Никакого работающего сервера. Это основа гарантии некастодиальности: прекращение работы сервиса не означает потерю средств.
Внутри зашифрованного профиля (версия 3)
Расшифрованный профиль — это JSON-документ с тегом version: 3. Вот что он содержит:
| Поле | Назначение |
|---|---|
seed | Мастер-сид HD — все ключи выводятся из этого одного 32-байтного значения |
hot_sk | Горячий подписывающий ключ для вывода из хранилища (или выведенный из сида) |
alarm_sk / alarm_card | Тревожный ключ (hex) или true — см. ниже |
funding_sk / funding_pk | Пара ключей для адресов пополнения хранилища |
fee_budget | Лимит сетевой комиссии (sompi) по умолчанию для транзакций ковенанта |
token | Токен аутентификации владельца для API Kaspa Forge |
wallet / walletOld | Текущий и предыдущий адреса получения |
note | Личная метка пользователя для хранилища |
Самое важное поле — seed. Из этого одного значения все ключи для всех продуктов Kaspa Forge выводятся детерминированно с помощью HMAC-SHA512 с доменно-разделёнными сообщениями:
HMAC-SHA512(key=seed, msg="kaspaforge/v1/vault/0") → горячий ключ хранилища 0
HMAC-SHA512(key=seed, msg="kaspaforge/v1/vault/1") → горячий ключ хранилища 1
HMAC-SHA512(key=seed, msg="kaspaforge/v1/escrow/0") → чат-ключ эскроу-сделки 0
Доменная строка кодирует продукт и индекс, поэтому ключи никогда не пересекаются между инструментами. Практический итог: одна резервная копия .age, сделанная сегодня, покрывает каждое хранилище, сделку, депозит и объявление, которые вы когда-либо создадите — даже те, которых ещё не существует. Вывод генерирует их по требованию.
Тревожная карта: ключ за пределами профиля
При создании хранилища Kaspa Safe вы настраиваете два ключа: горячий ключ (для инициирования вывода) и тревожный ключ (для отмены вывода в процессе — как мера противодействия краже). Горячий ключ всегда хранится в зашифрованном профиле. А для тревожного ключа предусмотрена альтернатива.
Если вы включите alarm_card, приватный тревожный ключ генерируется однократно, отображается на экране для записи на бумагу или физическую карту и никогда не сохраняется в профиле. В профиле остаётся только логический флаг.
Выигрыш в безопасности — разделение: злоумышленник, извлекший ваш .age файл и подобравший парольную фразу, получает горячий ключ, но не тревожный. Он сможет инициировать вывод, но вы сможете отменить его в окне задержки с помощью физической карты. И наоборот, кража одной только карты не позволяет инициировать вывод. Два сценария компрометации независимы.
Безопасность сессии: браузер как сейф
Шифрование при хранении — это лишь половина защиты. Когда вы реально пользуетесь Desk — проверяете баланс, подписываете вывод, присоединяетесь к эскроу-сделкам — ключи должны быть расшифрованы. Вот как работает слой выполнения:
Страж запуска (requireUnlock). Каждая страница Kaspa Forge при загрузке проверяет наличие активной сессии. Если её нет, интерфейс показывает запрос пароля. Зашифрованный профиль расшифровывается в память, а временная метка сессии фиксируется.
Подтверждение каждого действия (confirmPassword). Любая операция, формирующая подписанную транзакцию — отправка KAS, инициирование вывода из хранилища, освобождение средств эскроу — повторно запрашивает пароль. При запросе отображается контекст: сумма и адрес получателя. Это создаёт осознанный барьер «вы уверены?», который также защищает от подглядывания через плечо.
Автоблокировка (15 минут). После 15 минут бездействия сессия уничтожается. Расшифрованные ключи обнуляются из памяти (насколько это позволяет JavaScript), а следующее действие требует полной разблокировки.
Никакого сохранённого пароля. Парольная фраза никогда не записывается в localStorage, sessionStorage, cookies или какое-либо постоянное хранилище. Она существует только в переменной JavaScript во время активной сессии. Обновление страницы или закрытие вкладки требуют повторного ввода.
Это сознательный компромисс: вы вводите пароль чаще, чем потребовало бы кастодиальное приложение. Для инструмента, хранящего реальные средства в сети proof-of-work, каждый запрос — это осознанная авторизация.
Восстановление без сервера
Три пути восстанавливают доступ при потере устройства, и ни один не требует, чтобы Kaspa Forge был в сети:
Файл резервной копии .age + парольная фраза. Расшифруйте с помощью оригинального CLI age -d или опубликованного Kaspa Forge файла keyfile-decrypt.html — автономной HTML-страницы, выполняющей дешифровку age в вашем браузере, полностью офлайн. Извлеките мастер-сид HD. Затем используйте recover.html для gap-сканирования: он последовательно выводит адреса из вашего сида и запрашивает сеть Kaspa на наличие истории UTXO.
Только сид. Если вы записали мастер-сид HD при создании хранилища, можно полностью обойтись без .age файла. Инструмент с открытым исходным кодом vaultctl выполняет gap-сканирование через любой публичный узел Kaspa:
vaultctl recover --seed <hex> --node node.kaspaforge.org
vaultctl для всего. Помимо восстановления, vaultctl выполняет все операции с хранилищем — проверка баланса, инициирование вывода, отмена, завершение, проверка, наследование, миграция — из терминала через любой узел Kaspa v2+. Никакого веб-интерфейса, никакого JavaScript, никакого сервера.
Фундаментальная гарантия: ваши хранилища — это ончейн-ковенантные контракты, исполняемые сетью Kaspa. Задержка вывода, правило тревожного ключа и логика наследования встроены в скрипт блокчейна, а не в базу данных, контролируемую kaspaforge.org.
Попробуйте сами. Создайте хранилище Kaspa Safe — ончейн-операции бесплатны навсегда. Скачайте резервную копию .age, затем убедитесь, что можете расшифровать её самостоятельно с помощью age -d. Вы получите уверенность из первых рук, что ваши ключи переживут любой единичный отказ.
От чего эта модель защищает — и от чего нет
Честный анализ безопасности требует рассмотреть обе стороны.
Защита от:
- Компрометация сервера. Бэкенд никогда не видит ключи, сид или парольную фразу. Утечка ничего не раскроет о ваших средствах.
- Инъекция в браузерную вкладку (частично). Автоблокировка и запрос пароля при каждом действии сужают окно для внедрённого скрипта. Устойчивая XSS-атака на ту самую страницу, где ключи находятся в памяти, теоретически может действовать во время активной сессии — но это окно ограничено.
- Потеря устройства. Резервная копия
.ageвосстанавливает всё. Тревожная карта (если используется) обеспечивает независимый путь восстановления для отмены. - Прекращение работы сервиса. Правила ковенанта,
vaultctlиkeyfile-decrypt.htmlработают без серверов Kaspa Forge.
Нет защиты от:
- Слабая парольная фраза. Безопасность
.ageфайла сводится к стойкости вашего пароля против перебора scrypt. Короткий или словарный пароль — самое слабое звено во всей цепи. - Полная компрометация устройства. Если вредоносное ПО получило root- или kernel-доступ, оно может перехватить пароль при вводе и читать память во время сессии. Это фундаментальное ограничение программных кошельков — аппаратные подписанты его решают. Архитектура Kaspa Forge не исключает будущей интеграции аппаратных кошельков.
- Потеря всех резервных копий и пароля. Серверного эскроу нет. Это сделано намеренно: пользователь несёт полную ответственность за резервирование. Один
.ageфайл на USB-накопителе, одна записанная парольная фраза в отдельном месте — это минимально жизнеспособная резервная копия. - Компрометация обоих ключей — горячего и тревожного. Если злоумышленник получит оба ключа одновременно (например, из профиля при отключённом
alarm_card), единственным оставшимся препятствием будет временная задержка. Путьmigrate— требующий обе подписи — позволяет перевести средства мгновенно. Это принятый компромисс в дизайне хранилища, мотивирующий использование тревожной карты для хранилищ с большими суммами.
Один профиль — все продукты
Зашифрованный профиль Desk — это единый слой идентификации для всего стека Kaspa Forge:
- Kaspa Safe считывает горячие/тревожные ключи и параметры хранилища из профиля.
- Kaspa Escrow выводит чат-ключи и подписывающие ключи эскроу для каждой сделки из того же мастер-сида HD.
- Kaspa Deposit использует те же пути ключей эскроу — он работает на том же ончейн-ковенанте.
- Marketplace переиспользует инфраструктуру эскроу — один профиль обеспечивает чат объявлений, создание сделок и участие в спорах.
- Кошелёк выводит адреса получения и подписывает расходные транзакции выведенными ключами.
Один .age файл, один пароль, все продукты. Мастер-сид HD с доменным разделением в центре конверта шифрования делает это возможным без повторного использования или коллизий ключей, а одна резервная копия покрывает всё.
FAQ
Может ли Kaspa Forge видеть мои приватные ключи?
Нет. Ключи генерируются в вашем браузере через WASM, шифруются вашей парольной фразой с помощью age и хранятся только в localStorage вашего браузера. Сервер никогда не получает сид в открытом виде, подписывающие ключи или пароль.
Что такое .age файл?
Файл, зашифрованный утилитой age-encryption.org. Kaspa Forge использует режим парольной фразы scrypt: из вашего пароля через ресурсоёмкую функцию вывода ключей (KDF) формируется ключ дешифрования. Формат — ASCII-армированный, совместим со стандартным CLI age.
Что будет, если я забуду пароль от Desk?
Если у вас есть резервная копия .age, но пароль утерян, файл невозможно расшифровать — scrypt делает полный перебор непрактичным для достаточно сложных паролей. Если вы отдельно записали мастер-сид HD при создании хранилища, вы можете восстановить ключи без .age файла. В противном случае средства остаются в блокчейне, но недоступны до тех пор, пока вы не восстановите ключи.
Резервная копия покрывает будущие хранилища и сделки?
Да. Все ключи выводятся из одного мастер-сида HD по доменно-разделённым путям HMAC-SHA512. Резервная копия, сделанная сегодня, покрывает каждое хранилище, эскроу-сделку, депозит и взаимодействие с маркетплейсом, которые вы когда-либо создадите.
Что делает тревожная карта?
При включении тревожный (отменяющий) ключ хранилища записывается на физическую карту, а не в зашифрованный профиль. Злоумышленник, получивший ваш .age файл и подобравший парольную фразу, получает горячий ключ, но не тревожный: он сможет инициировать вывод, но вы сможете отменить его в окне задержки.
Можно ли использовать аппаратный кошелёк с Kaspa Forge?
На данный момент — нет. Профиль Desk использует программные ключи, обрабатываемые в браузерном WASM. Архитектура не исключает интеграции аппаратных подписей в будущем, но сейчас вся подпись происходит в браузере.
Держите KAS там, где кражу можно отменить
Ковенант-сейф в мейннете Kaspa: ваши ключи, ваши правила, наш инструмент. Ончейн — бесплатно, навсегда.
Создать сейф
