Hachage de mot de passe à l'aide de problèmes complets NP


16

Les algorithmes de hachage de mot de passe couramment utilisés fonctionnent comme ceci aujourd'hui: salez le mot de passe et introduisez-le dans un fichier KDF. Par exemple, en utilisant PBKDF2-HMAC-SHA1, le processus de hachage de mot de passe est DK = PBKDF2(HMAC, Password, Salt, ...). Parce que HMAC est un hachage à 2 tours avec des touches rembourrées et SHA1 une série de permutations, décalages, rotations et opérations au niveau du bit, fondamentalement, l'ensemble du processus consiste en quelques opérations de base organisées d'une certaine manière. Il n'est pas évident, fondamentalement, à quel point ils sont vraiment difficiles à calculer. C'est probablement pourquoi les fonctions à sens unique sont toujours une croyance et nous avons vu que certaines fonctions de hachage cryptographiques historiquement importantes sont devenues précaires et obsolètes.

Je me demandais s'il était possible de tirer parti des problèmes complets de NP pour hacher les mots de passe d'une toute nouvelle manière, dans l'espoir de lui donner une base théorique plus solide. L'idée clé est, supposons que P! = NP (si P == NP alors aucun OWF donc les schémas actuels se cassent aussi), étant un problème NPC signifie que la réponse est facile à vérifier mais difficile à calculer. Cette propriété correspond bien aux exigences du hachage de mot de passe. Si nous considérons le mot de passe comme la réponse à un problème NPC, nous pouvons stocker le problème NPC comme hachage du mot de passe pour contrer les attaques hors ligne: il est facile de vérifier le mot de passe, mais difficile à résoudre.

Attention, le même mot de passe peut être mappé à plusieurs instances d'un problème NPC, probablement pas tous difficiles à résoudre. Dans un premier temps dans cette recherche, j'essayais d'interpréter une chaîne binaire comme une réponse à un problème 3-SAT, et de construire une instance de problème 3-SAT à laquelle la chaîne binaire est une solution. Dans sa forme la plus simple, la chaîne binaire a 3 bits: x_0, x_1, x_2. Ensuite, il y a 2 ^ 3 == 8 clauses:

000 (    (x_0) v    (x_1) v    (x_2) )
--------------------------------------
001 (    (x_0) v    (x_1) v NOT(x_2) )
010 (    (x_0) v NOT(x_1) v    (x_2) )
011 (    (x_0) v NOT(x_1) v NOT(x_2) )
100 ( NOT(x_0) v    (x_1) v    (x_2) )
101 ( NOT(x_0) v    (x_1) v NOT(x_2) )
110 ( NOT(x_0) v NOT(x_1) v    (x_2) )
111 ( NOT(x_0) v NOT(x_1) v NOT(x_2) )

Supposons que la chaîne binaire soit 000. Ensuite, seule la clause 1 sur 8 est fausse (la première). Si nous éliminons la première clause et les 7 autres clauses, alors 000 est une solution de la formule résultante. Donc, si nous stockons la formule, nous pouvons vérifier 000.

Le problème est, pour une chaîne de 3 bits, si vous voyez 7 clauses différentes, alors vous savez instantanément laquelle est manquante, et cela révélerait les bits.

Alors plus tard, j'ai décidé d'en éliminer 3, en ne gardant que les 4 marqués par 001, 010, 100 et 111. Cela introduit parfois des collisions mais rend la résolution du problème moins triviale. Les collisions ne se produisent pas toujours, mais on ne sait pas encore si elles disparaîtront sûrement lorsque l'entrée aura plus de bits.

Éditer. Dans le cas général où la chaîne binaire peut être n'importe laquelle (000, 001, ..., 111), il existe toujours 8 clauses où 7 sont vraies et 1 est fausse. Choisissez les 4 clauses qui donnent la valeur de vérité (001, 010, 100, 111). Cela se reflète dans la mise en œuvre du prototype ci-dessous.

Edit. As the answer shown by @D.W. below, this method of choosing clauses may still result in too many clauses on a given set of variables which makes it possible to quickly narrow down their values. There are alternate methods of choosing the clauses among the total 7 * C(n, 3) clauses. For example: Pick a different number of clauses from a given set of variables, and do that only for adjacent variables ( (x_0, x_1, x_2), (x_1, x_2, x_3), (x_2, x_3, x_4), ... ) and thus form a cycle instead of a clique. This method is likely not working as well because intuitively you can try assignments using induction to test whether all clauses can be satisfied. So to make it simple explaining the overall structure let's simply use the current method.

Le nombre de clauses pour une chaîne de n bits est 4 * C (n, 3) = 4 * n * (n - 1) * (n - 2) / 6 = O (n ^ 3), ce qui signifie la taille de le hachage est un polynôme de la taille du mot de passe.

Il y a une implémentation de prototype en Python ici . Il génère une instance de problème 3-SAT à partir d'une chaîne binaire d'entrée utilisateur.


Après cette longue introduction, enfin mes questions:

  1. La construction ci-dessus (telle qu'implémentée dans le prototype) fonctionne-t-elle comme un hachage de mot de passe sécurisé, ou du moins semble prometteuse, peut être révisée, etc.? Sinon, où ça échoue?

  2. Parce que nous avons le choix entre 7 * C (n, 3) clauses, est-il possible de trouver une autre façon de construire une instance 3-SAT sécurisée pouvant être utilisée comme hachage de mot de passe, éventuellement à l'aide de la randomisation?

  3. Existe-t-il des travaux similaires visant à tirer parti de l'exhaustivité de NP pour concevoir des schémas de hachage de mot de passe sécurisés éprouvés, et déjà obtenu des résultats (positifs ou négatifs)? Quelques intros et liens seraient les bienvenus.


Éditer. J'accepterais la réponse ci-dessous de @DW, qui a été le premier à répondre et a donné un excellent aperçu de la structure du problème ainsi que des ressources utiles. Le schéma de sélection de clause naïve présenté ici (tel qu'implémenté dans le prototype Python) ne semble pas fonctionner car il est possible d'affiner rapidement les affectations de variables en petits groupes. Cependant, le problème reste ouvert car je n'ai pas vu de preuve formelle montrant que de telles réductions NPC-to-PasswordHashing ne fonctionneront pas du tout. Même pour ce problème spécifique de réduction de 3-SAT, il peut y avoir différentes façons de choisir des clauses que je ne veux pas énumérer ici. Toutes les mises à jour et discussions sont donc toujours les bienvenues.


