Hashlib.pbkdf2 hmac: примеры (PYTHON)

Функция hashlib.pbkdf2_hmac для генерации ключей в Python
Раздел: Хэширование, Криптография
hashlib.pbkdf2_hmac(hash_name: str, password: bytes, salt: bytes, iterations: int, dklen: int=None): bytes

Описание функции hashlib.pbkdf2_hmac

Функция hashlib.pbkdf2_hmac реализует алгоритм PBKDF2 (Password-Based Key Derivation Function 2) с HMAC (Hash-based Message Authentication Code). Основное применение - безопасное преобразование пароля или другой слабой ключевой информации в криптографически стойкий ключ фиксированной длины. Это полезно для хеширования паролей перед сохранением в базу данных или для получения ключа шифрования из пароля.

Параметры функции:

  • hash_name (строка): Имя хеш-функции для HMAC (например, 'sha256', 'sha512'). Должно поддерживаться модулем hashlib.
  • password (байты): Исходный пароль или ключевой материал в виде последовательности байтов.
  • salt (байты): Криптографическая соль. Должна быть уникальной для каждого пароля. Использование соли предотвращает атаки по радужным таблицам.
  • iterations (целое число): Количество итераций алгоритма. Увеличение числа повышает стойкость к перебору, но также и время вычисления. Рекомендуется минимум 100000 для SHA-256.
  • dklen (целое число, необязательный): Желаемая длина производного ключа в байтах. Если не указана, используется размер вывода хеш-функции.

Возвращаемое значение: Объект байтов (bytes) длиной dklen, содержащий производный ключ.

Короткие примеры использования

Пример с минимальным набором параметров:

import hashlib
password = b'my_strong_password'
salt = b'random_salt'
key = hashlib.pbkdf2_hmac('sha256', password, salt, 100000)
print(key.hex())
4c5d... (шестнадцатеричная строка длиной 64 символа для SHA-256)

Пример с указанием длины ключа (dklen):

key = hashlib.pbkdf2_hmac('sha256', password, salt, 50000, 32)
print(len(key))
print(key.hex()[:16])
32
8a3f...

Пример с использованием другой хеш-функции:

key_sha512 = hashlib.pbkdf2_hmac('sha512', b'pass', b'salt', 200000, 64)
print(key_sha512.hex()[:24])
c5e4...

Похожие функции в Python

hashlib.scrypt - функция, использующая алгоритм scrypt, который требует больше памяти и устойчив к атакам с использованием специализированного оборудования (ASIC). Рекомендуется для новых систем, где важна устойчивость к аппаратным атакам.

hashlib.pbkdf2_hmac остается хорошим выбором для совместимости и когда требования к памяти критичны.

passlib.hash - библиотека, предоставляющая высокоуровневые интерфейсы для многих алгоритмов хеширования паролей, включая PBKDF2, с автоматическим управлением солью и итерациями.

Аналоги функции в других языках

PHP: hash_pbkdf2.

$key = hash_pbkdf2('sha256', 'password', 'salt', 100000, 32, true);
echo bin2hex($key);
4c5d...

JavaScript (Node.js): crypto.pbkdf2 или crypto.pbkdf2Sync.

const crypto = require('crypto');
const key = crypto.pbkdf2Sync('password', 'salt', 100000, 32, 'sha256');
console.log(key.toString('hex'));
4c5d...

Java: SecretKeyFactory с алгоритмом "PBKDF2WithHmacSHA256".

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 100000, 256);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] key = skf.generateSecret(spec).getEncoded();

C#: Rfc2898DeriveBytes.Pbkdf2 (в .NET Core 2.1+ и .NET 5+).

using System.Security.Cryptography;
byte[] key = Rfc2898DeriveBytes.Pbkdf2(password, salt, 100000, HashAlgorithmName.SHA256, 32);

Go: golang.org/x/crypto/pbkdf2.Key.

import "golang.org/x/crypto/pbkdf2"
key := pbkdf2.Key([]byte("password"), []byte("salt"), 100000, 32, sha256.New)

Kotlin: Аналогично Java через SecretKeyFactory.

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

Типичные ошибки

