Block-Cipher

為什麼 .NET 的 ECB 模式實現會在我的密文中附加一個常量塊?

  • August 7, 2012

考慮以下程式碼和輸出:

   public static void Main() {
       DESCryptoServiceProvider symAlg = new DESCryptoServiceProvider();
       symAlg.BlockSize = 64;
       symAlg.GenerateKey();
       symAlg.Mode = CipherMode.ECB;

       testCipher(symAlg, new byte[] {
           0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
           0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
       });
       testCipher(symAlg, new byte[] {
           0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
           0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
           0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0x8E,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
       });

       Console.ReadKey();
   }

   public static void testCipher(SymmetricAlgorithm symAlg, byte[] plainText) {
       ICryptoTransform xfrm;

       xfrm = symAlg.CreateEncryptor();
       byte[] encrypted = xfrm.TransformFinalBlock(plainText, 0, plainText.Length);
       xfrm = symAlg.CreateDecryptor();
       byte[] decrypted = xfrm.TransformFinalBlock(encrypted, 0, encrypted.Length);

       Console.WriteLine(new string('=', 23));
       writeBlocks(plainText);
       writeBlocks(encrypted);
       writeBlocks(decrypted);
   }

   private static void writeBlocks(byte[] blocks){
       for (int i = 0; i < blocks.Length; i += 8) Console.WriteLine(BitConverter.ToString(blocks, i, 8));
       Console.WriteLine();
   }

輸出:

=======================
01-02-03-04-05-06-07-08
01-02-03-04-05-06-07-08

1E-0C-3E-59-93-5C-23-6E
1E-0C-3E-59-93-5C-23-6E
6F-AC-50-69-34-D0-B1-61 // NOTE THIS

01-02-03-04-05-06-07-08
01-02-03-04-05-06-07-08

=======================
C1-C2-C3-C4-C5-C6-C7-C8
D1-D2-D3-D4-D5-D6-D7-D8
E1-E2-E3-E4-E5-E6-E7-8E
00-00-00-00-00-00-00-00

F9-9A-77-30-3B-31-7F-D2
D8-B5-B2-C6-E7-E7-0F-90
0E-90-DF-AF-56-C0-DE-84
65-5D-E0-7D-5A-7A-0F-D9
6F-AC-50-69-34-D0-B1-61 // AND THIS

C1-C2-C3-C4-C5-C6-C7-C8
D1-D2-D3-D4-D5-D6-D7-D8
E1-E2-E3-E4-E5-E6-E7-8E
00-00-00-00-00-00-00-00

我理解歐洲央行的弱點。我不明白的是,為什麼.NET 會強迫我附加一個最終塊,該塊是密鑰的長度,並且只隨密鑰而變化。不管一開始加密有多弱,這不是更糟嗎?

我有一個使用 ECB 的特定原因:Encrypt array of int for individual retrieves

但是,僅解密一個塊(沒有恆定的最終塊)會產生: System.Security.Cryptography.CryptographicException 未處理 Message=Bad Data。

現在,知道密鑰是常量,我可以在應用程序初始化時執行虛假加密並記憶體最終塊,將其回饋給我的解密操作,而不是將其放入數據流中,但為什麼 .NET 會鼓勵我將其與數據一起儲存,並且只有.NET可以這樣做嗎?

我相信您所看到的是 .NET 自動使用 PKCS #7 填充。這將始終添加填充。因此,如果您的明文是完整的塊長度,則會添加一個額外的填充塊。

密文在兩個測試案例中最終相同的原因是它在兩種情況下都添加了相同的填充(有關 PKCS #7 的詳細資訊,請參閱PaddingMode 列舉)。

您可以使用Padding Property讓 .NET 不使用填充。

引用自:https://crypto.stackexchange.com/questions/3397