Перейти к основному содержимому

Энтропия и случайность в криптовалюте: почему это важно

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

Это руководство объясняет, что означает энтропия в криптографическом контексте, как работают генераторы случайных чисел, что исторически шло не так при сбоях случайности и как убедиться, что генерация ваших ключей надежна.

Что такое энтропия?

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

256-битный приватный ключ должен иметь 256 бит энтропии, то есть злоумышленнику в среднем потребуется 2^255 попыток, чтобы его найти (в среднем половина пространства поиска). Если ключ был сгенерирован только с 32 битами реальной энтропии (из-за дефектного RNG), злоумышленнику понадобится лишь около 2^31 попыток, примерно 2 миллиарда, что современный компьютер может перебрать за минуты.

Измерение энтропии

Энтропия измеряется в битах. Энтропия случайной величины X:

H(X) = -sum(p(x) * log2(p(x))) for all possible values x

Для равномерно случайного 256-битного числа:

  • Каждый бит имеет вероятность 0.5 быть 0 или 1.
  • Энтропия = 256 бит (максимум для такого размера).

Для смещенного генератора, где каждый бит имеет вероятность 0.7 быть равным 1:

  • Энтропия на бит = -(0.7 * log2(0.7) + 0.3 * log2(0.3)) = 0.881 бит.
  • Общая энтропия для 256 бит = 225.5 бит (на 11.9% меньше идеала).

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

Энтропия в контексте BIP-39

Длина мнемоникиЭнтропияУровень безопасностиBrute-Force при 10^12/сек
12 слов128 бит128-бит~10^19 лет
15 слов160 бит160-бит~10^28 лет
18 слов192 бит192-бит~10^38 лет
24 слова256 бит256-бит~10^57 лет

Эти значения предполагают, что энтропия действительно равномерна. Если RNG дефектен, фактический уровень безопасности может быть значительно ниже.

Типы генераторов случайных чисел

Истинные генераторы случайных чисел (TRNG)

TRNG используют физические явления, которые принципиально непредсказуемы на квантовом уровне:

  • Тепловой шум - случайные колебания напряжения в резисторах из-за теплового движения электронов.
  • Дробовой шум - случайные колебания тока из-за дискретной природы потока электронов.
  • Радиоактивный распад - время отдельных актов распада принципиально непредсказуемо.
  • Атмосферный шум - радиочастотный шум от молний и других атмосферных процессов.

Аппаратные кошельки, такие как Ledger и Trezor, используют встроенные TRNG. Они считывают физические источники шума и обрабатывают выход через whitening и health tests.

Преимущества: Истинная случайность из физики; нет детерминированного состояния для предсказания.
Недостатки: Зависимость от железа; возможен тихий отказ при деградации источника шума; пропускная способность может быть ограничена.

Криптографически стойкие псевдослучайные генераторы (CSPRNG)

CSPRNG - это детерминированный алгоритм, который выдает результат, неотличимый от истинной случайности, при достаточно случайном seed:

  • Linux: /dev/urandom (использует ChaCha20 или похожий шифр, seed берется из аппаратной энтропии).
  • macOS: /dev/urandom (arc4random, seed берется из аппаратной энтропии).
  • Windows: BCryptGenRandom (провайдер CNG).
  • Веб-браузеры: crypto.getRandomValues() (делегирует в CSPRNG ОС).
  • Python: os.urandom() или модуль secrets.
  • Node.js: crypto.randomBytes().

Преимущества: Быстро; хорошо изученные алгоритмы; доступно на всех платформах.
Недостатки: Сила зависит от начальной seed-энтропии; детерминированность - если внутреннее состояние известно, весь будущий вывод предсказуем.

Некриптографические PRNG (НИКОГДА не используйте для ключей)

