Un système sur lequel je travaille accepte de saisir un numéro de compte client et doit générer un jeton basé sur celui-ci. Nous ne sommes pas autorisés à stocker le texte simple du numéro de compte lui-même, de sorte que le but du jeton est le suivant:
Les numéros de compte ressemblent à des numéros de carte de crédit. Ils sont des chaînes numériques longues à 16 chiffres; Les 4 premiers caractères sont constants; Le dernier caractère est un chiffre de contrôle calculable. Cela signifie que la taille réelle de l'ensemble d'entrée est une chaîne numérique de 11 caractères: 99 999 999999 99999 permutations possibles.
J'ai pensé aux méthodes ci-dessous. Supposez HASH désigne un hachage sécurisé suffisamment lent tel que l'itération élevée PBKDF2, BCRYPT ou Argon2 et chiffrer signifie AES256.
1. HASH uni
hash(account_num)
Tout en étant simple, cette approche est facile à inverser via une force brute et est vulnérable aux tables arc-en-ciel.
2. HASH salé par compte
hash(salt + account_num)
Cette approche fixe toutefois la vulnérabilité aux tables arc-en-ciel, car la taille limitée de l'ensemble d'entrée est toujours facile à inverser via une force brute.
3. HASH salé par utilisateur crypté avec poivre global
encrypt(hash( salt + account_num ), pepper)
Ceci est basé sur Mécanisme de stockage de mot de passe de Dropbox . L'inversion via une force brute nécessite de fuir à la fois les blobs cryptés et la clé de cryptage. Cependant, étant donné que le cryptage de la même valeur deux fois avec les mêmes principes de flangs de sortie, cela éclaire la possibilité de sélectionner un compte à partir de la base de données par numéro de compte.
4. Approche hybride
Ce que cela accomplit:
Ma question: L'approche 4 a-t-elle un sens? Pour la sécurité supplémentaire, il fournit, est-ce trop compliqué? Avoir-t-il des défauts que je n'ai pas pensé? Surtout, y a-t-il un moyen plus simple de résoudre ce problème?
Vous pouvez simplement utiliser un [~ # ~ # ~] hmac [~ # ~] : Les HMAC ont deux entrées, un message et une clé de cryptage et produisent un code d'authentification de message, qui est essentiellement un hachage (par exemple Vous ne pouvez pas revenir au MAC dans le message, ni la touche, ou les deux). Donc, dans votre cas, vous auriez:
token = hmac(account_num, key)
Le HMAC est construit de manière particulière de se protéger contre les attaques susceptibles de révéler la clé. C'est une primitive cryptographique bien comprise.
Sans connaître la clé, une attaque de force brute sur le jeton pour obtenir le numéro de compte n'est pas pratique. OTOH, pour vous, connaissant la clé, il est trivial de transformer un numéro de compte en jeton.
Bien sûr, la sécurité de vos numéros de compte repose désormais avec la sécurité de la clé; Donc, si vous perdez la clé et la liste des jetons à un attaquant, vous avez ouvert vos numéros de compte aux attaques de la force brute. Mais votre idée numéro 4 souffre du même problème.
Ce pourrait être une bonne idée de penser à la gestion des clés. Vous pouvez donc facilement modifier une clé si on devient compromis.