web-dev-qa-db-fra.com

Quels sont les facteurs de travail de chiffrement optimaux?

J'utilise une bibliothèque Java scrypt pour le stockage des mots de passe. Il appelle une valeur N, r et p lorsque je crypte des choses, que sa documentation appelle "coût CPU", "coût mémoire" et "coût de parallélisation". paramètres. Le seul problème est que je ne sais pas vraiment ce qu'ils signifient spécifiquement ou quelles seraient les bonnes valeurs pour eux; peut-être qu'ils correspondent en quelque sorte aux commutateurs -t, -m et -M sur l'application d'origine de Colin Percival ?

Quelqu'un a-t-il des suggestions à ce sujet? La bibliothèque elle-même répertorie N = 16384, r = 8 et p = 1, mais je ne sais pas si c'est fort ou faible ou quoi.

65

Pour commencer:

cpercival mentionné dans ses diapositives de 2009 quelque chose autour

  • (N = 2 ^ 14, r = 8, p = 1) pour <100 ms (utilisation interactive), et
  • (N = 2 ^ 20, r = 8, p = 1) pour <5s (stockage sensible).

Ces valeurs s'avèrent être assez bonnes pour une utilisation générale (password-db pour certaines WebApp) même aujourd'hui (2012-09). Bien sûr, les détails dépendent de l'application.

De plus, ces valeurs signifient (principalement):

  • N: facteur de travail général, nombre d'itérations.
  • r: taille de bloc utilisée pour le hachage sous-jacent; affine le coût relatif de la mémoire.
  • p: facteur de parallélisation; affine le coût relatif du processeur.

r et p sont destinés à répondre au problème potentiel selon lequel la vitesse du processeur, la taille de la mémoire et la bande passante n'augmentent pas comme prévu. Si les performances du processeur augmentent plus rapidement, vous augmentez p, si au contraire une percée dans la technologie de la mémoire fournit une amélioration de l'ordre de grandeur, vous augmentez r. Et N est là pour suivre le doublement général des performances par période de temps .

Important: Toutes les valeurs modifient le résultat. (Mis à jour :) C'est la raison pour laquelle tous les paramètres scrypt sont stockés dans la chaîne de résultat.

65
gimpf

La mémoire requise pour que scrypt fonctionne est calculée comme suit:

128 octets × N_cost × r_blockSizeFactor

pour les paramètres que vous citez (N=16384, r=8, p=1)

128 × 16384 × 8 = 16 777 216 octets = 16 Mo

Vous devez en tenir compte lors du choix des paramètres.

Bcrypt est "plus faible" que Scrypt (bien qu'encore trois ordres de grandeur plus fort que PBKDF2 ) car il ne nécessite que 4 Ko de mémoire. Vous voulez rendre difficile la parallélisation de la fissuration dans le matériel. Par exemple, si une carte vidéo possède 1,5 Go de mémoire intégrée et que vous avez réglé scrypt pour consommer 1 Go de mémoire:

128 × 16384 × 512 = 1 073 741 824 octets = 1 Go

alors un attaquant n'a pas pu le paralléliser sur sa carte vidéo. Mais alors votre application/téléphone/serveur devrait utiliser 1 Go de RAM chaque fois qu'ils calculent un mot de passe).

Cela m'aide à considérer les paramètres de cryptage comme un rectangle. Où:

  • la largeur est la quantité de mémoire requise (128 * N * r)
  • la hauteur est le nombre d'itérations effectuées
  • et la zone résultante est la dureté globale