J'ai branché votre génération de clause à un solveur sat (picosat utilisant pycosat) ici . Pour nbits = 300, le plus long est de générer les clauses, pycosat tue l'instance. Je n'ai pas dépassé 300 car votre génération de clause est en fait très longue. De plus, 0 ... 0 est toujours une solution dans votre génération. Si vous avez toujours de telles solutions «faciles», cela ne fonctionnera pas.
holf

Réponses:


17

Malheureusement, cela ne semble pas fonctionner (voir ci-dessous pour plus de détails), et il semble difficile de trouver un moyen de faire en sorte que ce type d'idée produise un schéma prouvablement sécurisé.

Le problème avec votre idée générale

Vous n'êtes pas le premier à penser à l'idée de baser la cryptographie sur des problèmes NP-complets. Le problème est que la dureté NP garantit uniquement la dureté dans le pire des cas, mais la cryptographie nécessite une dureté moyenne dans le cas. Il y a eu plusieurs tentatives pour baser la cryptographie sur des problèmes NP-complets (par exemple, des cryptosystèmes à dos), mais ils n'ont pas bien réussi. Généralement, ce qui se passe, c'est que les gens découvrent des algorithmes qui sont souvent efficaces en moyenne (ou avec une probabilité non triviale), même si dans le pire des cas ils sont exponentiels; cela suffit pour briser la crypto, même si cela ne contredit pas la dureté NP.

Je suggère de lire plus sur le sujet. Vous pouvez trouver des points de départ utiles dans L'importance des problèmes NP-durs en cryptographie , Problèmes ouverts de complexité de cas moyen autres que les fonctions unidirectionnelles , Statut des mondes d'Impagliazzo? , Pire à des réductions de cas moyennes .

Le problème avec votre régime particulier

Votre proposition spécifique n'est pas entièrement spécifiée. Pour analyser un schéma, vous devez spécifier entièrement le fonctionnement du schéma. Dans votre cas, la façon dont vous sélectionnez 4 des 7 clauses dans l'exemple général n'est pas claire. (Et un seul exemple ne remplace pas une spécification qui décrit comment vous le faites en général.)

X0,X1,X2,X3,X425affectations possibles à ces 5 variables, essayez-les toutes et rejetez toute affectation violée par l'une des 40 clauses. Je prédis que cela ne vous laissera qu'une seule affectation compatible avec toutes les clauses.

1/21/2dix25-1sept/8(sept/8)402-7.7(25-1)×2-7.70,15

Cela peut être répété pour chaque groupe de 5 variables, récupérant de manière unique l'affectation satisfaisante unique pour chacune. En cas d'ambiguïté, les affectations de candidats peuvent être vérifiées par rapport à d'autres clauses.

De cette façon, nous voyons qu'il existe un algorithme efficace qui résoudra généralement la classe d'instances 3SAT générées par votre procédure. Il ne résoudra pas toutes les instances 3SAT, mais les instances que vous générez ont une structure spéciale, et il résout efficacement les instances avec cette structure spéciale. Cela illustre bien le point: certaines instances de 3SAT sont plus faciles que d'autres, et la dureté de 3SAT (dans le pire des cas) ne dit pas grand-chose sur la dureté des instances spéciales que vous générez ou la dureté d'une instance 3SAT moyenne.


Il existe une implémentation de référence qui agit comme une spécification complète. Dans cette première tentative, le schéma est vraiment simple. J'ai simplement choisi les 4 clauses qui donneraient 001, 010, 100 et 111 lors de la substitution dans le mot de passe. Cela donne 4 combinaisons valides sur 8 pour chaque clause.
Cyker

Vous avez probablement raison de dire que ce rapide donne trop de clauses, ce qui permet d'affiner rapidement la solution. Cependant, nous commençons par les clauses O (n ^ 3) et nous sommes libres de choisir celles à conserver. Les triplets peuvent ne pas être indépendants. Je me demande donc si les clauses sont choisies avec un modèle qui essaie de supprimer les instances de problème faciles, si votre analyse heuristique est toujours valable.
Cyker

1
Mais le plus intéressant est que, grosso modo, nous n'avons pas de problèmes de PNJ dans le cas moyen?
Cyker

1
@Cyker, vous avez absolument raison. À strictement parler, vous ne pouvez pas multiplier les probabilités car il n'y a aucune garantie que les probabilités sont indépendantes. C'est juste une heuristique pour essayer de prédire dans quelle mesure l'algorithme pourrait fonctionner. L'heuristique pourrait être fausse. Le test ultime consiste à implémenter l'algorithme et à voir s'il fonctionne ou non.
DW

2
Un test rapide pourrait être d'essayer vos instances sur un solveur SAT. Je pense que les solveurs SAT seront efficaces sur vos instances, mais je n'ai pas complètement essayé de comprendre vos spécifications. Essayez de générer une instance de 10000 variables et exécutez un solveur SAT (en passant, sans remplissage / salage, les mots de passe seront beaucoup plus petits ...)
holf
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.