27 votes

Pourquoi RijndaelManaged et AesCryptoServiceProvider renvoient-ils des résultats différents ?

Voici l'exemple que j'ai exécuté. Il a les mêmes Mode, Padding, BlockSize, KeySize. J'utilise les mêmes init vector, key et data.

L'utilisation du RijndaelManaged produit une valeur cryptée de : 0x8d,0x81,0x27,0xc6,0x3c,0xe2,0x53,0x2f,0x35,0x78,0x90,0xc2,0x2e,0x3b,0x8a,0x61, 0x41,0x47,0xd6,0xd0,0xff,0x92,0x72,0x3d,0xc6,0x16,0x2b,0xd8,0xb5,0xd9,0x12,0x85

L'utilisation du AesCryptoServiceProvider produit une valeur cryptée de : 0x8d,0x9f,0x6e,0x99,0xe9,0x54,0x8b,0x12,0xa9,0x88,0x1a,0x3d,0x65,0x23,0x9c,0x4e, 0x18,0x5a,0x89,0x31,0xf5,0x75,0xc5,0x9e,0x0d,0x43,0xe9,0x86,0xd4,0xf3,0x64,0x3a

Voici le code que j'ai utilisé pour générer ces résultats

   public partial class AesTest
   {
      private SymmetricAlgorithm mEncryptionType;
      private byte[] mPrivateKey;
      private byte[] mInitializationVector;
      private byte[] mData;

      public AesTest()
      {
         mPrivateKey = new byte[32] 
         { 
            0x22, 0x22, 0x22, 0x22, 
            0x22, 0x22, 0x22, 0x22, 
            0x22, 0x22, 0x22, 0x22, 
            0x22, 0x22, 0x22, 0x22,
            0x22, 0x22, 0x22, 0x22, 
            0x22, 0x22, 0x22, 0x22, 
            0x22, 0x22, 0x22, 0x22, 
            0x22, 0x22, 0x22, 0x22
         };

         mInitializationVector = new byte[16]
         { 
            0x33, 0x33, 0x33, 0x33,
            0x33, 0x33, 0x33, 0x33,
            0x33, 0x33, 0x33, 0x33,
            0x33, 0x33, 0x33, 0x33
         };

         mData = new byte[16]
         {
            0x44, 0x44, 0x44, 0x44,
            0x44, 0x44, 0x44, 0x44,
            0x44, 0x44, 0x44, 0x44,
            0x44, 0x44, 0x44, 0x44
         };

         mEncryptionType = new RijndaelManaged();
         mEncryptionType.Mode = CipherMode.CFB;
         mEncryptionType.Padding = PaddingMode.PKCS7;
         mEncryptionType.BlockSize = 128;
         mEncryptionType.KeySize = 256;

         byte[] rij_encrypted_data = Encrypt(mData);

         mEncryptionType = new AesCryptoServiceProvider();
         mEncryptionType.Mode = CipherMode.CFB;
         mEncryptionType.Padding = PaddingMode.PKCS7;
         mEncryptionType.BlockSize = 128;
         mEncryptionType.KeySize = 256;

         byte[] aes_encrypted_data = Encrypt(mData);
      }

      public virtual byte[] Encrypt(byte[] unencryptedData)
      {
         return TransformData(unencryptedData, mEncryptionType.CreateEncryptor(mPrivateKey, mInitializationVector));
      }

      private byte[] TransformData(byte[] dataToTransform, ICryptoTransform cryptoTransform)
      {
         byte[] result = new byte[0];
         if (dataToTransform != null && cryptoTransform != null && dataToTransform.Length > 0)
         {
            // Create the memory stream to store the results
            MemoryStream mem_stream = new MemoryStream();
            // Create the crypto stream to do the transformation
            CryptoStream crypto_stream = new CryptoStream(mem_stream, cryptoTransform, CryptoStreamMode.Write);
            // bytes are transformed on a write
            crypto_stream.Write(dataToTransform, 0, dataToTransform.Length);
            // Flush the final block
            crypto_stream.FlushFinalBlock();
            // Convert the transformed memory stream back to a byte array
            result = mem_stream.ToArray();
            // Close the streams
            mem_stream.Close();
            crypto_stream.Close();
         }
         return result;
      }
   }

Je suppose que je me demande juste si j'ai manqué quelque chose.

Mise à jour : Il s'avère que AesManaged lancera une CryptographicException ("Le mode de chiffrement spécifié n'est pas valide pour cet algorithme") si vous essayez de définir le CipherMode sur CFB. Je pense que le AesCryptoServiceProvider devrait faire la même chose, mais ce n'est pas le cas. C'est drôle que la classe certifiée FIPS permette des modes de chiffrement invalides.

30voto

makerofthings7 Points 10028

Réponse de Microsoft :

RijndaelManaged et AesCryptoServiceProvider sont deux implémentations différentes. RijndaelManaged La classe Rijndael est une sorte de implémentation de l'algorithme Rijndael dans le cadre de .net, qui n'a pas été validé par le NIST (National Institute of Standards and Technology) Cryptographic Module Validation Program (CMVP). Program (CMVP).