Передача строк вместо байтов для пароля или соли:

key = hashlib.pbkdf2_hmac('sha256', 'password', 'salt', 100000)  # TypeError
TypeError: Unicode-objects must be encoded before hashing

Использование слишком малого числа итераций:

key = hashlib.pbkdf2_hmac('sha256', b'pass', b'salt', 1)  # Небезопасно
print(key.hex())
a6c8... (ключ, легко подверженый перебору)

Использование предсказуемой или отсутствующей соли:

salt = b''  # Пустая соль
key1 = hashlib.pbkdf2_hmac('sha256', b'password', salt, 100000)
key2 = hashlib.pbkdf2_hmac('sha256', b'password', salt, 100000)
print(key1 == key2)
True  # Хеши одинаковы, что небезопасно

Указание длины ключа (dklen) больше, чем размер вывода хеш-функции, без явного указания хеш-функции, поддерживающей расширение:

key = hashlib.pbkdf2_hmac('sha256', b'pass', b'salt', 100000, 100)  # Работает, но внутренне используется алгоритм расширения.

Изменения в последних версиях

Функция hashlib.pbkdf2_hmac была добавлена в Python 3.4. В Python 3.11 были добавлены новые хеш-функции из OpenSSL, такие как 'sha3_256', 'sha3_512', которые также можно использовать в качестве параметра hash_name.

Расширенные примеры использования

Генерация соли с помощью os.urandom:

Пример python
import os, hashlib
salt = os.urandom(16)  # 16 байт соли
password = b'user_password'
key = hashlib.pbkdf2_hmac('sha512', password, salt, 150000, 64)

Сравнение хеша пароля при аутентификации:

Пример python
import hashlib, os
# Сохранение пароля (регистрация)
def store_password(password):
    salt = os.urandom(16)
    iterations = 210000
    key = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, iterations)
    return salt, iterations, key
# Проверка пароля (аутентификация)
def verify_password(input_password, stored_salt, stored_iterations, stored_key):
    new_key = hashlib.pbkdf2_hmac('sha256', input_password.encode(), stored_salt, stored_iterations)
    return new_key == stored_key
# Пример
salt, iters, key = store_password('secret')
print(verify_password('secret', salt, iters, key))
print(verify_password('wrong', salt, iters, key))
True
False

Использование функции для получения нескольких ключей из одного пароля (например, для шифрования и аутентификации):

Пример python
import hashlib
master_key = hashlib.pbkdf2_hmac('sha512', b'master_pass', b'app_specific_salt', 100000, 64)
enc_key = master_key[:32]
auth_key = master_key[32:]
print('Enc key:', enc_key.hex())
print('Auth key:', auth_key.hex())

Интеграция с базой данных (хранение соли, итераций и хеша):

Пример python
# Предположим, что salt, iterations и key_hex хранятся в БД
salt_hex = 'a1b2c3d4e5f6'
iterations = 120000
key_hex = 'abcdef123456'
# Проверка пароля
input_pass = b'user_input'
computed_key = hashlib.pbkdf2_hmac('sha256', input_pass, bytes.fromhex(salt_hex), iterations)
if computed_key.hex() == key_hex:
    print('Password correct')
else:
    print('Password incorrect')

Использование с переменным числом итераций, основанным на возможностях системы (адаптивное хеширование):

Пример python
import time, hashlib
# Функция для подбора итераций, чтобы хеширование занимало примерно 0.5 секунды
def calibrate_iterations(password, salt, hash_name='sha256', target_time=0.5):
    start = time.time()
    test_iterations = 10000
    hashlib.pbkdf2_hmac(hash_name, password, salt, test_iterations)
    elapsed = time.time() - start
    # Экстраполяция
    iterations = int(test_iterations * target_time / elapsed)
    return max(iterations, 10000)  # Минимум 10000
password = b'test_password'
salt = os.urandom(16)
iterations = calibrate_iterations(password, salt)
print('Calibrated iterations:', iterations)
key = hashlib.pbkdf2_hmac('sha256', password, salt, iterations)

питон hashlib.pbkdf2_hmac function comments

En
Hashlib.pbkdf2 hmac Password based key derivation function 2