Para crear un sistema seguro de desafío-respuesta en el que el servidor olvide el desafío antes de que se devuelva la respuesta, debe asegurarse de que un atacante no pueda enviarle una respuesta a un desafío que no envió. , o un desafío que fue dirigido hacia otra persona, o un desafío que es antiguo o que ya se ha utilizado.
En primer lugar, puede asegurarse de que todos sus desafíos son genuinos "firmándolos" de alguna manera. No tiene que usar los protocolos de firma tradicionales para hacer esto, ya que no es una firma de propósito general. En su lugar, simplemente tome su desafío existente, añádale una cadena "secreta" y tome un hash criptográfico del resultado (por ejemplo, SHA-256). Luego incluye el hash como parte del desafío. Cuando obtiene un desafío del cliente, puede verificar su autenticidad repitiendo el proceso y comparando el hash transmitido con el que usted calcula. Si el espacio es una prima, solo necesita incluir un pequeño subconjunto de todo el hash.
Para asegurarse de que los desafíos no se puedan usar para autenticar contra la cuenta de otra persona, puede hacer que la identificación de la cuenta sea parte del desafío en sí o de la autenticación descrita anteriormente. Es decir, en lugar de simplemente agregar una cadena "secreta", puedes agregar tanto el nombre de usuario Y una cadena secreta, y luego hash ESO. De manera similar, puede vincular los desafíos a una ID de conexión, una dirección de host IP, etc., incorporando esa información en la firma.
Finalmente, puede hacer que los desafíos sean sensibles al tiempo al incorporar la hora actual en el contenido del desafío, y puede evitar los ataques de repetición al dar a cada desafío una identificación y no permitir respuestas que se refieran a una identificación ya utilizada.
Su sistema puede verse así, como ejemplo. Tenga en cuenta que este ejemplo está fuera de mi cabeza, mientras que el suyo probablemente debería ser un poco más sofisticado que esto. Pero al menos esto demuestra cómo un sistema de este tipo podría funcionar.
Client:
say: My name is "Alice"
Server:
* super-secret key is "swordfish"
* sha1sum("Alice|30Nov11@12:03|swordfish")="4f9167de1e754d...."
say: Please sign this string: "Alice|30Nov11@12:03|4f9167de1e"
Client:
* password is "mustang"
* sha1sum("Alice|30Nov11@12:03|4f9167de1e|mustang")="6148f8d7bd9eeb6...."
* say: Challenge was "Alice|30Nov11@12:03|4f9167de1e"
* say: Response is "6148f8d7bd9eeb6c9156c5be385e96871721f6df"
Server:
* verify that user's name is in the challenge
* verify that timestamp is no more than 5 minutes in the past
* verify that "4f916..." corresponds to challenge with checksum replaced by "swordfish"
* verify that response is challenge with user's password appended