Хеширование паролей в Python используя pbkdf2 из haslib

Пароли никогда не хранятся в чистом виде. В ином случае их легко будет взломать, и надежность системы будет нарушена. Особенно это критично в интернет-банкинге и других подобных системах, где вопросы безопасности становятся на первое место. Один из действенных способов защитить пароли пользователей от взлома – хеширование. Сегодня рассмотрим такие важные аспекты этого вопроса, как зачем оно необходимо, какой алгоритм шифрования лучше использовать, как осуществляется шифрование в Python, как правильно хранить пароли, как проверить, тот ли пароль был введен и ряд других вопросов.

Зачем необходимо хеширование паролей?

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

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

Настоятельно рекомендуется вместе с хешированным паролем хранить соль. Что это такое? Далее мы поговорим.

Почему не рекомендуется использование SHA-256 либо что-то похожее?

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

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

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

Как использовать pbkdf2_hmac для хеширования паролей?

Этот метод использует гораздо более медленное хеширование. Это означает, что для определения подмножества хешей в течение определенного временного промежутка потребуется значительно больше времени. Следовательно, поиск может стать настолько долгим, что понадобится много-много лет, чтобы найти совпадение. А иногда – и десятков лет. Поэтому ни один злоумышленник не сможет выдержать так долго. Ему это попросту невыгодно. 

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

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

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

По факту, PBKDF2_HMAC – это вариант реализации функции получения ключа PBKDF2, где HMAC выступает псевдослучайной функцией. Где можно найти pbkdf2_hmac? В библиотеке hashlib (которая входит в стандартный комплект поставки Python), которая расположена в Python 3.4 и выше. pbkdf2_hmac может принимать пять аргументов.

  • hash_name: алгоритм хеш-дайджеста для HMAC.
  • password: пароль, который используется в качестве ключа.
  • salt – это соль, которая была сгенерирована случайно.
  • iterations: вычислительные итерации. От этого аргумента зависит длина производимых вычислений.
  • dklen: длина ключа вывода. Этот аргумент является опциональным.

Как выполнить генерацию соли в Python?

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

Нет необходимости скрывать, шифровать либо хешировать соль. Она просто складывается с паролем, чтобы вводом мог покрываться больший диапазон. Поскольку комбинация осуществляется pbkdf2_hmac, это самостоятельно делать не придется.

Как генерировать соль? Для этого используется функция os.random, задача которой – возвращать случайные байты, которые применяются для целей шифрования. Этой функцией генераторы псевдослучайных чисел не используются. Следовательно, нет никакой закономерности, позволяющей предугадать значение, которое возвращается. Идеально.

import os

 

salt = os.urandom(32)

Зачем мы использовали параметр 32? Он являет собой возвращаемый в байтах размер. Можно выбрать какой-угодно. Тем не менее, рекомендуется минимальный устанавливать в 16 байт. 

Не нужно использовать одинаковый хеш для всех паролей пользователя либо объекта. Каждый пароль должен иметь разный хеш. 

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

Как осуществляется хеширование в Python?

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

import hashlib

import os




salt = os.urandom(32) # Запомните

password = 'password123'




key = hashlib.pbkdf2_hmac(

    'sha256', # Используемый алгоритм хеширования

    password.encode('utf-8'), # Конвертируется пароль в байты

    salt, # Предоставляется соль

    100000 # Рекомендуется использовать хотя бы 100000 итераций SHA-256

Поскольку длина ключа была предоставлена, то и используется размер дайджеста хеш алгоритма. В этом примере нами используется SHA-256, поэтому размер составляет 64 байта. Если требуется ключ подлиннее для его использования в AES, необходимо осуществить передачу требуемого размера ключа dklen после итерации в hashlib.pbkdf2_hmac. Давайте такой пример рассмотрим. 

 import hashlib

import os

 

salt = os.urandom(32) # Запомните это

password = 'password123'

 

key = hashlib.pbkdf2_hmac(

    'sha256', # Используемый алгоритм хеширования

    password.encode('utf-8'), # Конвертирование пароля в байты

    salt, # Предоставление соли

    100000, # Рекомендуется использоваться по крайней мере 100000 итераций SHA-256 

    dklen=128 # Получает ключ в 128 байтов

Что здесь является ключом? Конечно же, ваш «хеш».

Как осуществлять хранение хеша и соли?

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

Если у вас есть только одно место для хранения, можно добавить соль и пароль вместе, а потом их сохранить. Можно также разделить их во время чтения, когда будет известна длина соли и ключа. Давайте рассмотрим следующий пример. 

import os

import hashlib

 

# Пример генерации

salt = os.urandom(32)

key = hashlib.pbkdf2_hmac('sha256', 'mypassword'.encode('utf-8'), salt, 100000)

 

# Хранение как

storage = salt + key 

 

# Получение значений обратно

salt_from_storage = storage[:32] # 32 является длиной соли

key_from_storage = storage[32:]

Если требуется воспользоваться двумя местами (как правило, так оно и есть), то это вполне можно сделать. Так можно сделать процесс значительно проще. 

Как проверить, насколько правильно пароль был введен в Python?

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

import hashlib




salt = b'' # Получение соли, сохраненной для *этого* пользователя

key = b'' # Получение рассчитанного ключа пользователя




password_to_check = 'password246' # Пароль, предоставленный пользователем, проверяется




# Используется та же настройка для генерации ключа, только на этот раз вставляется для проверки настоящий пароль

new_key = hashlib.pbkdf2_hmac(

    'sha256',

    password_to_check.encode('utf-8'), # Конвертирование пароля в байты

    salt, 

    100000

)




if new_key == key:

    print('Пароль правильный')

else:

    print('Пароль неправильный')

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

Выводы

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

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

ОфисГуру
Adblock
detector