Fallo en la verificación de firma HMAC-SHA-256 en el inicio de sesión web de Telegram.
Estoy tratando de agregar el inicio de sesión de Telegram Web a mi proyecto Django+Vue. Estoy manejando el inicio de sesión en Vue y pasando directamente los datos de autorización obtenidos de TG a Django a través de DRF. Eso funciona bien. El problema ocurre en la verificación en la vista POST de REST. Cuando usaba la biblioteca js-sha256 en Vue, funcionaba perfectamente y obtenía el valor verdadero de la cadena hash proporcionada por la función sha256.hmac()
de la biblioteca js-sha256. Estoy luchando por obtener la misma hash en Python. Aquí se explica la verificación de datos de TG y el código que estoy usando en la vista POST:
class TelegramLoginSerializer(serializers.Serializer):
raw_data = serializers.JSONField(required=True)
def create(self, validated_data):
raw_data = validated_data['raw_data']
tg_data = "\n".join([f'{k}={raw_data[k]}' for k in sorted(raw_data)])
if raw_data['hash'] != self.verify_telegram_data(tg_data):
return PermissionDenied()
else:
...
@staticmethod
def verify_telegram_data(data):
secret_key = hashlib.sha256(settings.TG_BOT_TOKEN.encode('utf-8'))
message = data.encode('utf-8')
return hmac.new(secret_key.digest(), message, hashlib.sha256).hexdigest()
Aquí se explica la verificación de datos de TG y el código que estoy usando en la vista POST.
davy.ai
Solución para obtener el mismo hash en Python que el de la biblioteca js-sha256
El problema parece estar en la codificación de la clave secreta y el mensaje utilizados para HMAC. Para obtener el mismo hash en Python que el de la biblioteca js-sha256, debes hacer los siguientes cambios:
binascii.unhexlify()
antes de ser utilizada para HMAC. Esto se debe a queTG_BOT_TOKEN
está en formato hexadecimal.El mensaje debe ser codificado como bytes con
str.encode()
. Esto asegura que el mensaje de entrada para HMAC también esté en formato de bytes.Aquí tienes una implementación actualizada del método
verify_telegram_data()
:Con estos cambios, el hash generado en Python debería coincidir con el de la biblioteca js-sha256.