Comment choisir un IV approprié (vecteur D'initialisation) pour AES/CTR/NoPadding?

Je voudrais crypter les cookies qui sont écrits par une webapp et je voudrais garder la taille des cookies au minimum, d'où la raison pour laquelle j'ai choisi AES/CTR/NoPadding.

Que recommanderiez-vous d'utiliser comme IV qui est assez aléatoire et garde toujours l'application sans état. Je sais que je peux simplement générer un IV aléatoire et l'ajouter au message, mais cela augmentera la taille du cookie.

En outre, Quelle est la taille recommandée de IV pour AES 128 bits?

Comment le reste est à chacun de faire ceci? Faire tout "essayé et vrai" les moyens existent-ils? Je ne veux pas réinventer la roue.

26
demandé sur Artjom B. 2011-01-05 22:46:55

5 réponses

La sécurité CTR exige que vous ne réutilisez jamais un IV pour deux chiffrements de messages avec la même clé. En fait, c'est encore plus strict: le mode CTR fonctionne en chiffrant les valeurs successives d'un compteur (le IV n'est que la valeur initiale de ce compteur) et une sécurité appropriée n'est obtenue que si la même valeur du compteur n'est pas utilisée deux fois; cela signifie que le chiffrement d'une valeur avec un IV" consomme" cryptage.

Le moyen le plus simple de le faire est d'utiliser un générateur de nombres aléatoires cryptographiquement sécurisé, et de créer un nouveau IV aléatoire de 16 octets pour chaque message. Je souligne "cryptographiquement sécurisé" parce que c'est important; un générateur de nombres aléatoires de base ne suffit pas. Avec Java, utilisez java.util.SecureRandom. Avec Win32, appelez CryptGenRandom(). Avec une sélection aléatoire, l'espace d'IV 128 bits possible est suffisamment grand pour que les collisions soient extrêmement improbables. En fait, C'est pourquoi AES utilise des blocs de 128 bits (ainsi ce qui implique 128 bits IV).

L'entité qui décryptera le message doit connaître L'IV, vous devez donc le stocker avec le message crypté. C'est un supplément de 16 octets. Je comprends que cette surcharge est ce que vous voulez éviter, bien que 16 octets n'est pas beaucoup pour un cookie. La longueur maximale effective d'un cookie dépend du navigateur Web, mais 4000 caractères semblent fonctionner "partout". Un IV de 16 octets, lorsqu'il est codé en caractères (par exemple avec Base64), utilisera environ 22 caractères, c'est-à-dire beaucoup moins de 1% de la taille maximale de votre cookie: peut-être que vous pouvez vous le permettre ?

Maintenant, nous pouvons devenir funky et essayer de réduire la longueur IV par la ruse:

  • Générez L'IV avec une fonction de hachage: côté serveur, utilisez un compteur, qui commence à 0 et est incrémenté chaque fois qu'un nouveau IV est nécessaire. Pour obtenir L'IV, vous hachez le compteur avec une fonction de hachage appropriée, par exemple SHA-256, et vous conservez les 16 premiers octets de la valeur de hachage. Les "propriétés de randomisation" du la fonction de hachage sera suffisante pour rendre L'IV suffisamment aléatoire en ce qui concerne les exigences CTR. Cela nécessite une fonction de hachage cryptographiquement sécurisée, d'où SHA-256 (évitez MD5). Il vous suffit ensuite de stocker la valeur du compteur dans le cookie, et le compteur sera inférieur à 16 octets (par exemple, si vous n'avez pas plus de 4 milliards de clients, le compteur tiendra dans 4 octets). Cependant, il y a un coût caché: le serveur (je suppose que le serveur effectue le cryptage dans votre système) doit s'assurer qu'il ne réutilise jamais une valeur de compteur, il doit donc stocker le" compteur actuel " quelque part d'une manière qui persiste sur les redémarrages du serveur, et n'échoue pas non plus si vous évoluez jusqu'à plusieurs frontaux. Ce n'est pas aussi facile à is semble.

  • Utilisez une valeur unique externe: Il est possible que le cookie fasse partie d'un contexte qui fournit suffisamment de données pour générer une valeur qui sera unique à chaque cryptage. Par exemple, si la demande contient également (en clair) un " ID utilisateur", vous pouvez utiliser l'ID utilisateur comme source IV. La configuration est similaire à celle ci-dessus: vous obtenez toutes ces données, les bourrez dans SHA-256, et les 16 premiers octets de la sortie SHA-256 sont le IV dont vous avez besoin. Cela ne fonctionne que si ces données ne changent pas pour un message crypté donné, et si elle est vraiment unique. C'est une occurrence rare: par exemple, un "ID utilisateur" n'est bon pour cela que s'il n'est jamais nécessaire de réencrypter un nouveau message pour le même utilisateur, et s'il n'y a jamais une possibilité qu'un ID utilisateur soit réutilisé (par exemple, un ancien utilisateur se ferme, un nouvel utilisateur vient et sélectionne l'ID utilisateur maintenant libre).

