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) # TypeErrorTypeError: 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:
import os, hashlib
salt = os.urandom(16) # 16 байт соли
password = b'user_password'
key = hashlib.pbkdf2_hmac('sha512', password, salt, 150000, 64)Сравнение хеша пароля при аутентификации:
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
Использование функции для получения нескольких ключей из одного пароля (например, для шифрования и аутентификации):
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())Интеграция с базой данных (хранение соли, итераций и хеша):
# Предположим, что 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')Использование с переменным числом итераций, основанным на возможностях системы (адаптивное хеширование):
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)