web-dev-qa-db-fra.com

Cryptage utilisant AES-256, puis-je utiliser 256 bits IV?

Je veux chiffrer des données en utilisant AES en Java et je veux initialiser le chiffrement avec le vecteur d'initialisation. Puis-je utiliser 256 bits IV? Ou dois-je utiliser uniquement 128 bits IV?

19
Hakim

Le IV dépend du mode de fonctionnement . Pour la plupart des modes (par exemple CBC), l'IV doit avoir la même longueur que le bloc. AES utilise des blocs de 128 bits, donc un IV de 128 bits. Notez que AES-256 utilise une clé de 256 bits (d'où le nom), mais toujours avec des blocs de 128 bits.

AES a été choisi comme sous-ensemble de la famille de chiffrement par blocs connue sous le nom de Rijndael . Cette famille comprend pas moins de 15 variantes, pour trois tailles de bloc possibles (128, 192 et 256 bits) et cinq tailles de clé possibles (128, 160, 192, 224 et 256 bits). AES , tel que normalisé par le NIST, ne comprend que trois variantes, toutes avec des blocs de 128 bits, et avec des clés de 128, 192 ou 256 bits.

Pour confondre davantage les choses, certains cadres logiciels se sont trompés; par exemple. PHP utilise "MCRYPT_RIJNDAEL_128" pour désigner Rijndael avec des clés de 128 bits et des blocs de 128 bits (c'est-à-dire la même chose que AES-128), et "MCRYPT_RIJNDAEL_256" pour Rijndael avec des clés de 256 bits et Blocs de 256 bits (c'est-à-dire pas une des variantes AES, et en particulier pas du tout AES-256).

41
Thomas Pornin

Vous devez utiliser un IV 128 bits. Pour CBC, le mode IV doit correspondre à la taille du bloc, qui est toujours de 128 bits pour AES.

Rijndael, le candidat AES gagnant, est défini pour les blocs de 128 et 256 bits, mais seuls les blocs de 128 bits ont été standardisés en AES. Certaines bibliothèques prennent en charge Rijndael avec des blocs de 256 bits, mais vous n'utilisez plus AES.

Si vous avez besoin d'un IV plus long pour une raison quelconque, vous pouvez utiliser un KDF ou un hachage pour transformer la clé d'origine et le IV en clé que vous utilisez réellement pour AES.

6
CodesInChaos

La gestion IV dans Java dépend du fournisseur de chiffrement utilisé. Le fournisseur Sun fourni avec les runtimes Oracle est plutôt strict; il requiert que l'IV soit de la même taille que la taille de bloc pour la plupart modes de fonctionnement . Cela est vrai même pour le mode CTR où vous vous attendiez à ce que la fourniture d'un nonce - les premiers octets de l'IV - soit suffisante. Bien entendu, le mode ECB ne nécessite pas de IV, il lancera donc une exception si vous essayez d'en fournir une.

La taille de bloc d'AES est toujours de 128 bits, donc un IV de 256 bits n'est pas possible pour la plupart des modes de fonctionnement. Comme déjà indiqué dans quelques réponses, Rijndael peut être configuré avec une taille de bloc de 256 bits, mais Rijndael n'est pas inclus dans le runtime standard. Vous auriez besoin d'un fournisseur ou d'une bibliothèque supplémentaire comme Bouncy Castle pour utiliser Rijndael. Le chiffrement par blocs AES n'utilise pas un IV en entrée, c'est pourquoi la fourniture d'un IV pour le mode ECB échoue. Certaines autres langues/runtimes ignorent simplement l'IV pour la BCE

Maintenant, il y a un chiffre qui vous permet de spécifier un IV 256 bits (ou en fait: nonce) et c'est GCM. GCM fonctionne mieux avec un nonce de 12 octets. GCM convertit les données - y compris le nonce - en un compteur 128 bits pour le mode CTR en interne.

Notez que l'augmentation de la taille IV ne rend pas automatiquement l'algorithme plus sûr. Si vous avez une entrée 256 bits pour un IV, vous pouvez utiliser SHA-256 bits sur l'entrée et prendre à la place les 128 bits les plus à gauche.


Comme nous parlions de Java, voici du code, vous pouvez jouer avec la taille IV et essayer des algorithmes tels que "AES/CFB/NoPadding" toi même. Notez que les IV statiques utilisés dans le code sont uniquement à des fins de démonstration . CTR nécessite un IV unique, CBC nécessite un IV indiscernable de aléatoire à un attaquant.

SecretKey aesKey = new SecretKeySpec(new byte[256 / Byte.SIZE], "AES");
byte[] pt = "owlstead".getBytes(StandardCharsets.US_ASCII);

{
    // === CBC mode requires an IV of the same size as the block size
    Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
    // changing the IV size will result in an exception
    byte[] ivBytes = new byte[c.getBlockSize()];
    IvParameterSpec iv = new IvParameterSpec(ivBytes);
    c.init(Cipher.ENCRYPT_MODE, aesKey, iv);
    byte[] ct = c.doFinal(pt);
    System.out.println(Hex.toHexString(ct));
}

