web-dev-qa-db-ja.com

RijndaelManagedとAesCryptoServiceProviderが異なる結果を返すのはなぜですか?

これが私が実行した例です。これには、同じMode、Padding、BlockSize、KeySizeがあります。同じ初期化ベクトル、キー、データを使用しています。

RijndaelManagedを使用すると、次の暗号化された値が生成されます:0x8d、0x81,0x27,0xc6,0x3c、0xe2,0x53,0x2f、0x35,0x78,0x90,0xc2,0x2e、0x3b、0x8a、0x61、0x41,0x47,0x 、0x92,0x72,0x3d、0xc6,0x16,0x2b、0xd8,0xb5,0xd9,0x12,0x85

AesCryptoServiceProviderを使用すると、次の暗号化された値が生成されます:0x8d、0x9f、0x6e、0x99,0xe9,0x54,0x8b、0x12,0xa9,0x88,0x1a、0x3d、0x65,0x23,0x9c、0x4e、0x18,0x5 、0x75,0xc5,0x9e、0x0d、0x43,0xe9,0x86,0xd4,0xf3,0x64,0x3a

これらの結果を生成するために使用したコードは次のとおりです


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

私は何かを逃したのだろうかと思っているだけだと思います。

更新: CipherModeをCFBに設定しようとすると、 AesManaged がCryptographicException( "指定された暗号モードはこのアルゴリズムでは無効です")をスローすることがわかります。 AesCryptoServiceProvider も同じようにすべきだと思いますが、そうではありません。 FIPS認定クラスが無効な暗号モードを許可しているのはおかしいようです。

33
SwDevMan81

マイクロソフトからの回答:

RijndaelManagedクラスとAesCryptoServiceProviderクラスは2つの異なる実装です。 RijndaelManagedクラスは、.netフレームワークでのRijndaelアルゴリズムの一種の実装であり、NIST(米国国立標準技術研究所)暗号化モジュール検証プログラム(CMVP)では検証されていません。

ただし、AesCryptoServiceProviderクラスはRSAENH.DLLを使用するWindowsCrypto APIを呼び出し、CMVPのNISTによって検証されています。 RijndaelアルゴリズムはAESになるアルゴリズムを選択するためのNIST競争の勝者でしたが、Rijndaelと公式AESの間にはいくつかの違いがあります。したがって、RijndaelManagedクラスとAesCryptoServiceProviderクラスの実装には微妙な違いがあります。

さらに、RijndaelManagedクラスはAESで同等の実装を提供できません。 .netフレームワークに実装されている別のクラスAesManagedクラスがあります。このクラスは、AES標準を達成するために、固定ブロックサイズと反復回数でRijndaelManagedクラスをラップしました。ただし、フィードバックサイズはサポートされていません。特に、モードがCFBまたはOFBに設定されている場合は、CryptographicExceptionがスローされます。

詳細については、次のMSDNドキュメントを参照してください。

AesManaged Class および AesManaged.Modeプロパティ

アプリケーションのセキュリティアルゴリズムとして標準のAESを採用する場合は、AesCryptoServiceProviderクラスを使用することをお勧めします。アプリケーションでRijndaelMangedクラスとAesCryptoServiceProviderクラスを混在させたい場合は、プログラムでCFBモードの代わりにCBCモードを使用することをお勧めします。これは、両方のクラスでのCBCモードの実装が同じ。

45

CipherMode.CFBと関係があると思います。 この投稿 説明 AesManaged :を参照してください。

AesManagedは、実際にはRinjdaelManagedの単なるラッパーであり、AESと互換性のない方法で動作するようにアルゴリズムを設定しないようにいくつかのコードが追加されています。たとえば、AesManagedではブロックサイズを変更できません。 (RijndaelManagedがこれらのモードで動作する方法のため、CFBおよびOFBモードの使用も許可されません)。

CipherMode.ECBまたはCipherMode.CBCを使用すると、同じ結果が表示されることに注意してください。 CBCではなくCFBが必要な理由は何ですか?

7
Jeff Moser

この投稿 からの追加情報は言う:

基本的に、RijndaelManagedをAESとして使用する場合は、次のことを確認する必要があります。
1)ブロックサイズは128ビットに設定されています
2)CFBモードを使用していないか、フィードバックサイズも128ビットである場合

わかりました。 mEncryptionType.FeedbackSize = 128を追加しました。上記の例では、CryptographicExecptionを取得します。

 System.Security.Cryptography.CryptographicExceptionが処理されませんでした
 Message = "BadData。\ 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 )[。 、Int32フィードバックサイズ、SafeCspHandleプロバイダー、SafeCapiKeyHandleキー、Byte [] iv、CipherMode cipherMode、PaddingMode paddingMode、EncryptionMode EncryptionMode)
 at System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor(SafeCapiKeyHandle key、Byte [] iv)
 System.Security.Cryptography.AesCでryptoServiceProvider.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 
 C:\ Documents and Settings\nschoonmaker\My Documents\Visual Studio 2005\Projects\AESTest\AESTest\Form1.csのAESTest.Form1..ctor() :行73 
 C:\ Documents and Settings\nschoonmaker\My Documents\Visual Studio 2005\Projects\AESTest\AESTest\Program.cs:line 17 
のAESTest.Program.Main()

これをサポートしないSystem.Coredllに何か問題がありますか、それとも他の何かを変更する必要がありますか?

ちなみに、両方のFeedbackSizeを8に変更すると、機能するようです。 CFBモードでも。だから私の次の質問は、どうすれば128を機能させることができるかということだと思います(そしてうまくいけば、これでこの質問に終止符が打たれます)?

1
SwDevMan81