Une chose que je n'ai pas vue mentionnée ici, bien que ce soit une extension de la réponse de Marcus Adams, est que vous ne devriez pas utiliser une seule information pour identifier et authentifier un utilisateur s'il y a une possibilité d' attaques chronométrées , ce qui peut utilisez les différences de temps de réponse pour deviner jusqu'où une comparaison de chaînes est arrivée.
Si vous utilisez un système qui utilise une «clé» pour rechercher l'utilisateur ou les informations d'identification, cette information peut être devinée progressivement au fil du temps en envoyant des milliers de requêtes et en examinant le temps nécessaire à votre base de données pour trouver (ou non trouver) un enregistrement. Ceci est particulièrement vrai si la "clé" est stockée en texte brut au lieu d'un hachage unidirectionnel de la clé. Vous voudrez stocker les clés des utilisateurs dans un texte brut ou crypté symétriquement si vous avez besoin de pouvoir afficher à nouveau la clé à l'utilisateur.
En ayant une deuxième information, ou "secret", vous pouvez d'abord rechercher l'utilisateur ou les informations d'identification à l'aide de la "clé", qui pourrait être vulnérable à une attaque de synchronisation, puis utiliser une fonction de comparaison sécurisée pour vérifier la valeur de le secret".
Voici l'implémentation de cette fonction par Python:
https://github.com/python/cpython/blob/cd8295ff758891f21084a6a5ad3403d35dda38f7/Modules/_operator.c#L727
Et il est exposé dans la hmac
lib (et probablement dans d'autres):
https://docs.python.org/3/library/hmac.html#hmac.compare_digest
Une chose à noter ici est que je ne pense pas que ce type d'attaque fonctionnera sur des valeurs qui sont hachées ou chiffrées avant la recherche, car les valeurs comparées changent de manière aléatoire chaque fois qu'un caractère de la chaîne d'entrée change. J'ai trouvé une bonne explication à cela ici .
Les solutions pour stocker les clés API seraient alors:
- Utilisez une clé et un secret séparés, utilisez la clé pour rechercher l'enregistrement et utilisez une comparaison sécurisée pour vérifier le secret. Cela vous permet de montrer à nouveau à l'utilisateur la clé et le secret à un utilisateur.
- Utilisez une clé et un secret séparés, utilisez un chiffrement symétrique et déterministe sur le secret et faites une comparaison normale des secrets chiffrés. Cela vous permet de montrer à nouveau à l'utilisateur la clé et le secret, et peut vous éviter d'avoir à implémenter une comparaison sécurisée dans le temps.
- Utilisez une clé et un secret séparés, affichez le secret, hachez et stockez-le, puis effectuez une comparaison normale du secret haché. Cela supprime la nécessité d'utiliser un cryptage bidirectionnel et présente l'avantage supplémentaire de garder votre secret sécurisé si le système est compromis. Cela présente l'inconvénient que vous ne pouvez plus montrer le secret à l'utilisateur.
- Utilisez une seule clé , montrez-la une fois à l'utilisateur, hachez-la, puis effectuez une recherche normale de la clé hachée ou chiffrée. Cela utilise une seule clé, mais il ne peut pas être montré à nouveau à l'utilisateur. A l'avantage de garder les clés en sécurité si le système est compromis.
- Utilisez une seule clé , montrez-la une fois à l'utilisateur, cryptez-la et effectuez une recherche normale du secret crypté. Peut être montré à nouveau à l'utilisateur, mais au prix de la vulnérabilité des clés si le système est compromis.
Parmi ceux-ci, je pense que 3 est le meilleur équilibre entre sécurité et commodité. J'ai vu cela mis en œuvre sur de nombreux sites Web lors de l'émission des clés.
J'invite également tous les experts en sécurité à critiquer cette réponse. Je voulais juste que cela soit un autre point de discussion.