128 бит и больше

Стойкость пароля зависит от алгоритма, который его использует. Оценить скорость перебора на GPU можно по hashcat benchmark. Отличие скорости работы слабых алгоритмов от сильных в пределах 10^6. Это большая цифра, но только для плохих паролей!

Количество возможных паролей удваивается с увеличением длины на 1 бит: старое число паролей с единицей, плюс оно же с нулём. Для сохранения той же скорости взлома, потребуется купить второй GPU. Даже если собрать ферму из 100 граф-карт, это даст всего лишь стократный прирост скорости. Увеличение же длины пароля на байт, умножит число вариантов на 256. После определенного числа бит полный перебор лишается экономического смысла.

На сегодня таким значением считается 128 бит.

Как узнать число вариантов? Обычная комбинаторика. Число возможных элементов в степени длины пароля. В нашем случае речь идет о битах, что даёт 2 возможных значения: 0 и 1. И таких 128 штук, значит 2 ^ 128. Это примерно 10^38. Взлом абсолютно нерентабелен!

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

Но как узнать число бит, зная только число вариантов? Если пароль собран из 15 цифр, вариантов 10^15. Для перевода бит в варианты, мы возводили два в степень. Что бы узнать в какое число бит влезет число всех вариантов, нужно провести обратную процедуру! Логарифмирование по основанию два:

10^15 = 2^X
X = log2(10^15) = 49.8

Округлив, получаем что стойкость такого пароля - 50 бит. Цифровой пароль оказался довольно слабым.

Как же выбрать пароль?

Сгенерировать 128 случайных бит, т.е. ровно 16 байт. Большинство систем требуют пароль в ASCII, поэтому нам потребуется его перекодировать. Для отправки бинарных файлов по текстовым протоколам используют кодировку base_64. Мы можем выбрать любую или даже придумать свою. Стойкость пароля это не уменьшит.

# здесь и далее весь код будет на Python3
import secrets
key_int = secrets.randbits(128)
print(hex(key_int))
# 0x2af0f3958e106d1621658dbd7bd7653b

Как это запомнить?

Многократное повторение? Есть метод проще. До этого момента мы кодировали base_256 (т.е. обычный байт) в base_16. Но что, если мы кодируем пароль в base_2048? Только вместо привычных чисел возьмём слова. Этот метод используется в BIP_0039 и активно применяется для бэкапа крипто-кошельков.

Его предшественник Diceware использовал словарь на 7776 слов и был полностью аналоговым.

В чем их отличие? BIP_0039 использует меньший словарь и имеет проверку целостности. Словарь - ключевой элемент системы. Если слова трудно запомнить или легко спутать друг с другом, то пароль бесполезен.

Как работает BIP_0039?

  • 128-битный секрет хешируется sha256
  • первые 4 бита хеша добавляют к 128-битам секрета
  • полученную 132 битную строку делят на 12 частей по 11 бит
  • число в 11-бит дает диапазон от 0 до 2047
  • берут специальный словарь на 2048 слов
  • заменяют каждое число на соответствующее ему слово
  • получают 12 слов, содержащих секрет и хеш

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

Практика!

Установим библиотеку mnemonic

from mnemonic import Mnemonic

mnemo = Mnemonic('english')
key_int = 0x2af0f3958e106d1621658dbd7bd7653b
key_byte = key_int.to_bytes(16, 'little')
print(mnemo.to_mnemonic(key_byte))

# derive concert ten kitchen stone mountain fluid pear model question winter feel

Теперь получим из слов байты:

words = 'derive concert ten kitchen stone mountain fluid pear model question winter feel'
out_bytes = mnemo.to_entropy(words)
out_int = int.from_bytes(out_bytes, 'little')
print(hex(out_int))

# 0x2af0f3958e106d1621658dbd7bd7653b

В следующий раз мы обсудим более изощрённые методы кодирования паролей, допускающих открытое хранение.