2009-06-05 25 views
32

Este es el ejemplo que he ejecutado. Tiene el mismo Modo, Relleno, Tamaño de bloque, Tamaño de tecla. Estoy usando el mismo vector init, clave y datos.¿Por qué RijndaelManaged y AesCryptoServiceProvider devuelven resultados diferentes?

Uso de la RijndaelManaged produce un valor cifrado 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

Uso de la AesCryptoServiceProvider produce un valor cifrado 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 he perdido algo.

Actualización: Resulta que AesManaged arrojará un CryptographicException ("El modo de cifrado especificado no es válido para este algoritmo") si intenta establecer el CipherMode a 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.

+0

Esta pregunta salió de la discusión de: http://stackoverflow.com/questions/939040/when-will-c-aes-algorithm-be-fips-compliant –

Respuesta

40

respuesta de Microsoft:

RijndaelManaged clase y AesCryptoServiceProvider clase son dos implementaciones diferentes. RijndaelManaged clase es un tipo de implementación de algoritmo Rijndael en .NET Framework, lo que no fue validado bajo el NIST (Instituto Nacional de Estándares y Tecnología) módulo criptográfico programa de validación de (CMVP).

Sin embargo, AesCryptoServiceProvider clase llama la API de Windows Crypto, que utiliza rsaenh.dll, y ha sido validado por NIST en CMVP. Aunque el algoritmo de Rijndael fue el ganador de la competencia NIST para seleccionar el algoritmo que se convertiría en AES, existen algunas diferencias entre Rijndael y AES oficial. Por lo tanto, clase RijndaelManaged y AesCryptoServiceProvider clase tienen diferencias sutiles en la implementación.

Además, RijndaelManaged clase no puede proporcionar una aplicación equivalente con AES. Hay otra clase implementada en .net framework, AesManaged class. Esta clase acaba de envolver RijndaelManaged clase con un tamaño de bloque fijo y recuento de iteraciones para lograr el estándar AES . Sin embargo, no admite el tamaño de realimentación, especialmente cuando el modo está configurado como CFB u OFB, se lanzará el CryptographicException.

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

AesManaged Class y AesManaged.Mode Property

Si usted quiere recoger estándar AES algoritmo de seguridad en su aplicación , se recomienda utilizar la clase AesCryptoServiceProvider. Si quiere mezclar la clase RijndaelManged clase y AesCryptoServiceProvider en su aplicación, se sugiere utilizar el modo CBC en lugar del modo CFB en su programa , desde la implementación de el modo CBC en ambas clases es el misma.

6

Creo que tiene que ver con el CipherMode.CFB. Ver this post describir AesManaged:

AesManaged es en realidad sólo un envoltorio alrededor RinjdaelManaged con algo de código añade para asegurarse de que no lo hace configuración del algoritmo para operar de una manera compatible no AES. Por ejemplo, AesManaged no le permite cambiar el tamaño del bloque. (También va a no permitir el uso del modo CFB y OFB debido a la forma en que RijndaelManaged funciona con esos modos ).

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

+0

Sí, algoritmo VHDL que compramos para interactuar con el software solo es compatible con el modo CFB. – SwDevMan81

+0

Supongo que AesCryptoServiceProvider es el que funciona con su cliente? –

+0

Sí, según la otra discusión, es la versión compatible con FIPS que es lo que el cliente quiere – SwDevMan81

1
información

adición de this post dice:

En esencia, si desea utilizar RijndaelManaged como AES que necesita para asegurarse de que:
1) El tamaño del bloque se establece en 128 bits
2) Usted es no está utilizando el modo CFB, o si el tamaño de la retroalimentación también es de 128 bits

Ok, excelente. Agregué mEncryptionType.FeedbackSize = 128; a mi ejemplo anterior y me sale 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 

¿Hay algo malo en la DLL System.Core que molestaría apoyar esto, o tengo que cambiar algo más?

En una nota lateral, 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)?

+0

Si puede hacer que funcione con 8, tomaría eso y ejecutaría :-) –

+0

Ojalá pudiera, el algoritmo VHDL de nuevo solo parece ser compatible con 128 para FeedbackSize :( – SwDevMan81

+0

Tal vez el FeedbackSize se expresa en bytes, no en bits. 8 * 16 = 128. – Cheeso

Cuestiones relacionadas