Cependant, AesCryptoServiceProvider appelle l'API Crypto de Windows, qui utilise RSAENH.DLL, et a été validé par le NIST dans le cadre du CMVP. Bien que l'algorithme Rijndael ait été le gagnant de la compétition du NIST compétition du NIST pour sélectionner l'algorithme qui deviendrait AES, il y a quelques différences entre Rijndael et l'algorithme l'AES officiel. Par conséquent, La classe RijndaelManaged et AesCryptoServiceProvider classe ont des différences subtiles au niveau de la mise en œuvre.

En outre, RijndaelManaged classe ne peut pas fournir une implémentation équivalente équivalente avec AES. Il existe une autre classe implémentée dans .net framework, AesManaged classe. Cette classe ne fait qu'envelopper RijndaelManaged avec une taille de bloc et un nombre d'itérations d'itération pour atteindre la norme AES pour atteindre la norme AES. Cependant, il ne supporte pas la taille de la rétroaction, en particulier, lorsque le mode est défini comme CFB ou OFB, la taille de rétroaction n'est pas prise en charge. CryptographicException seront lancées.

Pour plus d'informations, veuillez vous référer aux les documents MSDN suivants.

Classe AesManaged et Propriété AesManaged.Mode

Si vous voulez prendre l'AES standard comme algorithme de sécurité dans votre application, nous vous recommandons d'utiliser l'option AesCryptoServiceProvider classe. Si vous voulez mélanger les RijndaelManged classe et AesCryptoServiceProvider dans votre application, nous vous suggérons d'utiliser le mode CBC au lieu du mode CFB dans votre programme programme, puisque l'implémentation du mode mode CBC dans les deux classes est même.

6voto

Jeff Moser Points 11452

Je pense que cela a à voir avec le CipherMode.CFB. Voir ce poste décrivant AesManaged :

AesManaged est en fait juste une enveloppe autour de RinjdaelManaged avec un peu de code ajouté pour s'assurer que vous ne configurer l'algorithme pour qu'il fonctionne dans un manière non compatible avec AES. Par exemple, AesManaged ne vous permet pas de changer la taille du bloc. (Il interdit également interdit l'utilisation du mode CFB et OFB à cause de la façon dont RijndaelManaged fonctionne avec ces modes). modes).

Notez que si vous utilisez CipherMode.ECB ou CipherMode.CBC, vous obtiendrez des résultats identiques. Y a-t-il une raison pour laquelle vous avez besoin de CFB et non de CBC ?

0voto

SwDevMan81 Points 22634

Informations complémentaires de ce poste dit :

Essentiellement, si vous voulez utiliser RijndaelManaged comme AES vous devez vous assurer que :
1) La taille du bloc est fixée à 128 bits.
2) Vous n'utilisez pas le mode CFB ou, si vous le faites, la taille du retour d'information est également de 128 bits.

Ok, super. J'ai ajouté mEncryptionType.FeedbackSize = 128 ; à mon exemple ci-dessus et j'obtiens un CryptographicExecption :

System.Security.Cryptography.CryptographicException was unhandled
  Message="Bad Data.\\r\\n"
  Source="System.Core"
  StackTrace:
       at System.Security.Cryptography.CapiNative.SetKeyParameter(SafeCapiKeyHandle key, KeyParameter parameter, Byte\[\] value)
       at System.Security.Cryptography.CapiNative.SetKeyParameter(SafeCapiKeyHandle key, KeyParameter parameter, Int32 value)
       at System.Security.Cryptography.CapiSymmetricAlgorithm.SetupKey(SafeCapiKeyHandle key, Byte\[\] iv, CipherMode cipherMode, Int32 feedbackSize)
       at System.Security.Cryptography.CapiSymmetricAlgorithm..ctor(Int32 blockSize, Int32 feedbackSize, SafeCspHandle provider, SafeCapiKeyHandle key, Byte\[\] iv, CipherMode cipherMode, PaddingMode paddingMode, EncryptionMode encryptionMode)
       at System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor(SafeCapiKeyHandle key, Byte\[\] iv)
       at System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor(Byte\[\] key, Byte\[\] iv)
       at AESTest.Form1.Encrypt(Byte\[\] unencryptedData) in C:\\Documents and Settings\\nschoonmaker\\My Documents\\Visual Studio 2005\\Projects\\AESTest\\AESTest\\Form1.cs:line 79
       at AESTest.Form1..ctor() in C:\\Documents and Settings\\nschoonmaker\\My Documents\\Visual Studio 2005\\Projects\\AESTest\\AESTest\\Form1.cs:line 73
       at AESTest.Program.Main() in C:\\Documents and Settings\\nschoonmaker\\My Documents\\Visual Studio 2005\\Projects\\AESTest\\AESTest\\Program.cs:line 17

Y a-t-il un problème avec la dll System.Core qui ne supporte pas cela, ou dois-je changer quelque chose d'autre ?

D'ailleurs, si je modifie la taille du feedback à 8 pour les deux, cela semble fonctionner ! Même pour le mode CFB. Je suppose donc que ma prochaine question est la suivante : comment faire pour que 128 fonctionne (et j'espère que cela mettra fin à cette question) ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X