El código de Google Authenticator no coincide con el código generado por el servidor

Antecedentes

Actualmente estoy trabajando en un sistema de autenticación de dos factores donde el usuario puede autenticarse usando su teléfono inteligente. Antes de que el usuario pueda hacer uso de su dispositivo, primero deben verificarlo. Para esto, necesitan escanear un código QR que les doy e ingresar el código que se muestra a continuación.

Problema

El escaneo del código QR funciona bien y la aplicación Google Authenticator lo lee correctamente. Sin embargo, los códigos generados no coinciden con los que estoy generando en el servidor.

Que he probado

He intentado un par de cosas con la esperanza de encontrar mi problema.

He intentado insertar directamente un secreto predeterminado:'thiswasmysecretkeyused' y unbase64.b32encode() versión codificada del secreto:'ORUGS43XMFZW26LTMVRXEZLUNNSXS5LTMVSA====' en la aplicación Google Authenticator, pero ambos códigos generados son diferentes del servidor.

Leí que el final==== de la clave puede hacer que no funcione, así que intenté agregar uno sin esos también. Todavía no hay buenos resultados (generan los mismos códigos)

He intentado usar un algoritmo diferente para generar códigos TOTP, porque en el caso poco probable de que el algoritmo que estoy usando (django-otp) Es incorrecto. El algoritmo diferente que utilicé fue tomado deesta responder. Ambos algoritmos generaron los mismos códigos cuando se usa la misma clave.

Verifiqué la hora en mi sistema. Vi que el sistema operativo mostraba15:03 tal como era mi teléfono inteligente. Después de volcar el tiempo en python con ambostime.time() ydatetime.datetime.now() Vi que la hora de regreso estaba una hora por detrás de la hora del sistema operativo; demostración14:03. Traté de agregar3600 segundos en la marca de tiempo utilizada para la generación de código, pero fue en vano.

He intentado varias otras cosas, pero no puedo recordar cuáles eran todas.

He buscado el código que acepta claves en Google Authenticator y he verificado que espera una cadena base32. Entonces, mi codificación de la clave es correcta, hasta donde yo sé. Del código (EnterKeyActivity.java, línea 78):

Verifique que el campo de entrada contiene una cadena base32 válida

Código

Generando la clave secreta;

def generate_shared_key(self):
    # create hash etc.
    return base64.b32encode(hasher.hexdigest())

Generando el código QR;

key = authenticator.generate_shared_key()
qrcode = pyqrcode.create('otpauth://totp/someurl.nl?secret=' + key)

Generando el código TOTP;

def generate_code(self, drift_steps=0, creation_interval=30, digits=6, t0=0):
    code = str(totp(self.generate_shared_key(), creation_interval, timestamp, digits, drift_steps))
    return code.zfill(digits)

Si necesita más código, como django-otp, actual código generador de totp, hágamelo saber.

Errores

Sin errores.

Corazonadas

Mi presentimiento es que debo estar yendo mal en algún lugar con la generación de claves o al pasar la clave a Google Authenticator. Dado que incluso poner manualmente la clave en Google Authenticator no puede generar los códigos correctos. ¿Google Authenticator hace algo más con la clave una vez que se ha guardado, como agregar un usuario?

También noté en el otro algoritmo que usé que el secreto allí se decodifica primero;

key = base64.b32decode(secret, True) 

¿Mi clave original (un hash SHA512) está mal? ¿Debería o no debería codificarlo conbase64.b32encode()? Si trato de escanear el código QR generado sin codificar el hash, Google Authenticator dice que no lo reconoce como una clave (válida).

Respuestas a la pregunta(1)

Su respuesta a la pregunta