válido tiene tamaño para funciona este especificada encrypt como clave algoritmo c# .net encryption rijndaelmanaged aescryptoserviceprovider

c# - funciona - la clave especificada no tiene el tamaño válido para este algoritmo



¿Por qué RijndaelManaged y AesCryptoServiceProvider devuelven resultados diferentes? (3)

Creo que tiene que ver con el CipherMode.CFB. Vea esta publicación que describe a AesManaged :

AesManaged es en realidad solo una envoltura alrededor de Rinjdael administrado con algún código agregado para asegurarse de que no configure el algoritmo para operar de una manera no compatible con AES. Por ejemplo, AesManaged no le permite cambiar el tamaño del bloque. (También impedirá el uso del modo CFB y OFB debido a la forma en que RijndaelManaged funciona con esos 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?

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

El uso de AesCryptoServiceProvider produce un valor encriptado de: 0x8d, 0x9f, 0x6e, 0x99, 0x9,0x54,0x8b, 0x12, 0xa9, 0xx0,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.

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


La 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 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 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)?


Respuesta de Microsoft:

RijndaelManaged clase RijndaelManaged y la clase AesCryptoServiceProvider son dos implementaciones diferentes. RijndaelManaged clase RijndaelManaged es un tipo de implementación del algoritmo de Rijndael en .NET Framework, que no fue validado por el Programa de Validación de Módulos Criptográficos (CMVP) del NIST (Instituto Nacional de Estándares y Tecnología).

Sin embargo, la clase AesCryptoServiceProvider llama a Windows Crypto API, que usa RSAENH.DLL, y ha sido validado por NIST en CMVP. Aunque el algoritmo 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, la clase RijndaelManaged y la clase AesCryptoServiceProvider tienen diferencias sutiles en la implementación.

Además, la clase RijndaelManaged no puede proporcionar una implementación equivalente con AES. Hay otra clase implementada en el framework .net, clase AesManaged . Esta clase simplemente envolvió la clase RijndaelManaged con un tamaño de bloque fijo y recuento de iteraciones para alcanzar el estándar AES. Sin embargo, no es compatible con el tamaño de retroalimentación, especialmente cuando el modo se configura como CFB o OFB, se lanzará la CryptographicException .

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

AesManaged y propiedad AesManaged.Mode

Si desea obtener el estándar AES como algoritmo de seguridad en su aplicación, le recomendamos utilizar la clase AesCryptoServiceProvider . Si desea mezclar la clase RijndaelManged y la clase AesCryptoServiceProvider en su aplicación, sugerimos utilizar el modo CBC en lugar del modo CFB en su programa, ya que la implementación del modo CBC en ambas clases es la misma.