КриптовалютыСмартфоны

Генерация безопасной BIP-39 сид-фразы с помощью кубиков (d6): пошаговое руководство, безопасность и формулы 🎲🔐

Как надежно сгенерировать BIP-39 сид-фразу с помощью кубиков (d6) — инструкция, формулы и скрипты

1 0
63 / 100 SEO оценка

Вступление — зачем генерировать сид-фразу с помощью кубиков

Генерация сид-фразы офлайн — один из самых надёжных способов получить истинно случайную фразу, не доверяя программному обеспечению или интернет-источникам. Метод с кубиками (d6) позволяет получить энтропию от физических явлений — человеческих бросков — и при корректной процедуре получить полноценную 12-словную BIP-39 фразу с полной 128-битной энтропией.

В этой статье — полная инструкция: сколько бросков нужно, как перевести последовательность бросков в ровные 128 бит без биаса (rejection sampling), как получить контрольную сумму согласно BIP-39 и преобразовать всё это в 12 слов. В конце — скрипт для красиво отформатированного показа формул в браузере (MathJax) и офлайн-скрипт (Python) для запуска на air-gapped машине.



Краткий план (если спешишь)

  • Нужно 128 бит энтропии → 12 слов BIP-39.
  • d6 даёт ≈ log2(6) ≈ 2.585 bits на бросок → нужно 50 бросков (50 × log2(6) ≈ 128.25).
  • Интерпретируем 50 бросков как 50-значное base-6 число V.
  • Делаем rejection sampling: принимаем V только если V < T (см. формулы), иначе повторяем 50 бросков.
  • Берём E = V mod 2^128 → это ровные 128 бит; добавляем 4-битную контрольную сумму SHA-256 → 132 бита → 12 × 11-бит индексов → слова BIP-39.

Теория и формулы (коротко и математически)

Основные обозначения и формулы, которые мы будем использовать — в удобном виде (формулы красиво отрисованы с помощью MathJax внизу страницы):

  • Количество бросков: \(n = 50\).
  • Каждый бросок: \(r_i \in \{1,2,3,4,5,6\}\), \(i=1..50\).
  • Base-6 цифра: \(d_i = r_i — 1 \in \{0,\dots,5\}\).
  • Целое число V (base-6 → integer):
    \[
    V = \sum_{i=1}^{50} d_i \cdot 6^{50-i}
    \]
  • Rejection sampling:
    \[
    K = \left\lfloor \dfrac{6^{50}}{2^{128}} \right\rfloor,\quad T = K \cdot 2^{128}.
    \] Принимаем V только если \(V < T\). Иначе — бросаем заново.
  • Энтропия (128 бит):
    \[
    E = V \bmod 2^{128}.
    \]
  • Контрольная сумма (4 бита):
    \[
    CS = \mathrm{first\_bits}_4(\mathrm{SHA256}(E)).
    \]
  • Полная последовательность: \(132\) бита \(= \mathrm{ENT}\,||\,\mathrm{CS}\). Разбиваем на 12 групп по 11 бит и получаем индексы \(i_j\in[0,2047]\) для слов BIP-39.

Подробный пошаговый алгоритм

Шаг 0 — подготовка

  • Возьми один кубик d6 (или несколько — не имеет принципиального значения), чистый лист / карандаш и устройство для оффлайн-вычислений (air-gapped ноутбук) с Python, если будешь проверять/обрабатывать данные.
  • Отключи интернет на устройстве, если собираешься обрабатывать результаты на компьютере; лучше запускать проверочный скрипт на полностью оффлайн машине.

Шаг 1 — делаем броски

  1. Сделай ровно 50 бросков кубиком.
  2. Записывай каждый результат в порядке: \(r_1, r_2, \dots, r_{50}\). Рекомендуется считать \(r_1\) как самый значимый разряд (MSD), \(r_{50}\) — как младший (LSD).

Шаг 2 — перевод в base-6 целое V

Для каждого броска вычисляем цифру \(d_i = r_i — 1\) (диапазон 0..5). Затем:

\(V = \displaystyle\sum_{i=1}^{50} d_i \cdot 6^{50-i}\)

Шаг 3 — rejection sampling (убираем bias)

Вычисляем:

\(K = \left\lfloor \dfrac{6^{50}}{2^{128}} \right\rfloor,\quad T = K \cdot 2^{128}\).

Принимаем V только если \(V < T\). Если \(V \ge T\) — весь набор из 50 бросков отвергается и процесс начинается заново (еще 50 бросков).

Практическое замечание: вероятность принять V ≈ 84.2% → редкие перебросы.

Шаг 4 — получение 128 бит энтропии

\(E = V \bmod 2^{128}.\)

`E` — 128-битное целое. Запиши его в 16 байт (big-endian) — это твоя ENT-последовательность.

Шаг 5 — контрольная сумма и 12 слов

  1. Вычисли \(h = \mathrm{SHA256}(E)\).
  2. Возьми первые 4 бита \(CS = h[0]_{\text{bits}}[:4]\).
  3. Составь полный битстрим: `ENT (128 бит)` || `CS (4 бита)` → 132 бита.
  4. Разбей на 12 групп по 11 бит → индексы 0..2047 → смотри BIP-39 wordlist → получишь 12 слов.

Безопасность и практические советы

  • Полностью офлайн: броски делай в месте без камер; при обработке результатов используй машину без подключения к интернету.
  • Запись: запиши фразу на бумаге и (ещё лучше) на металле. Сделай 2–3 копии и храни в разнесённых безопасных местах (банк-ячейка, дом, доверенное лицо).
  • Не фотографируй и не сохраняй цифровые копии.
  • Проверка: проверь фразу, восстановив её в офлайн-кошельке и сверив публичные адреса (тестовая транзакция с малой суммой — опция).
  • Добавь BIP-39 passphrase</strong (опционально): дополнительный секрет повышает безопасность, но его нужно хранить также надежно.