L'utilisation d'un IV aléatoire de 16 octets généré avec un PRNG cryptographiquement sécurisé est toujours le moyen "sûr", et celui que je recommande. Si vous trouvez un espace restreint dans le cookie, cela signifie que vous approchez de la limite de 4 Ko, à quel point vous voudrez peut-être utiliser la compression (sur les données avant le cryptage ; après le cryptage, la compression est très peu susceptible de fonctionner). Utiliser zlib (en Java, vous pouvez accéder à zlib via java.util.zip).

Avertissement: dans tout ce qui précède, Je ne dis rien sur le fait de savoir si le cryptage des Cookies aide à fournir les caractéristiques de sécurité que vous essayez d'atteindre. Habituellement, lorsque le chiffrement est nécessaire, vous avez besoin à la fois de chiffrement et d'intégrité, puis vous devez utiliser un mode de chiffrement et d'intégrité combiné. Recherche de GCM et CCM. De plus, le cryptage des cookies est surtout bon pour un le but, qui est d'éviter le coût de stockage côté serveur un peu de données spécifiques à l'utilisateur. Si vous voulez crypter un cookie pour autre chose, par exemple pour authentifier un utilisateur valide, alors vous le faites mal: le cryptage n'est pas le bon outil pour cela.

45
répondu Thomas Pornin 2017-12-01 12:58:03

Je n'ai pas de réponse directe à votre question, mais quelques choses à ajouter.

Tout d'abord, crypter le cookie n'a pas de sens pour moi. Si vous voulez la confidentialité de vos données, vous ne devriez pas les stocker dans un cookie de toute façon. Si vous voulez de l'intégrité (c'est à dire pas possible d'altérer le contenu du cookie), vous devez utiliser un hachage à clé HMAC (par exemple).

Une autre note est de Ne jamais Utiliser un IV qui est tout 0 juste pour plus de commodité.

IV sont égaux en taille avec de votre bloc. Dans le cas de AES-128, la taille de bloc est 128, la taille de clé est 128 et donc L'IV est 128 bits.

La meilleure façon de le faire est de créer une clé AES aléatoire et de l'utiliser comme IV. cette IV aléatoire peut être publique tant qu'elle n'est pas réutilisée dans les chiffrements suivants avec la même clé

Modifier :

Vous pouvez regarder cette page wiki pour plus d'informations sur le mode à utiliser. Cependant, n'utilisez jamais ECB sauf si vous êtes sûr de l'utiliser. Et même alors,, vérifiez avec un expert. CBC est pour autant que je sache le plus sûr (avec PCBC).

Http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation

4
répondu Henri 2012-10-14 11:35:17

Si vous ne faites pas l'IV aléatoire (c'est-à-dire que vous utilisez un groupe de nombres répétitifs), il sera plus facile de comprendre la clé si le cookie commence toujours par le même texte clair.

La taille IV pour AES-128 est de 128 bits. IIRC, le IV est de la même taille que le bloc de chiffrement. 128 bits est de 16 octets. 32 octets si vous le stockez en tant que chaîne hexadécimale ASCII. Est-ce vraiment trop? 32 octets en ce jour et l'âge est pas beaucoup du tout...

2
répondu Jörgen Sigvardsson 2011-01-05 20:09:31

Inclure un grand nombre aléatoire avec le cookie. Un nombre de 64 ou 128 bits est probablement assez grand. Il doit être assez grand pour qu'il soit très difficile d'obtenir des doublons. Assurez-vous de mettre suffisamment d'entropie dans ce numéro. N'utilisez pas simplement gettime (). Si vous avez accès à CRNG, utilisez-le ici.

Stockez une clé maître 256 bits avec votre application. Utilisez SHA256 pour dériver vos informations clés. Encore une fois, utilisez un CRNG pour cela.

$keyblob = sha256( concat("aeskeyid", $masterkey , $randomnumberwithcookie ) )
$aeskey = $keyblob[0..15]
$aesiv = $keyblob[16..31]

, Vous pouvez également dériver une clé pour un HMAC.

$mackeyblob = sha256( concat("hmackeyid", $masterkey , $randomnumberwithcookie ) )

Alternativement, vous pouvez combiner les deux opérations de hachage ci-dessus en une seule en utilisant SHA512.

$keyblob = sha512( concat("randomkeyid", $masterkey , $randomnumberwithcookie ) )
$aeskey = $keyblob[0..15]
$aesiv = $keyblob[16..31]
$hmackey = $keyblob[32..63] 
0
répondu Lunatic Experimentalist 2011-01-06 01:23:04

Il est possible d'éviter l'IV aléatoire en utilisant CBC et en stockant le HMAC devant le message. L'utilisation d'une constante IV choisie au hasard est ok. Mais vous devez être sûr que les messages sont tous différents.

C'est le cas lorsque le message chiffré est toujours différent. Une clé de licence avec un numéro de série correspondrait à ce critère. Un cookie avec un id utilisateur ou un ID de session le correspondrait également.

Vous pouvez utiliser CBC avec une constante aléatoire IV si vous stockez le hmac devant le message. Le hachage va cumuler toutes les variations réparties dans le message dans le premier bloc. Vous pouvez également ajouter quelques octets aléatoires ou de préférence un numéro de série, si vous pouvez vous assurer qu'il soit unique ou non réutilisés dans un temps très long.

Ne pensez même pas à utiliser CTR avec une constante IV.

0
répondu chmike 2017-08-27 08:37:54