31 июля 2026 года в 01:31 UTC биткоин начал уходить с кошельков, чьи владельцы не сделали ровным счётом ничего. К 01:56 — двадцать пять минут спустя — около 594 BTC, примерно $38 млн, были выведены приблизительно с 500 кошельков с одной подписью. Более поздний анализ Galaxy Research и материалы Chainalysis связали с инцидентом до примерно 1 083 BTC на порядка 1 196 адресах. Никого не фишили. Никто не устанавливал вредоносное ПО. Никто не одобрял транзакцию. Единственное, что объединяло пострадавших, — дата создания их кошелька, потому что отказала энтропия кошелька: случайность, из которой делается сид-фраза, зафиксированная в первую секунду жизни кошелька.
Кошельки были сгенерированы на аппаратных устройствах Coldcard, а стоявшая за этим уязвимость больше пяти лет просидела в выпущенной прошивке. В этой статье — что произошло, почему этот класс ошибок остаётся невидимым, что это говорит и чего не говорит об аппаратных кошельках — и что стоит спросить о случайности любого кошелька, включая наш.
Уязвимость 2021 года, обналиченная в 2026-м
Согласно бюллетеню Coinkite, уязвимость появилась в прошивке Coldcard 4.0.0, выпущенной в марте 2021 года. На затронутых устройствах генерация сида пропускала аппаратный генератор случайных чисел и откатывалась к ключевому материалу, засеянному несекретными данными чипа. Сид-фраза BIP39 должна кодировать 128 бит энтропии — 2¹²⁸ возможных сидов, пространство, которое не переберёт ни один злоумышленник. Сиды, сгенерированные на затронутых устройствах Mk3, вместо этого несли примерно 40 бит эффективной энтропии. 2⁴⁰ — это около 1,1 триллиона кандидатов: колоссально для человека, полностью перебираемо для машины. Вот вся уязвимость Coldcard в одном предложении: устройство тихо перестало использовать собственную случайность, и ничто видимое этого не выдало.
Две группы пользователей не пострадали вовсе: те, кто создавал сид с passphrase BIP39, и те, кто генерировал его из 50 и более бросков игральной кости. Coinkite раскрыла проблему и выпустила исправленную прошивку — 5.6.0 для Mk4 и Mk5, 1.5.0Q для Q. Все пять лет между этими точками затронутые кошельки работали безупречно и выглядели неотличимо от безопасных. Тому, кто провёл эту зачистку, ни разу не понадобилось касаться жертв: перебрать слабое пространство ключей, вывести адреса, сопоставить их с блокчейном и перевести всё за одно 25-минутное окно.
Тихая деградация энтропии: почему сиды выглядели случайными
Тревожнее всего то, что в затронутых сидах никогда ничего не выглядело неправильным. Сид, построенный из 40 бит предсказуемого материала, всё равно выходит в виде двенадцати совершенно обычных слов BIP39 с корректной контрольной суммой. Кошелёк принимает его, выводит адреса, подписывает транзакции; каждый экран показывает ровно то, что показал бы сильный кошелёк.
Статистическое тестирование тоже не поможет: детерминированный генератор, засеянный предсказуемыми данными, всё равно выдаёт вывод, который проходит тесты на случайность, — биты хорошо распределены, просто взяты из катастрофически малого множества возможных последовательностей. Слабость живёт в свойстве, которое не раскроет никакой вывод: сколько других сидов могло бы быть сгенерировано вместо этого. Ответ хранится только в коде генерации.
Слабый сид не выглядит слабым. Разница между 2¹²⁸ и 2⁴⁰ существует только в коде, который создал эти слова.
Именно поэтому этот класс ошибок живёт годами — и поэтому инцидент с Coldcard принадлежит к целому семейству. Milk Sad в инструменте bx из Libbitcoin, генератор MT19937 в браузерном расширении Trust Wallet, Cake Wallet, инструмент генерации vanity-адресов Profanity и Randstorm в ранних браузерных кошельках имеют одну и ту же форму: CSPRNG, тихо подменённый предсказуемым источником, — без ошибки, без предупреждения, без видимой разницы, пока кто-нибудь не переберёт пространство ключей.
Неудобный урок
«Аппаратный кошелёк» — это название форм-фактора, а не гарантия. Кошельки, опустошённые 31 июля, были созданы на специализированном подписывающем железе — и отказал не этот слой. Выживание определило свойство, зафиксированное годами раньше: то, как был сгенерирован сид в день создания кошелька. Всё, что идёт дальше, — холодное хранение, подписание с воздушным зазором, тщательная проверка — защищает ключ от кражи. Ничто из этого не помогает, если ключ можно сгенерировать заново.
Не менее важно и то, что Coinkite раскрыла уязвимость и оперативно выпустила исправленную прошивку. Это не история о небрежном вендоре; это режим отказа, который индустрия переоткрывает снова и снова — и в железе, и в софте. Любой кошелёк — включая наш — находится в одном тихом откате от того же класса ошибок. Честный вопрос не «какой вендор неуязвим?», а «как именно откажет этот кошелёк — и заметит ли это хоть кто-нибудь?».
Пять вопросов о случайности любого кошелька
Не нужно быть криптографом, чтобы поднять планку. Пять вопросов осмысленно сортируют кошельки:
- Каков источник энтропии? Сид должен происходить из CSPRNG, а не из меток времени, идентификаторов устройства или чего-либо ещё, что мог бы реконструировать посторонний.
- Что происходит, если этот источник отказывает? Приемлемый ответ — жёсткая ошибка, останавливающая создание кошелька. Неприемлемый — тихая замена: тихий откат и есть определяющая черта этого класса ошибок.
- Открыт ли исходный код пути генерации и можно ли его проверить? Слабая энтропия невидима в выводе, поэтому ревью кода — единственное место, где её можно поймать.
- Поддерживает ли кошелёк passphrase BIP39? Passphrase добавляет секретный материал, которого генератор устройства никогда не касался. Именно поэтому пользователи passphrase на затронутых Coldcard не потеряли ничего.
- В мультиподписи — генерируются ли ключи на независимых устройствах? Независимые устройства означают независимую случайность: один дефектный генератор компрометирует один ключ, а не кворум.
Как Ownbit генерирует энтропию
Подобные вопросы заслуживают конкретных ответов и о нашем собственном продукте. Генерация мнемонической фразы в Ownbit имеет два слоя. На уровне приложения generateMnemonicRandom(entropy, langIndex) вызывает generateMnemonic из стандартной библиотеки bip39 — 128 бит энтропии по умолчанию и поддержка восьми списков слов BIP39: английского, упрощённого и традиционного китайского, японского, французского, итальянского, корейского и испанского. На уровне библиотеки randomBytes в bip39 черпает случайность из crypto.getRandomValues — платформенного CSPRNG.
Важно здесь то, что происходит, когда этот источник недоступен: библиотека выбрасывает ошибку. Она не обращается ни к часам, ни к идентификатору чипа, ни к какому-либо вторичному источнику — пути отката в коде просто нет. Режим отказа — громкая ошибка в момент создания, и никогда — тихо ослабленный сид. Это свойство — падать громко и никогда не откатываться — прямая противоположность уязвимости, стоявшей за инцидентом с Coldcard, Milk Sad и Randstorm, где генерация тихо продолжала работу от предсказуемого источника.
Мы не станем утверждать, что это делает Ownbit неуязвимым для ошибок; этого не может ни один честный вендор. Но по самой конструкции это устраняет данную форму отказа: в коде не существует пути, на котором кошелёк Ownbit тихо сгенерирует слабый сид. Остальная часть модели изложена на нашей странице безопасности.
Почему независимо сгенерированные ключи переживают этот класс ошибок
Зачистка 31 июля ударила по кошелькам с одной подписью: один сид, одна подпись — и средств нет; хрестоматийный случай того, как сид-фраза становится единой точкой отказа. Мультиподпись меняет арифметику. В MultiSig-кошельке Ownbit каждый ключ — это собственная стандартная сид-фраза BIP39, сгенерированная на устройстве самого участника. Предположим, одно из устройств несло ровно этот класс уязвимости. В кошельке 2-из-3 злоумышленник, перебравший слабое пространство ключей, держит один ключ — ниже порога. Ничего не движется. Слабый ключ становится задачей обслуживания — заменить его, — а не потерей.
Защиту даёт независимость, а не слово «мультиподпись». Три ключа соподписантов, сгенерированные на одной и той же дефектной модели устройства, отказали бы вместе. Три ключа, родившиеся на по-настоящему разных устройствах — ваш повседневный телефон, запасной телефон, который держат офлайн как холодный кошелёк с подписанием по QR, устройство члена семьи, — не делят между собой генератор, а значит, не делят и баг. Та же логика объясняет, почему passphrase BIP39 спасла затронутых пользователей Coldcard: passphrase — это секретный материал, который ГСЧ устройства никогда не производил, поэтому перебора 2⁴⁰ сидов для трат оказалось недостаточно.
Если у вас затронутый Coldcard
Три действия:
- Обновите прошивку. Исправленные версии, названные в бюллетене Coinkite, — 5.6.0 для Mk4 и Mk5 и 1.5.0Q для Q.
- Переведите средства на новый сид, сгенерированный на исправленной прошивке. Обновление защищает будущие сиды; усилить уже существующий оно не может. Сид, родившийся с примерно 40 битами, остаётся перебираемым навсегда — выведите его из обращения полностью, никогда не используйте повторно и никогда не отправляйте средства обратно на его адреса.
- Никогда не вводите существующую сид-фразу ни на каком сайте, предлагающем «проверить», уязвима ли она. Ввод сида во что угодно онлайн — это ровно то, как забирают оставшиеся средства; сайты-«чекеры» — устойчивый фишинговый шаблон после подобных инцидентов.
Часто задаваемые вопросы
Что такое энтропия кошелька?
Энтропия кошелька — это случайность, используемая при создании сид-фразы. Стандартный сид BIP39 из 12 слов кодирует 128 бит энтропии — 2¹²⁸ возможных сидов. Если генератор предсказуем, реальное число возможных сидов схлопывается, и злоумышленник может перебрать их независимо от того, как сид хранился потом.
Затронут ли мой Coldcard?
Согласно бюллетеню Coinkite, уязвимость появилась в прошивке 4.0.0 в марте 2021 года, и затронутые сиды Mk3 несли примерно 40 бит эффективной энтропии вместо 128. Сиды, созданные с passphrase BIP39 или из 50 и более бросков игральной кости, риску не подвержены. Если сомневаетесь, обновитесь до исправленной прошивки — 5.6.0 для Mk4/Mk5, 1.5.0Q для Q — и переведите средства на заново сгенерированный сид.
Можно ли распознать слабый сид, глядя на него?
Нет. Слабый сид всё равно даёт двенадцать нормальных слов с корректной контрольной суммой, а статистические тесты не могут выявить предсказуемый источник. Стойкость — свойство кода генерации, а не самих слов; именно поэтому затронутые кошельки оставались незамеченными больше пяти лет.
Защищает ли мультиподпись от слабой энтропии?
Структурно — да, при условии что ключи сгенерированы на независимых устройствах. Один слабый ключ даёт злоумышленнику одну подпись — ниже порога M-из-N, — поэтому средства не двигаются. Ключи, сгенерированные на одной и той же дефектной модели устройства, могли бы отказать вместе — вот почему независимость важна не меньше самого порога.
Стоит ли перестать пользоваться аппаратными кошельками?
Нет. Урок уже: сами слова «аппаратный кошелёк» — ещё не гарантия; гарантия — то, как был сгенерирован сид. Продолжайте пользоваться хорошо поддерживаемыми устройствами, устанавливайте обновления прошивки, добавляйте passphrase BIP39 там, где она поддерживается, и держите серьёзные балансы за порогом мультиподписи, а не за каким-либо одним сидом.
Если этот инцидент заставил вас пересмотреть собственную схему хранения, структурное решение — перестать оставлять какой-либо один сид в одиночку между вашими средствами и злоумышленником. MultiSig-кошелёк Ownbit ставит порог M-из-N поверх ключей, сгенерированных на независимых устройствах, и каждый из них — стандартная сид-фраза BIP39. Каждый новый пользователь получает 7-дневный бесплатный период, и ваши ключи в любом случае остаются вашими.