Prueba de contraseña de conocimiento cero: ¿por qué el hash de la contraseña en el lado del cliente no es un ZKP?

5

Escenario:

  1. El cliente envía su nombre de usuario u al servidor.
  2. El servidor extrae una tupla en forma de (username, salt, hashed_password) de su base de datos, donde username coincide con el nombre de usuario del cliente u . hashed_password es el resultado de hash(salt + password) (donde hash es una función hash criptográfica moderna) que se ha calculado cuando la tupla se ha escrito en la base de datos (por ejemplo, durante el registro del usuario).
  3. El servidor envía salt al cliente.
  4. El cliente calcula h := hash(salt + password) y envía h al servidor.
  5. El servidor compara h con hashed_password y otorga acceso si los hashes coinciden.

Si asumimos que el servidor no ha calculado el hash durante el registro del usuario (en su lugar, el cliente calculó el hash y envió la tupla (username, salt, hashed_password) al servidor para almacenarlo en la base de datos), ¿por qué este escenario? ¿No se considera una prueba de contraseña de conocimiento cero? ¿O es de hecho un ZKP?

Según tengo entendido, el servidor nunca ha visto la contraseña real, pero se puede verificar que el cliente posee la contraseña original que se utilizó para crear el hash inicial.

    
pregunta watain 01.02.2017 - 09:42
fuente

2 respuestas

6

El principal problema de su protocolo es que la segunda respuesta del cliente es vulnerable a ataques de reproducción . Durante el procedimiento de inicio de sesión, un atacante aprende u y h , que pueden ser reutilizados posteriormente en un inicio de sesión malicioso por parte del atacante y darán como resultado un inicio de sesión exitoso.

Recomendaría usar la autenticación de desafío-respuesta con HMAC aquí, lo que significa que el cliente recibe un desafío del servidor y devuelve el desafío firmado por HMAC (= respuesta).

  • Suponiendo que el cliente conoce la contraseña, el cliente puede firmar mensajes con ella (simétricamente utilizando HMAC)
  • Desde el punto de vista del servidor, el cliente se autentica firmando un mensaje dado desde el servidor

Protocolo ingenuo para entender la idea:

1. [C] –––(username)–––> [S]

Atacante: aprende el nombre de usuario (es posible que desee cambiar eso eventualmente)

2. Server calculates M = (nonce) and stores M

nonce : un grupo de bytes aleatorios que DEBE ser único, evita los ataques de repetición. Para hacerlo único, agregue una marca de tiempo o un contador de inicio de sesión, por ejemplo.

2. [C] <––– M ––– [S]

Atacante pasivo: el atacante aprende M, que es diferente para cada intento de inicio de sesión, incluso para el mismo usuario. Sin saber la contraseña, el atacante no puede firmarla.

Atacante activo: manipular M no ayuda en nada: el cliente firmará la M incorrecta que no será aceptada por el servidor más adelante.

3. [C] ––– HMAC(M, pw) –––> [S]

Atacante pasivo: aprende la firma HMAC (M, pw). La firma HMAC no se puede reutilizar porque M siempre es diferente (por eso debe ser único).

Atacante activo: la manipulación de M o la firma HMAC hace que la firma no sea válida o no coincida con la M almacenada en el servidor en el paso 4.

4. Server examines if the received M equals the stored M and verifies the HMAC signature

Esto es posible porque el servidor también conoce la contraseña.

Este protocolo satisface mi interpretación de la muy floja definición de wikipedia de ZKPP , ya que es interactivo y el cliente lo sabe. de datos derivados de contraseñas y no la contraseña en sí.

En general, el nivel de seguridad de las pruebas de conocimiento cero se basa en procedimientos iterativos que mi intento ingenuo no cubre. Recomiendo echar un vistazo a CHAP y / o SRP.

    
respondido por el atzeton 01.02.2017 - 15:11
fuente
4

Su ejemplo elimina la noción de hash por completo: H (S + P) se convierte en una contraseña de texto simple que se puede reutilizar directamente sin ningún trabajo adicional.

    
respondido por el Stephane 01.02.2017 - 09:51
fuente

Lea otras preguntas en las etiquetas