{
    // === CTR mode actually requires a complete IV in Java
    // Java (or actually, the Sun provider) requires a 128 bit IV instead of just a nonce
    Cipher c = Cipher.getInstance("AES/CTR/NoPadding");
    // changing the IV size will result in an exception
    byte[] ivBytes = new byte[c.getBlockSize()];
    IvParameterSpec iv = new IvParameterSpec(ivBytes);
    c.init(Cipher.ENCRYPT_MODE, aesKey, iv);
    byte[] ct = c.doFinal(pt);
    System.out.println(Hex.toHexString(ct));
}

{
    // === GCM mode can do it!
    Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
    byte[] ivBytes = new byte[256 / Byte.SIZE];
    GCMParameterSpec gcmSpecWithIV = new GCMParameterSpec(128, ivBytes);
    c.init(Cipher.ENCRYPT_MODE, aesKey, gcmSpecWithIV);
    byte[] ct = c.doFinal(pt);
    System.out.println(Hex.toHexString(ct));
}

{
    // ===  Java.security.InvalidAlgorithmParameterException: ECB mode cannot use IV
    Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
    byte[] ivBytes = new byte[c.getBlockSize()];
    IvParameterSpec iv = new IvParameterSpec(ivBytes);
    c.init(Cipher.ENCRYPT_MODE, aesKey, iv);
    byte[] ct = c.doFinal(pt);
    System.out.println(Hex.toHexString(ct));
}
5
Maarten Bodewes

Le but de l'IV est de "mélanger" un peu.

Sans cela, les messages avec le même premier bloc de texte en clair partageraient tous le même premier bloc de texte chiffré. Ce scénario n'est pas si rare, considérez les fichiers qui commencent par des déclarations standard sur leur type de fichier ou la façon dont SMTP utilise des choses comme RCPT TO :, MAIL FROM: etc comme éléments communs. 128 bits (la taille de bloc d'AES) est petit, donc ce genre de chose se produirait.

Il existe différents modes de fonctionnement, mais en utilisant CBC comme le plus simple (et peut-être toujours le plus commun?), Le texte chiffré d'un bloc est utilisé pour alimenter le suivant, c'est-à-dire que la sortie chiffrée (texte chiffré) faite à partir du premier bloc de texte en clair est utilisée. à XOR le texte en clair du bloc 2 (avant qu'il soit ensuite chiffré). Le texte chiffré de chaque bloc est utilisé pour XOR (OU exclusif) le texte en clair du bloc suivant, et donc le nom Cipher block [~ # ~] chaînage [~ # ~] . Le problème est que le premier bloc n'a pas de bloc à précéder ça (enfin à CBC quand même ...)

C'est là que le problème décrit en premier est un problème - les messages avec le même premier bloc de texte en clair partageraient tous le même premier bloc de texte chiffré si la même clé était utilisée pour les crypter.

Pour éviter ce problème, un IV (vecteur d'initialisation) est utilisé. C'est un bloc de matériel qui peut être utilisé pour XOR (OU exclusif) le tout premier bloc pour démarrer la chaîne. Le IV est envoyé avec le message, sinon il serait impossible de démarrer le décryptage.

Même en rechiffrant le même message encore et encore avec la même clé, le premier bloc crypté serait différent à chaque fois, et donc en enchaînant, le message crypté entier serait différent à chaque fois.

Si vous considérez ce qui est fait avec l'IV, dans mon exemple CBC, cela n'a aucun sens de discuter d'un IV de n'importe quelle taille supérieure ou inférieure à la taille de bloc de 128 bits, car c'est la taille du premier bloc dont vous avez besoin "mélanger" et à partir de là, vous utilisez le texte chiffré précédent pour l'enchaîner. (OK, ce n'est pas vrai pour tous les modes, certains IV peuvent avoir besoin d'être plus petits que le premier bloc, mais considérons simplement CBC pour l'instant). Donc, pour CBC, l'IV doit être le même que la taille de bloc, qui dans AES est toujours 128 bits (quelle que soit la taille de clé).

L'avantage pour la sécurité n'est pas autant compte tenu de la longueur de l'IV, ne pensez pas qu'un IV plus long doit signifier une meilleure sécurité, l'IV n'est pas la clé!

Le problème avec les IV est plus ce que/comment vous générez vos IV. Ils doivent être de bonne qualité (c'est-à-dire du matériel pseudo-aléatoire uniforme statistiquement sans rapport avec les IV précédemment utilisés), si vous avez un mauvais schéma de génération IV ou un mauvais calendrier clé, vous pouvez compromettre la sécurité, l'ouvrir potentiellement à la cryptanalyse basée sur des statistiques techniques.

Ce que je voudrais vraiment dire, c'est que la cryptographie est un peu compliquée :) et même faire la meilleure erreur intentionnelle a entraîné des conséquences catastrophiques. Certains plans par ailleurs bons ont été complètement ruinés par de petites erreurs de mise en œuvre. Rappelez-vous WEP pour personne sans fil?

Si vous ne comprenez pas pleinement et profondément tous les facteurs impliqués, veuillez vous en tenir aux normes et utiliser des bibliothèques bien utilisées (bien évaluées par les pairs) et des pratiques établies.

Essayer de faire quelque chose d'intelligent, même avec les meilleures intentions, est extrêmement dangereux à moins d'en comprendre toutes les conséquences. Ce que j'essaie de dire très poliment, c'est que si vous devez poser une question comme: quelle est la taille IV à utiliser, vous ne devriez pas essayer d'expérimenter comment mettre en œuvre, il suffit de s'en tenir aux valeurs standard.

Meilleurs voeux avec votre codage, profitez ...

2
TomH