Secrets.compare digest: примеры (PYTHON)
secrets.compare_digest(a: str or bytes, b: str or bytes): boolОписание функции secrets.compare_digest
Функция secrets.compare_digest(a, b) является частью стандартного модуля secrets, появившегося в Python 3.6. Её основное назначение - безопасное сравнение двух строк или байтовых последовательностей, устойчивое к атакам по времени (timing attacks).
Такой тип атак основан на анализе времени выполнения операции: обычное сравнение строк (оператор ==) завершается при первом несовпадении символов, что позволяет злоумышленнику постепенно подбирать секретные значения, измеряя время ответа. compare_digest реализует алгоритм постоянного времени, где время выполнения не зависит от совпадающих префиксов.
Функция обычно применяется для проверки криптографических хешей, токенов аутентификации, ключей API и других чувствительных данных.
Аргументы функции
- a: первый объект для сравнения. Может быть типом
bytesилиstr(как Unicode, так и ASCII). - b: второй объект для сравнения. Также может быть
bytesилиstr.
Возвращаемое значение
Функция возвращает True, если объекты a и b равны. В противном случае возвращается False. Важно, что сравнение безопасно по времени только когда оба аргумента имеют одинаковый тип (оба bytes или оба str). При сравнении строк разной длины также обеспечивается постоянное время выполнения.
Короткие примеры использования
Базовое сравнение строк:
import secrets
result = secrets.compare_digest('secret_token', 'secret_token')
print(result)True
Сравнение байтовых последовательностей:
import secrets
bytes_a = b'\xde\xad\xbe\xef'
bytes_b = b'\xde\xad\xbe\xef'
result = secrets.compare_digest(bytes_a, bytes_b)
print(result)True
Сравнение различных строк:
import secrets
result = secrets.compare_digest('password', 'password1')
print(result)False
Сравнение строк разной длины:
import secrets
result = secrets.compare_digest('short', 'very_long_string')
print(result)False
Похожие функции в Python
hmac.compare_digest: Функция из модуля hmac, обладающая идентичной реализацией и поведением. Она появилась в Python 3.3. Для нового кода рекомендуется использовать secrets.compare_digest, так как модуль secrets явно предназначен для криптографически безопасных операций.
Оператор ==: Обычное сравнение строк или байтов. Небезопасно по времени, поэтому не должно использоваться для сравнения секретных данных, таких как токены или хеши паролей.
Аналоги функции в других языках
PHP
Функция hash_equals предназначена для безопасного сравнения строк.
$result = hash_equals('secret', 'secret');
var_dump($result);bool(true)
JavaScript (Node.js)
Модуль crypto предоставляет метод timingSafeEqual для сравнения буферов.
const crypto = require('crypto');
const buf1 = Buffer.from('secret');
const buf2 = Buffer.from('secret');
const result = crypto.timingSafeEqual(buf1, buf2);
console.log(result);true
Java
Класс MessageDigest имеет метод isEqual, который реализует сравнение с постоянным временем.
import java.security.MessageDigest;
boolean result = MessageDigest.isEqual("secret".getBytes(), "secret".getBytes());
System.out.println(result);true
C#
В .NET Core 3.0 и выше доступен метод CryptographicOperations.FixedTimeEquals.
using System.Security.Cryptography;
bool result = CryptographicOperations.FixedTimeEquals(
Encoding.UTF8.GetBytes("secret"),
Encoding.UTF8.GetBytes("secret")
);
Console.WriteLine(result);True
Golang
Пакет crypto/subtle содержит функцию ConstantTimeCompare.
package main
import (
"crypto/subtle"
"fmt"
)
func main() {
result := subtle.ConstantTimeCompare([]byte("secret"), []byte("secret"))
fmt.Println(result == 1)
}true
Главное отличие Python-функции - универсальность работы как со строками, так и с байтами, в то время как во многих других языках работа ведётся только с байтовыми массивами.
Типичные ошибки при использовании
Передача аргументов разных типов вызывает исключение TypeError.
import secrets
try:
result = secrets.compare_digest(b'bytes', 'str')
except TypeError as e:
print(f'Ошибка: {e}')Ошибка: a and b must be of the same type
Использование нестроковых и небайтовых объектов также приводит к ошибке.
import secrets
try:
result = secrets.compare_digest(12345, 12345)
except TypeError as e:
print(f'Ошибка: {e}')Ошибка: a and b must be of the same type
Недостаточная обработка данных от пользователя перед сравнением. Функция не выполняет декодирование или преобразование, данные должны быть уже подготовлены.
Изменения в последних версиях
Начиная с Python 3.10, в реализации функции не было внесено существенных изменений, влияющих на её сигнатуру или поведение. Основные оптимизации проводились на уровне исходного кода CPython для повышения производительности. Функция остаётся стабильной и рекомендованной для использования.
Расширенные примеры использования
Сравнение HMAC-подписей для веб-запросов:
import secrets
import hmac
def verify_signature(received_signature, payload, secret_key):
expected_signature = hmac.new(secret_key, payload, 'sha256').hexdigest()
return secrets.compare_digest(received_signature, expected_signature)
secret = b'my_secret_key'
payload = b'important_data'
valid_sig = hmac.new(secret, payload, 'sha256').hexdigest()
invalid_sig = 'invalid_signature'
print(verify_signature(valid_sig, payload, secret))
print(verify_signature(invalid_sig, payload, secret))True False
Проверка API-токена с предварительным кодированием в байты:
import secrets
import base64
def check_api_token(header_token, stored_token):
# Декодируем токен из base64, если необходимо
decoded_header = base64.b64decode(header_token) if len(header_token) % 4 == 0 else header_token.encode()
decoded_stored = stored_token.encode() if isinstance(stored_token, str) else stored_token
return secrets.compare_digest(decoded_header, decoded_stored)
stored = 'actual_token'
header_good = 'actual_token'
header_bad = 'wrong_token'
print(check_api_token(header_good, stored))
print(check_api_token(header_bad, stored))True False
Использование в контексте сравнения хешей паролей (хотя для хеширования паролей лучше применять специализированные функции, такие как bcrypt или argon2):
import secrets
import hashlib
def verify_password_hash(input_password, stored_hash, salt):
input_hash = hashlib.pbkdf2_hmac('sha256', input_password.encode(), salt, 100000)
return secrets.compare_digest(input_hash, stored_hash)
salt = secrets.token_bytes(16)
password = 'user_password'
stored = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)
print(verify_password_hash('user_password', stored, salt))
print(verify_password_hash('wrong_password', stored, salt))True False
Сравнение данных большой длины. Функция работает с постоянным временем даже на больших объёмах данных:
import secrets
import time
large_data1 = secrets.token_bytes(1000000)
large_data2 = secrets.token_bytes(1000000)
large_data3 = large_data1 # Та же ссылка
start = time.perf_counter()
result1 = secrets.compare_digest(large_data1, large_data2)
time1 = time.perf_counter() - start
start = time.perf_counter()
result2 = secrets.compare_digest(large_data1, large_data3)
time2 = time.perf_counter() - start
print(f'Разные данные: {result1}, время: {time1:.6f} сек')
print(f'Одинаковые данные: {result2}, время: {time2:.6f} сек')
print(f'Время примерно одинаковое: {abs(time1 - time2) < 0.001}')Разные данные: False, время: 0.002123 сек Одинаковые данные: True, время: 0.002056 сек Время примерно одинаковое: True
питон secrets.compare_digest function comments
- питон secrets.compare digest - аргументы и возвращаемое значение
- Функция python secrets.compare_digest - описание
- secrets.compare digest - примеры
- secrets.compare digest - похожие методы на python
- secrets.compare_digest на php, c#, sql, java
- secrets.compare digest изменения python
- Примеры secrets.compare_digest на питон