Quelle est la meilleure façon de hacher un numéro de carte de crédit afin qu'il puisse être utilisé pour les empreintes digitales (c'est-à-dire que la comparaison de deux hachages vous permettra de savoir si les numéros de carte correspondent ou non)?
Idéalement, je suis à la recherche de recommandations dont le haschich + sel pourrait bien convenir à ce cas d'utilisation. Le hachage identifierait de manière unique un numéro de carte particulier. Vous pouvez utiliser cet attribut pour vérifier si deux clients qui se sont inscrits avec vous utilisent le même numéro de carte, par exemple. (puisque vous n'auriez pas accès aux numéros de carte en texte brut)
Pour donner à cela un peu de contexte, voir Stripe API docs et recherchez fingerprint
. C'est là que j'ai entendu parler pour la première fois de ce concept. Les informations de carte de crédit seront stockées sur une machine sécurisée (quelque part dans le backend Stripe) qui n'est pas accessible au client, et l'API renvoie l'empreinte digitale afin de permettre au consommateur de l'API de faire des comparaisons (par exemple pour répondre à des questions comme = cette carte a-t-elle déjà été utilisée?).
Soyons clairs, car je sais que vous allez demander: Je n'essaye pas de le reproduire. Je suis juste curieux de comprendre comment cela pourrait être mis en œuvre
Je ne peux pas commenter comment Stripe fait cela mais je peux vous dire exactement comment Braintree le fait (parce que c'est là que je travaille). Si je devais deviner, Stripe utilise probablement une méthode similaire.
Dans l'API Braintree, nous proposons un identifiant de numéro unique pour une carte de crédit . Cet identifiant est un jeton opaque aléatoire qui sera toujours le même pour le numéro de carte stocké dans notre système. La valeur de départ de ce nombre est différente par commerçant dans notre système, vous ne pouvez donc pas les comparer entre les marchands.
Lorsqu'une nouvelle carte arrive, nous la recherchons en la comparant à une colonne hachée + salée. S'il correspond à cette colonne existante, nous savons que nous pouvons retourner le même identifiant de numéro unique. S'il ne correspond à aucun enregistrement existant, nous utilisons un générateur de nombres pseudo-aléatoires cryptographiquement sécurisé pour créer un nouvel identifiant de numéro unique et nous assurer qu'il n'entre pas en conflit avec un existant.
De cette façon, la valeur hachée + salée ne quitte jamais notre backend mais nous pouvons toujours fournir un moyen pour un commerçant d'identifier de manière unique les cartes de crédit stockées.
Ok, donc si c'est une exigence commerciale à laquelle vous devez répondre (vérifiez si une carte existe déjà dans le système), c'est comme ça que je le ferais.
Premièrement, PCI-DSS permet de stocker un PAN (numéro de compte principal ou numéro de carte de crédit) sous forme de hachage en utilisant une "cryptographie forte" et ils recommandent (mais n'exigent pas) qu'un sel soit également utilisé. PCI-DSS v3 § 3.4 (lien PDF) La raison est d'empêcher un tiers malveillant qui obtient le hachage de déterminer le PAN utilisé comme entrée pour le hachage.
Deuxièmement, votre plan de stocker cela dans un système séparé et sécurisé et de l'exposer uniquement via une API est une bonne mesure de défense en profondeur. Si j'implémentais cela, je ne le ferais pas renvoyer un hachage au système principal, je prendrais simplement le hachage comme paramètre pour l'appel d'API et que l'API renvoie "vrai" ou "faux" selon que le le hachage existe déjà dans le système ou non.
Pour la fonction de hachage, la clé pour empêcher la récupération des entrées (comme requis par PCI-DSS) est de choisir un algorithme qui vous permet de rendre le processus difficile à calculer, donc la tâche de forcer brutalement l'espace d'entrée relativement petit de PAN valides raisonnablement lents. SHA-512, suggéré par une autre réponse, n'est pas cet algorithme. En regardant la matrice de test pour la fissuration par hachage fournie par hashcat.net la machine la plus rapide de sa matrice peut calculer près de 2 milliards de hachages SHA-512 par seconde. Avec un espace d'entrée estimé à environ 30 000 000 000 000 de cartes **, cela signifie que non salé, vous pouvez calculer le SHA-512 de chacun de ces PAN en un peu plus de 4 heures et avoir les numéros de carte de chaque carte dans la base de données, si jamais cela se produisait. être volé.
Donc, ce dont nous avons besoin, c'est d'une fonction de hachage lent, mais la définition de la lenteur change tout le temps à mesure que les ordinateurs accélèrent et que la technologie évolue. Cela signifie qu'une fonction de hachage sécurisée sera une fonction avec un facteur de travail réglable, de sorte qu'au fil du temps, vous pouvez augmenter l'effort de calcul nécessaire pour calculer le hachage d'une entrée donnée. Il existe plusieurs algorithmes candidats qui répondent à ces critères, notamment PBKDF2, bcrypt et scrypt. Le consenus général pour le hachage de mot de passe est bcrypt, et c'est ce que je suggérerais ici. Pour le coût, définissez-le aussi haut que votre application le permet. Ce n'est probablement pas quelque chose que vous allez calculer très fréquemment (j'imagine que, selon votre application, vous allez regarder x hachages par minute ou heure ou jour plutôt que par seconde) et plus le coût, plus il sera difficile pour un adversaire qui capture le hachage à la force brute.
** Mon estimation est basée sur un numéro de compte à 9 chiffres, un chiffre de contrôle calculable qui n'augmente pas la complexité et un WAG de 30000 numéros d'identification bancaire actifs (les 6 premiers chiffres de la carte) basés sur une liste que j'ai trouvée.
Le hachage des numéros de carte de crédit ne remplace pas la sécurisation des données. Si votre système n'est pas suffisamment sécurisé pour stocker les numéros de carte de crédit bruts, il n'est pas suffisamment sécurisé pour stocker les hachages CC.
Même chose pour tout ce qui a une taille fixe et un jeu de caractères limité: date de naissance, numéro de téléphone, Zip, etc.
Les cartes de crédit sont toutes seize chiffres et même si 10 ^ 16 semble être un grand nombre, c'est assez simple pour les ressources de calcul. Si j'ai votre table de hachage CC #, je peux facilement l'attaquer avec une table Rainbow et obtenir une liste complète des cartes de crédit. Saler les valeurs avant de hacher rend la recherche impossible.
Toutes les valeurs CC possibles: quelque chose de moins de 10 ^ 16.
À titre de comparaison, imaginez que vos utilisateurs aient utilisé un mot de passe raisonnable à 8 caractères avec un sel de 20 octets: 62 ^ 28.
(Si j'étais votre auditeur PCI, je considérerais que le hachage de cartes de crédit équivaut à stocker les numéros de carte eux-mêmes.)
La réponse vous décevra: si un service/Oracle/hash peut vous dire si un numéro d'entrée est dans le fichier, il peut être brisé par une très petite force brute.
Considérez que dans une grande partie du pays, les cartes de crédit sont émises par relativement peu de banques dans leur région géographique. Vous pouvez facilement apprendre les numéros BIN des banques les plus populaires. Disons que vous avez un reçu dans un magasin de Memphis, et il est écrit VISA **** 1234. Il y a environ 20% de chances que ce soit l'un des dix BIN différents appartenant aux plus grandes banques de la région de Memphis. C'est 10 ^ 1 suppositions pour les six premiers chiffres. Ensuite, vous connaissez les 4 derniers, car ils sont imprimés sur le reçu. C'est maintenant seulement 10 ^ 1 suppositions qui couvrent 10 des 16 chiffres. Sur les six chiffres restants, itérez sur 5 et calculez le dernier en utilisant Luhn. C'est 10 ^ 6 tests qui donneront un numéro de compte valide 20% du temps.
Tout ce que vous avez à faire pour tester un numéro est de parcourir le service 100 000 fois. Peu importe si le service utilise un hachage ou un chiffrement ou une baguette magique pour protéger les numéros de compte, tant qu'il vous indique si votre entrée correspond ou non.
Vous pouvez noter que cela ne fonctionne que dans environ 20% des cas. Considérez que le gars qui a volé Target a pris 40 millions de numéros de compte et qu'il ne pouvait pas tous les vendre, car il n'y avait pas assez d'escrocs dans le monde pour en acheter autant. 20% de cela est 8 millions, et il n'en a probablement pas vendu autant non plus. Donc 20% est une bonne cote pour un attaquant.
Complétant les suggestions précédentes. Que diriez-vous d'utiliser SHA qui n'était apparemment pas officiel jusqu'en 2015, plus tard que cette discussion) en ajoutant le numéro de carte avec une clé secrète spécifique au commerçant afin de rendre les hachages spécifiques au commerçant.
Le simple ajout d'une clé secrète au message n'était pas sûr pour SHA-1 et SHA-2 en raison de leur faiblesse d'extension de longueur. Ce n'est pas le cas avec SHA-3, qui est résistant aux attaques par extension de longueur par conception. Comme expliqué --- (ici , on pourrait même utiliser SHA-3 pour le calcul MAC en ajoutant simplement le message avec la clé.
Bien sûr, le problème de la façon de stocker en toute sécurité les clés secrètes demeure. Je n'ai aucune expérience avec l'industrie des cartes de paiement. Je suis juste tombé sur cette question et l'ai trouvée intéressante. J'adorerais obtenir des commentaires d'utilisateurs plus expérimentés sur les problèmes spécifiques au traitement des numéros de carte (et de leur espace de recherche relativement petit) en utilisant cette approche.
Vous ne devez pas le stocker selon les normes PA-DSS définies ici: https://www.pcisecuritystandards.org/documents/pa-dss_v2.pdf
Il est dit:
1.1 Ne stockez pas les données d'authentification sensibles après autorisation (même si elles sont cryptées): les données d'authentification sensibles incluent les données citées dans les exigences 1.1.1 à 1.1.3 suivantes.
Dans la colonne adjacente, il indique:
Si cette application de paiement stocke des données d'authentification sensibles, vérifiez que l'application est destinée uniquement aux émetteurs et/ou aux sociétés qui prennent en charge les services d'émission
Je suppose que vous n'êtes pas un émetteur ou une entreprise qui prend en charge l'émission de services. Gardez à l'esprit que Target Corporation a récemment été piraté et que les informations de carte de crédit ont été volées en temps réel et sur des serveurs qui n'ont pas chiffré les données de bout en bout. Je crois comprendre qu'il est en cours de rectification et de sécurisation. Franchement, ne le stockez pas période. Même si vous utilisez le hachage SHA512, votre implémentation peut être défectueuse. Avec les meilleures contre-mesures, je ne voudrais pas être à la fin d'un procès.
Éditer:
Il est techniquement autorisé dans la section 2.3 de PA-DSS v2.0. Mais ne le fais pas.
Si vous allez le faire, ajoutez une sorte d'obscurcissement. Je viens de me garantir des votes négatifs, mais l'obscurcissement n'est pas sans valeur comme certains insisteront.
Si vous supposez que le système est connu, il n'y a aucune valeur. Mais si le système n'est pas connu, il a une valeur absolue. Un IV utilisé pour "poivrer", comme l'a dit Alex, serait une forme d'obscurcissement, sans augmenter les collisions, et maintenir la capacité d'interroger.
Un poivron ne serait cependant pas une obfuscation très efficace, à moins qu'il ne soit suffisamment gros pour ne pas être deviné par force brute dans un délai raisonnable. 100 octets aléatoires seraient peut-être exagérés mais il n'y a aucune raison de ne pas aller trop loin.
Une autre chose qui pourrait être une obfuscation efficace serait de ne pas supposer que le poivre et le message sont atteints en même temps, de sorte que si vous remaniez périodiquement les hachages dans un lot de nuit (en gardant une trace du nombre de tours), ils besoin d'un autre élément d'information - combien de tours, ou comment les tours sont calculés.
Gardez à l'esprit que je ne pense pas que ce soit une bonne idée, je pense juste à haute voix ici. Si votre environnement est suffisamment sécurisé pour les cartes de crédit, non seulement je ne les hacherais pas, mais je les stocke dans une table conçue pour les performances de recherche les plus rapides.