Pregunta ¿Por qué RijndaelManaged y AesCryptoServiceProvider devuelven resultados diferentes?


Aquí está el ejemplo que he corrido. Tiene el mismo Modo, Relleno, Tamaño de bloque, Tamaño de tecla. Estoy usando el mismo vector init, clave y datos.

El uso de RijndaelManaged produce un valor encriptado 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

El uso de AesCryptoServiceProvider produce un valor encriptado 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

Aquí está el código que utilicé para generar estos resultados


   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;
      }
   }

Supongo que me pregunto si me perdí algo.

 Actualizar:  Resulta que AesManaged arrojará una CryptographicException ("El modo de cifrado especificado no es válido para este algoritmo") si intenta configurar CipherMode en CFB. Siento que el AesCryptoServiceProvider debería hacer lo mismo, pero no es así. Parece divertido que la clase certificada por FIPS permita modos de cifrado no válidos.


32
2018-06-05 18:33


origen


Respuestas:


Respuesta de Microsoft:

RijndaelManaged clase y   AesCryptoServiceProvider clase son dos  diferentes implementaciones.   RijndaelManaged clase es un tipo de  implementación del algoritmo Rijndael  en .NET Framework, que no era  validado bajo NIST (National  Instituto de Estándares y Tecnología)  Validación del Módulo Criptográfico  Programa (CMVP).

Sin embargo,   AesCryptoServiceProvider llamadas de clase  la API de Windows Crypto, que usa  RSAENH.DLL, y ha sido validado por  NIST en CMVP. Aunque Rijndael  Algoritmo fue el ganador del NIST  competencia para seleccionar el algoritmo  eso se convertiría en AES, hay algunos  diferencias entre Rijndael y  AES oficial. Por lo tanto,  Clase administrada Rijndael y   AesCryptoServiceProvider clase tiene  sutiles diferencias en la implementación.

En adición, RijndaelManaged clase  no puede proporcionar un equivalente  implementación con AES. Ahi esta  otra clase implementada en .net  marco de referencia, AesManaged clase. Esta  clase solo envuelta RijndaelManaged  clase con un tamaño de bloque fijo y  recuento de iteraciones para lograr el AES  estándar. Sin embargo, no es compatible  el tamaño de la retroalimentación, especialmente cuando  el modo está configurado como CFB o OFB, el   CryptographicException será arrojado.

Para obtener más información, consulte  los siguientes documentos de MSDN.

Clase AesManaged        y Propiedad AesManaged.Mode 

Si desea recoger AES estándar como  algoritmo de seguridad en su  aplicación, recomendamos usar   AesCryptoServiceProvider clase. Si tu  quiero mezclar el RijndaelManged clase  y AesCryptoServiceProvider clase en  su aplicación, sugerimos usar CBC  modo en lugar de modo CFB en su  programa, desde la implementación de  el modo CBC en ambas clases es el  mismo.


40
2018-02-01 14:44



Creo que tiene que ver con el CipherMode.CFB. Ver esta publicación describiendo AesManaged:

AesManaged es en realidad solo una envoltura   alrededor de Rinjdael administrado con algún código   agregado para asegurarse de que no   configurar el algoritmo para operar en una   no compatible con AES. Por ejemplo,   AesManaged no te permite   cambiar el tamaño del bloque. (También lo hará   no permitir el uso del modo CFB y OFB   debido a la forma en que   RijndaelManaged funciona con aquellos   modos).

Tenga en cuenta que si usa CipherMode.ECB o CipherMode.CBC, verá resultados idénticos. ¿Alguna razón por la que necesita CFB y no CBC?


6
2018-06-05 18:46



Información adicional de esta publicación dice:

Básicamente, si desea utilizar RijndaelManaged como AES, debe asegurarse de que:
1) El tamaño del bloque se establece en 128 bits
2) No está utilizando el modo CFB, o si el tamaño de la retroalimentación también es de 128 bits

Vale genial. Agregué mEncryptionType.FeedbackSize = 128; a mi ejemplo anterior y obtengo un CryptographicExecption:

System.Security.Cryptography.CryptographicException no fue manejado
  Mensaje = "Datos incorrectos. \ R \ n"
  Fuente = "System.Core"
  StackTrace:
       en System.Security.Cryptography.CapiNative.SetKeyParameter (clave SafeCapiKeyHandle, parámetro KeyParameter, valor Byte [])
       en System.Security.Cryptography.CapiNative.SetKeyParameter (clave SafeCapiKeyHandle, parámetro KeyParameter, valor Int32)
       en System.Security.Cryptography.CapiSymmetricAlgorithm.SetupKey (SafeCapiKeyHandle key, Byte [] iv, CipherMode cipherMode, Int32 feedbackSize)
       en System.Security.Cryptography.CapiSymmetricAlgorithm..ctor (Int32 blockSize, Int32 feedbackSize, SafeCspHandle provider, SafeCapiKeyHandle key, Byte [] iv, CipherMode cipherMode, PaddingMode paddingMode, EncryptionMode encryptionMode)
       en System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor (SafeCapiKeyHandle key, Byte [] iv)
       en System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor (tecla Byte [], Byte [] iv)
       en AESTest.Form1.Encrypt (Byte [] unencryptedData) en C: \ Documents and Settings \ nschoonmaker \ Mis documentos \ Visual Studio 2005 \ Projects \ AESTest \ AESTest \ Form1.cs: línea 79
       en AESTest.Form1..ctor () en C: \ Documents and Settings \ nschoonmaker \ Mis documentos \ Visual Studio 2005 \ Projects \ AESTest \ AESTest \ Form1.cs: línea 73
       en AESTest.Program.Main () en C: \ Documents and Settings \ nschoonmaker \ Mis documentos \ Visual Studio 2005 \ Projects \ AESTest \ AESTest \ Program.cs: línea 17

¿Hay algún problema con System.Core dll que no sea compatible con esto, o tengo que cambiar algo más?

En una nota al margen, si cambio el FeedbackSize a 8 para ambos, ¡parece que funciona! Incluso para el modo CFB. Así que supongo que mi próxima pregunta es, ¿cómo puedo hacer que funcione 128 (y espero que esto ponga fin a esta pregunta)?


1
2018-06-08 23:05