enter image description here

  • la cost ( [~ # ~] n [~ # ~] ) augmente la mémoire utilisation et itérations .
  • blockSizeFactor ( r ) augmente l'utilisation de la mémoire .

Le paramètre restant parallelization ( p ) signifie que vous devez faire la chose en entier 2, 3 ou plusieurs fois:

enter image description here

Si vous aviez plus de mémoire que CPU, vous pourriez calculer les trois chemins séparés en parallèle - nécessitant le triple de la mémoire:

enter image description here

Mais dans toutes les implémentations du monde réel, il est calculé en série, triplant les calculs nécessaires:

enter image description here

En réalité, personne n'a jamais choisi un facteur p autre que p=1.

Quels sont les facteurs idéaux?

  • Autant RAM que vous pouvez épargner
  • pour autant de temps que possible!

Tableau des bonus

Version graphique de ce qui précède:

enter image description here

Remarques:

  • l'axe vertical est l'échelle logarithmique
  • Le facteur de coût (horizontal) lui-même est log (itérations = 2CostFactor)
  • Mis en évidence dans le r=8 courbe

Et zoomé dans la version ci-dessus sur la zone raisonnable:

enter image description here

53
Ian Boyd

Je ne veux pas marcher sur les excellentes réponses fournies ci-dessus, mais personne ne parle vraiment de la raison pour laquelle "r" a la valeur qu'il a. La réponse de bas niveau fournie par le papier Scrypt de Colin Percival est qu'elle se rapporte au "produit de latence de mémoire-bande passante". Mais qu'est-ce que cela veut vraiment dire?

Si vous faites bien Scrypt, vous devriez avoir un grand bloc de mémoire qui se trouve principalement dans la mémoire principale. La mémoire principale prend du temps à extraire. Lorsqu'une itération de la boucle de saut de bloc sélectionne pour la première fois un élément du grand bloc à mélanger dans le tampon de travail, il doit attendre de l'ordre de 100 ns pour que le premier bloc de données arrive. Ensuite, il doit en demander un autre et attendre qu'il arrive.

Pour r = 1, vous feriez 4 itérations Salsa20/8 et 2n lectures imprégnées de latence à partir de la mémoire principale.

Ce n'est pas bon, car cela signifie qu'un attaquant pourrait obtenir un avantage sur vous en créant un système avec une latence réduite sur la mémoire principale.

Mais si vous augmentez r et diminuez proportionnellement N, vous pouvez atteindre les mêmes besoins en mémoire et effectuer le même nombre de calculs qu'auparavant - sauf que vous avez troqué certains accès aléatoires pour des accès séquentiels. L'extension de l'accès séquentiel permet à l'UC ou à la bibliothèque de pré-extraire efficacement les prochains blocs de données requis. Alors que la latence initiale est toujours là, la latence réduite ou éliminée pour les blocs ultérieurs fait la moyenne de la latence initiale à un niveau minimal. Ainsi, un attaquant gagnerait peu à améliorer sa technologie de mémoire par rapport à la vôtre.

Cependant, il y a un point de rendements décroissants avec l'augmentation de r, et cela est lié au "produit de latence de bande passante mémoire" mentionné précédemment. Ce que ce produit indique, c'est combien d'octets de données peuvent être en transit de la mémoire principale au processeur à un moment donné. C'est la même idée qu'une autoroute - s'il faut 10 minutes pour voyager du point A au point B (latence), et que la route livre 10 voitures/minute au point B à partir du point A (bande passante), la route entre les points A et B contient 100 voitures. Ainsi, le r optimal se rapporte au nombre de blocs de données de 64 octets que vous pouvez demander à la fois, afin de couvrir la latence de cette demande initiale.

Cela améliore la vitesse de l'algorithme, vous permettant soit d'augmenter N pour plus de mémoire et de calculs, soit d'augmenter p pour plus de calculs, comme vous le souhaitez.

Il y a d'autres problèmes avec l'augmentation trop importante de "r", dont je n'ai pas beaucoup discuté:

  1. Augmenter r tout en diminuant N réduit le nombre de sauts pseudo-aléatoires autour de la mémoire. Les accès séquentiels sont plus faciles à optimiser et pourraient donner une fenêtre à un attaquant. Comme Colin Percival me l'a fait remarquer sur Twitter, un r plus élevé pourrait permettre à un attaquant d'utiliser une technologie de stockage moins coûteuse et plus lente, réduisant considérablement leurs coûts ( https://Twitter.com/cperciva/status/66137393187022848 ).
  2. La taille du tampon de travail est de 1024r bits, donc le nombre de produits finaux possibles, qui seront éventuellement introduits dans PBKDF2 pour produire la clé de sortie Scrypt, est de 2 ^ 1024r. Le nombre de permutations (séquences possibles) de sauts autour du grand bloc mémoire est de 2 ^ NlogN. Ce qui signifie qu'il existe 2 ^ NlogN produits possibles de la boucle de saut de mémoire. Si 1024r> NlogN, cela semble indiquer que le tampon de travail est sous-mélangé. Bien que je ne sache pas cela avec certitude et que j'aimerais voir une preuve ou une réfutation, il peut être possible de trouver des corrélations entre le fonctionnement le résultat du tampon et la séquence de sauts, ce qui pourrait permettre à un attaquant de réduire ses besoins en mémoire sans augmenter le coût de calcul. Encore une fois, c'est une observation basée sur les chiffres - il se peut que tout soit si bien mélangé à chaque tour que ce ne soit pas un problème. r = 8 est bien en dessous de ce seuil potentiel pour le standard N = 2 ^ 14 - pour N = 2 ^ 14, ce seuil serait r = 224.

Pour résumer toutes les recommandations:

  1. Choisissez r pour être juste assez grand pour faire la moyenne des effets de la latence de la mémoire sur votre appareil et pas plus. Gardez à l'esprit que la valeur recommandée par Colin Percival, r = 8, semble rester assez optimale globalement pour la technologie de la mémoire, et cela n'a apparemment pas beaucoup changé en 8 ans; 16 peut être un peu mieux.
  2. Décidez de la taille d'un bloc de mémoire que vous souhaitez utiliser par thread, en gardant à l'esprit que cela affecte également le temps de calcul et définissez N en conséquence.
  3. Augmentez arbitrairement p ce que votre utilisation peut tolérer (remarque: sur mon système et en utilisant ma propre implémentation, p = 250 (4 threads) avec N = 16384 et r = 8 prend ~ 5 secondes), et activez le threading si vous pouvez gérer avec le coût de mémoire supplémentaire.
  4. Lors du réglage, préférez une grande taille de N et de bloc de mémoire à une augmentation de p et du temps de calcul. Le principal avantage de Scrypt vient de sa grande taille de bloc de mémoire.

Une référence de ma propre implémentation de Scrypt sur une Surface Pro 3 avec un i5-4300 (2 cœurs, 4 threads), en utilisant une constante 128Nr = 16 Mo et p = 230; l'axe gauche est en secondes, l'axe inférieur est la valeur r, les barres d'erreur sont +/- 1 écart-type:

Scrypt r values vs. p with constant large block size

11
Nick Bauer