Стандартные функции случайных чисел в большинстве языков программирования предназначены для статистического моделирования, а не для криптографии:

  • Python: random.random() (Mersenne Twister - детерминированный, состояние восстанавливается по 624 значениям).
  • JavaScript: Math.random() (xorshift128+ в V8 - предсказуем).
  • C: rand() (линейный конгруэнтный генератор - тривиально предсказуем).
  • Java: java.util.Random (линейный конгруэнтный - предсказуем).

У этих генераторов низкая энтропия, короткие периоды и предсказуемое состояние. Использовать их для генерации ключей означает фактически не использовать случайность вообще. Никогда не создавайте приватные ключи или сид-фразы с помощью этих функций.

Исторические провалы случайности

Баг Android SecureRandom (2013)

В августе 2013 года был обнаружен критический дефект в реализации SecureRandom на Android. Java PRNG на некоторых устройствах Android не инициализировался seed должным образом, из-за чего несколько приложений Bitcoin-кошельков генерировали приватные ключи из предсказуемого состояния. Злоумышленник использовал это и украл примерно 55 BTC. Баг затрагивал генерацию nonce для подписи ECDSA: повторное использование одного и того же nonce позволяет вычислить приватный ключ по двум подписям.

"Blockchain Bandit" (2019)

Исследователь безопасности Adrian Bednarek обнаружил, что кошельки создавались с тривиально слабыми приватными ключами, например 1, 2, 3 или простыми словарными словами, хешированными один раз. Злоумышленник годами систематически выводил средства с этих адресов и накопил более 45,000 ETH. Он просто перебирал ключи с низкой энтропией и проверял, есть ли на них средства.

Примеры ключей, с которых вывели средства:

  • Приватный ключ 0x0000000000000000000000000000000000000000000000000000000000000001 (число 1)
  • Приватные ключи, полученные из распространенных паролей и фраз

Уязвимость Milk Sad (2023)

Команда seed в инструменте libbitcoin-explorer (bx) использовала Mersenne Twister, seed которого состоял только из 32 бит системного времени. Это означало, что все ключи, сгенерированные этим инструментом, имели максимум 32 бита энтропии, примерно 4.3 миллиарда вариантов. Злоумышленники перебрали эти ключи и украли средства.

Баг слабых ключей Debian OpenSSL (2008)

Сопровождающий Debian случайно удалил строку кода, добавлявшую энтропию в генератор случайных чисел OpenSSL. В течение двух лет (2006-2008) каждый криптографический ключ, сгенерированный в Debian и Ubuntu, имел только 15 бит энтропии от process ID, что давало максимум 32,767 уникальных ключей. Все SSH-ключи, SSL-сертификаты и любые криптовалютные ключи, созданные в этот период на затронутых системах, были скомпрометированы.

Выводы

  1. Никогда не доверяйте одному источнику энтропии без проверки.
  2. Небольшие ошибки реализации могут катастрофически снизить энтропию.
  3. Злоумышленники активно используют слабую случайность, это не теория.
  4. Открытый и аудированный код критически важен для операций, чувствительных к энтропии.

Источники энтропии подробнее

Пул энтропии операционной системы

Современные ОС поддерживают пул энтропии, который пополняется из нескольких источников:

  • Тайминг прерываний - время аппаратных прерываний (клавиатура, мышь, диск, сеть) дает непредсказуемый ввод.
  • Тайминг дискового I/O - точное время чтения/записи меняется из-за механических и электронных факторов.
  • Аппаратный RNG - современные CPU (Intel RDRAND, AMD) включают встроенные генераторы случайных чисел.
  • Энтропия при загрузке - некоторые системы сохраняют энтропию между перезагрузками (/var/lib/systemd/random-seed в Linux).

ОС смешивает эти источники в пуле энтропии с помощью криптографических примитивов, затем использует пул для seed своего CSPRNG. В современных ядрах Linux (5.18+) /dev/urandom блокируется до сбора достаточной энтропии при загрузке, после чего больше не блокируется.

Энтропия в браузере (crypto.getRandomValues)

