Perché RijndaelManaged e AesCryptoServiceProvider restituiscono risultati diversi?

Ecco l’esempio che ho eseguito. Ha la stessa modalità, Padding, BlockSize, KeySize. Sto usando lo stesso vettore, la chiave e i dati di init.

L’utilizzo di RijndaelManaged produce un valore crittografato di: 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’utilizzo di AesCryptoServiceProvider produce un valore crittografato di: 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

Ecco il codice che ho usato per generare questi risultati

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 transformsd on a write crypto_stream.Write(dataToTransform, 0, dataToTransform.Length); // Flush the final block crypto_stream.FlushFinalBlock(); // Convert the transformsd memory stream back to a byte array result = mem_stream.ToArray(); // Close the streams mem_stream.Close(); crypto_stream.Close(); } return result; } } 

Immagino che mi stia chiedendo se mi sia sfuggito qualcosa.

    Aggiornamento: Si scopre che AesManaged genererà una CryptographicException (“La modalità di crittografia specificata non è valida per questo algoritmo”) se si tenta di impostare CipherMode su CFB. Sento che AesCryptoServiceProvider dovrebbe fare lo stesso, ma non lo fa. Sembra strano che la class FIPS Certified permetta modalità di cifratura non valide.

    Risposta di Microsoft:

    RijndaelManaged classi RijndaelManaged e AesCryptoServiceProvider sono due diverse implementazioni. RijndaelManaged class RijndaelManaged è una sorta di implementazione dell’algoritmo di Rijndael in .net framework, che non è stato convalidato dal programma di validazione del modulo crittografico (CMVP) del NIST (National Institute of Standards and Technology).

    Tuttavia, la class AesCryptoServiceProvider chiama l’API Crypto di Windows, che utilizza RSAENH.DLL ed è stata convalidata da NIST in CMVP. Sebbene l’algoritmo di Rijndael fosse il vincitore della competizione NIST per selezionare l’algoritmo che sarebbe diventato AES, ci sono alcune differenze tra Rijndael e AES ufficiale. Pertanto, le classi RijndaelManaged e AesCryptoServiceProvider presentano sottili differenze nell’implementazione.

    Inoltre, la class RijndaelManaged non può fornire un’implementazione equivalente con AES. C’è un’altra class implementata in .net framework, class AesManaged . Questa class ha appena completato la class RijndaelManaged con una dimensione di blocco fissa e un conteggio di iterazione per raggiungere lo standard AES. Tuttavia, non supporta le dimensioni del feedback, in particolare, quando la modalità è impostata come CFB o OFB, verrà lanciata CryptographicException .

    Per ulteriori informazioni, consultare i seguenti documenti MSDN.

    Proprietà AesManaged e AesManaged.Mode

    Se si desidera AesCryptoServiceProvider AES standard come algoritmo di sicurezza nell’applicazione, si consiglia di utilizzare la class AesCryptoServiceProvider . Se si desidera mescolare la class RijndaelManged e la class AesCryptoServiceProvider nella propria applicazione, si consiglia di utilizzare la modalità CBC anziché la modalità CFB nel programma, poiché l’implementazione della modalità CBC in entrambe le classi è la stessa.

    Penso che abbia a che fare con CipherMode.CFB. Vedi questo post che descrive AesManaged :

    AesManaged è in realtà solo un wrapper di RinjdaelManaged con qualche codice aggiunto per essere sicuro di non configurare l’algoritmo in modo che funzioni in un modo non compatibile con AES. Ad esempio, AesManaged non ti consente di modificare le dimensioni del blocco. (Disabiliterà anche l’uso della modalità CFB e OFB a causa del modo in cui RijndaelManaged funziona con tali modalità).

    Nota che se usi CipherMode.ECB o CipherMode.CBC, vedrai risultati identici. Qualche ragione per cui hai bisogno di CFB e non di CBC?

    Le informazioni aggiuntive di questo post dicono:

    In sostanza, se si desidera utilizzare RijndaelManaged come AES è necessario assicurarsi che:
    1) La dimensione del blocco è impostata su 128 bit
    2) Non si sta utilizzando la modalità CFB, o se si è la dimensione di feedback è anche 128 bit

    Ok fantastico. Ho aggiunto mEncryptionType.FeedbackSize = 128; al mio esempio precedente e ottengo un CryptographicExecption:

     System.Security.Cryptography.CryptographicException non è stato gestito
       Messaggio = "Dati non validi. \ R \ n"
       Source = "System.Core"
       StackTrace:
            a System.Security.Cryptography.CapiNative.SetKeyParameter (chiave SafeCapiKeyHandle, parametro KeyParameter, valore Byte [])
            a System.Security.Cryptography.CapiNative.SetKeyParameter (chiave SafeCapiKeyHandle, parametro KeyParameter, valore Int32)
            a System.Security.Cryptography.CapiSymmetricAlgorithm.SetupKey (chiave SafeCapiKeyHandle, Byte [] iv, CipherMode cipherMode, Int32 feedbackSize)
            a System.Security.Cryptography.CapiSymmetricAlgorithm..ctor (Int32 blockSize, Int32 feedbackSize, SafeCspHandle provider, SafeCapiKeyHandle key, Byte [] iv, CipherMode cipherMode, PaddingMode paddingMode, EncryptionMode encryptionMode)
            a System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor (chiave SafeCapiKeyHandle, Byte [] iv)
            a System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor (Byte [] key, Byte [] iv)
            su AESTest.Form1.Encrypt (Byte [] unencryptedData) in C: \ Documents and Settings \ nschoonmaker \ Documenti \ Visual Studio 2005 \ Projects \ AESTest \ AESTest \ Form1.cs: riga 79
            in AESTest.Form1..ctor () in C: \ Documents and Settings \ nschoonmaker \ Documenti \ Visual Studio 2005 \ Projects \ AESTest \ AESTest \ Form1.cs: riga 73
            su AESTest.Program.Main () in C: \ Documents and Settings \ nschoonmaker \ Documenti \ Visual Studio 2005 \ Projects \ AESTest \ AESTest \ Program.cs: riga 17
    

    C’è qualcosa di sbagliato nella dll System.Core che non supporta questo, o devo cambiare qualcos’altro?

    Una nota a margine, se cambio FeedbackSize su 8 per entrambi, sembra funzionare! Anche per la modalità CFB. Quindi immagino che la mia prossima domanda sia: come faccio a far funzionare 128 (e spero che questo metta fine a questa domanda)?