Оффлайн-скрипт (Python) — принимает 50 бросков и выдаёт 12 слов

Запусти на air-gapped машине. Требуется файл bip39.txt (2048 слов, по одному на строку). Скрипт проверяет rejection sampling и выводит фразу.

# bip39_dice.py — запускать офлайн (Python 3.8+)
import hashlib
import sys

# Вставьте 50 чисел 1..6 (по порядку бросков), либо вводите через stdin/файл
# Пример: rolls = [1,4,6,2,...] длина 50
rolls = []
print("Введите 50 бросков (через пробел или по одному, enter для следующего):")
while len(rolls) < 50:
    try:
        parts = input().strip().split()
        for p in parts:
            if p:
                v = int(p)
                if 1 <= v <= 6: rolls.append(v) else: print("Число должно быть 1..6") except EOFError: break if len(rolls) != 50: print("Нужно ровно 50 бросков. Ввод окончен.") sys.exit(1) # base-6 -> V
V = 0
for r in rolls:
    V = V * 6 + (r - 1)

# rejection sampling
K = (6**50) // (2**128)
T = K * (2**128)
if V >= T:
    print("Набор отвергнут (V >= T). Повторите 50 бросков.")
    sys.exit(2)

E = V % (2**128)
entropy_bytes = E.to_bytes(16, byteorder='big')

# checksum (4 bits)
h = hashlib.sha256(entropy_bytes).digest()
cs_bits = bin(h[0])[2:].zfill(8)[:4]

ent_bits = bin(int.from_bytes(entropy_bytes, 'big'))[2:].zfill(128)
full_bits = ent_bits + cs_bits

# split into 12 indices
indexes = [int(full_bits[i*11:(i+1)*11], 2) for i in range(12)]

# load bip39 wordlist (bip39.txt — 2048 слов)
with open('bip39.txt', 'r', encoding='utf-8') as f:
    words = [w.strip() for w in f.readlines()]
    if len(words) != 2048:
        print("Ошибка: bip39.txt должен содержать 2048 слов.")
        sys.exit(3)

phrase = ' '.join(words[idx] for idx in indexes)
print("\\nBIP-39 phrase:")
print(phrase)

Скрипт для красивого отображения формул (MathJax)

Ниже — фрагмент HTML/JS, который можно вставить в страницу (без <head> и <body> по твоему запросу). Он подключает MathJax и аккуратно отображает формулы, включая те, что использованы в статье. Если хочешь использовать офлайн, замени подключение MathJax на локальную копию (или пропусти подключение и используй серверную рендеринговую утилиту).

<!-- Вставь этот блок в HTML (без head/body по соглашению) -->
<div id="math-container">
  <p>Основные формулы: </p>
  <div>V = \sum_{i=1}^{50} d_i \cdot 6^{50-i}</div>
  <div>K = \left\lfloor \dfrac{6^{50}}{2^{128}} \right\rfloor, \quad T = K \cdot 2^{128}</div>
  <div>E = V \bmod 2^{128}</div>
</div>

<!-- MathJax CDN (можно заменить на локальную копию) -->
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<script>
  window.MathJax = {
    tex: { inlineMath: [['$','$'], ['\\(','\\)']] },
    svg: { fontCache: 'global' }
  };
  // Необязательный: плавная анимация при рендере
  document.addEventListener('DOMContentLoaded', function () {
    if (window.MathJax && MathJax.typesetPromise) {
      MathJax.typesetPromise();
    }
  });
</script>

Этот блок автоматически отрисует LaTeX-формулы и будет корректно работать в современных браузерах. Если хочешь, заменю подключение на KaTeX (более лёгкий, но требует CSS) или подготовлю offline-bundle MathJax для запуска без интернета.


Примеры и контрольные проверки

  • После генерации фразы импортируй её в офлайн-кошелёк (на той же air-gapped машине) и проверь первый адрес. Сравни с адресом, который выдаст любой стандартный BIP-39 инструмент с тем же derivation path.
  • Рекомендация: сначала протестируй процесс с небольшими суммами (0.0001 …) чтобы убедиться, что всё работает как нужно.

Частые вопросы (FAQ)

Q: Сколько раз процедура может отвергнуть набор бросков?
A: Вероятность отклонения ≈ 15.8% для 50 бросков. В среднем нужен ≈1.19 попытки — то есть редко требуется повтор.

Q: Можно ли использовать другие кубики (d20, монеты)?
A: Да. Формула и число бросков меняются в зависимости от логарифма базы: для d20 (base-20) потребуется меньше бросков, для монеты (d2) — больше. Всегда используйте rejection sampling при несоответствии base^n ≠ 2^128.

Q: Можно ли сократить количество бросков до 48 или 49?
A: Теоретически — да, но тогда вероятность отклонения и bias меняются. Практически 50 — удобное и безопасное решение для d6.


Заключение

Генерация BIP-39 сид-фразы с помощью кубиков — надёжный офлайн-метод для тех, кто хочет исключить зависимость от программных источников энтропии. Главное — соблюдать алгоритм (50 бросков, base-6 → V, rejection sampling, мод 2^128, добавление контрольной суммы и перевод в 12 слов). Храни фразу офлайн и добавь passphrase при необходимости.

Happy
Happy
100 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %

Похожие статьи

Кнопка «Наверх»