Когда вы используете веб-инструмент, например генератор SafeSeed, применяется API браузера crypto.getRandomValues(). Он делегирует работу CSPRNG операционной системы:

  • Chrome: делегирует CSPRNG ОС (BoringSSL).
  • Firefox: делегирует CSPRNG ОС (NSS).
  • Safari: делегирует CSPRNG ОС (CommonCrypto).

Это считается безопасным для генерации ключей, если базовая ОС безопасна. Основной риск - запуск в среде, где CSPRNG ОС может быть скомпрометирован (например, виртуальная машина с недостаточными источниками энтропии или скомпрометированная операционная система).

Энтропия аппаратных кошельков

Аппаратные кошельки используют встроенные истинные генераторы случайных чисел:

  • Ledger (Secure Element ST33): использует TRNG чипа ST33, который считывает аналоговый шум. Перед использованием результат проходит health tests NIST SP 800-90B.
  • Trezor: использует аппаратный RNG чипа STM32. Trezor также поддерживает смешивание с энтропией от пользовательских бросков кубика.
  • Coldcard: использует TRNG secure element ATECC608A плюс аппаратный RNG MCU, смешивая оба источника.

Энтропия от бросков кубика

Ручные броски кубика - самый прозрачный метод генерации энтропии:

  • Честный шестигранный кубик дает log2(6) = 2.585 бит энтропии на бросок.
  • 100 бросков дают примерно 258.5 бит энтропии, этого достаточно для сид-фразы из 24 слов.
  • Пользователь может физически проверить случайность (честные кубики, честные броски, без манипуляций).

Проверка честности кубика:

  • Используйте прецизионные кубики казино-качества (острые грани, не скругленные).
  • Бросайте на твердую ровную поверхность с бортиком.
  • Не "ставьте" кубики, пусть они свободно перекатываются.
  • Сразу записывайте каждый результат по порядку.
Инструмент SafeSeed

Генератор сид-фраз SafeSeed позволяет ввести собственную энтропию (например, результаты бросков кубика) для генерации сид-фразы BIP-39. Это позволяет проверить источник случайности и при этом использовать корректную реализацию BIP-39 в инструменте. Для максимальной безопасности используйте инструмент офлайн, см. наше руководство по офлайн-генерации ключей.

Тестирование и проверка случайности

Набор статистических тестов NIST

NIST SP 800-22 определяет набор статистических тестов для оценки генераторов случайных чисел:

  • Frequency test - примерно ли одинаково количество 0 и 1?
  • Block frequency test - равномерно ли распределены подблоки битов?
  • Runs test - имеют ли серии одинаковых подряд битов (runs) ожидаемую длину?
  • Longest run test - находится ли самая длинная серия в ожидаемых границах?
  • Matrix rank test - соответствуют ли ранги бинарных матриц ожидаемым распределениям?
  • Spectral test - показывает ли DFT битовой последовательности ожидаемые свойства?

Эти тесты могут выявлять смещения и шаблоны, но не могут доказать безопасность генератора. Они могут только обнаруживать сбои.

Набор тестов Dieharder

Более полный набор статистических тестов, включающий оригинальные тесты Diehard и дополнительные проверки. Доступен как open-source ПО в Linux.

Практическая проверка для пользователей

Большинство пользователей не могут запускать наборы тестов NIST. Практические шаги проверки:

  1. Проверка источника - использует ли инструмент crypto.getRandomValues(), os.urandom() или аппаратный RNG? Проверьте исходный код.
  2. Тест перекрестной генерации - сгенерируйте несколько сид-фраз и убедитесь, что они каждый раз разные.
  3. Отображение энтропии - некоторые инструменты показывают сырую энтропию; проверьте, что она выглядит случайной (без очевидных паттернов).
  4. Open-source аудит - инструмент open-source и проходил аудит?

Смешивание источников энтропии

Лучшая практика для высокозащищенной генерации ключей - смешивать несколько источников энтропии:

Final Entropy = Hash(Hardware RNG output || OS CSPRNG output || User dice rolls || Timing data)

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

XOR-смешивание

Простой метод смешивания - XOR: если у вас есть 256 бит от источника A и 256 бит от источника B:

Mixed = A XOR B

Если A или B действительно случайный, результат действительно случаен. Если оба смещены, но независимы, результат менее смещен, чем каждый из них по отдельности.

Hash-смешивание

Для смешивания источников разной длины или качества хешируйте их вместе:

Mixed = SHA-256(Source_A || Source_B || Source_C)

Хеш-функция выступает как экстрактор энтропии, формируя равномерный вывод независимо от формата входа.

Энтропия в мультиподписных схемах

Кошельки с мультиподписью дают форму избыточности энтропии: даже если один ключ сгенерирован со слабой энтропией, злоумышленнику нужно скомпрометировать и другие ключи. В схеме multisig 2-of-3, где каждый ключ генерируется независимо, безопасность равна самому сильному ключу, а не самому слабому.

Это сильный аргумент в пользу мультиподписных схем для хранения крупных сумм.

FAQ

Что такое энтропия в криптовалюте?

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

Сколько энтропии нужно для безопасного кошелька?

Сид-фраза BIP-39 из 12 слов дает 128 бит энтропии, а фраза из 24 слов дает 256 бит. Оба варианта считаются устойчивыми к brute-force атакам при текущих технологиях. Для долгосрочного хранения высокой ценности рекомендуется 256 бит (24 слова), чтобы получить максимальный запас безопасности.

Безопасен ли Math.random() для генерации криптоключей?

Абсолютно нет. Math.random() и подобные некриптографические PRNG (Python random, C rand()) детерминированы, предсказуемы и имеют низкую энтропию. Их нельзя использовать для генерации криптографических ключей. Всегда используйте crypto.getRandomValues() в браузерах, os.urandom() в Python или аппаратный генератор случайных чисел.

Могу ли я сам придумать случайные числа как источник энтропии?

Нет. Люди очень плохо генерируют случайные числа. Исследования стабильно показывают, что выбранные человеком "случайные" последовательности имеют гораздо меньше энтропии, чем кажется. Используйте физический процесс (кубики, аппаратный RNG) или криптографически стойкий программный RNG.

Как проверить, что генератор случайных чисел моего кошелька безопасен?

Проверьте исходный код кошелька (если он open-source), чтобы убедиться, что используется CSPRNG или аппаратный TRNG. Ищите вызовы crypto.getRandomValues(), os.urandom() или API аппаратного RNG. Для аппаратных кошельков изучайте документацию производителя по безопасности и отчеты сторонних аудитов.

Что такое "blockchain bandit" и чему это учит про энтропию?

"blockchain bandit" - это злоумышленник, который систематически крал криптовалюту из кошельков, созданных со слабыми приватными ключами (например, 1, 2, 3 или ключи из простых паролей). Это показало, что атакующие активно перебирают ключи с низкой энтропией и выводят любые найденные средства. Это подчеркивает критическую важность генерации случайных чисел с высокой энтропией.

Можно ли доверять генераторам случайных чисел в аппаратных кошельках?

TRNG в аппаратных кошельках в целом заслуживают доверия, но это одна точка доверия. Для максимальной безопасности можно смешивать вывод аппаратного RNG с энтропией от пользователя (броски кубика). Некоторые аппаратные кошельки (например, Trezor и Coldcard) поддерживают это нативно. Это гарантирует, что даже при компрометации аппаратного RNG итоговый ключ останется безопасным.

Влияет ли операционная система (Linux, macOS, Windows) на безопасность ключей?

Да. Качество и реализация CSPRNG в ОС влияют на безопасность ключей. Современные версии Linux, macOS и Windows предоставляют криптографически стойкие генераторы случайных чисел (/dev/urandom, arc4random, BCryptGenRandom). Однако баг Debian OpenSSL 2006-2008 годов показал, что уязвимости на уровне ОС могут катастрофически снизить энтропию. Обновляйте ОС и используйте хорошо аудированное ПО.

Связанные руководства