question

UdoRiedel-3318 avatar image
0 Votes"
UdoRiedel-3318 asked TimonYang-MSFT commented

CryptoStream padding in .NET 5.0 different from .NET Framework 4.6 ?

I have a program de-/encrypting data and running under .NET Framework 4.6 using CryptoStream and AES.
When I run the same code in a .NET 5.0 program, I can decrypt anything encrypted with 4.6. But I cannot decrypt files in 4.6 that were encrypted by the 5.0 program.
In 4.6 this gives the exception "The input data is not a complete block.".

In one of my example files the original file size is 22.263 bytes. Encrypted with 4.6 it gives a file of 22.272 bytes which is in my opinion the correct size for AES (128 bit block length, so 1392 blocks). Encrypted with 5.0 it gives a file of 22.264 bytes (1391 and a half block?!).
I tried every available padding (I use PKCS7) in .NET 5.0 but every time it gives 22.264 bytes as file size.
Does anyone know whats wrong there?

Here is some sample code:

         static void EncryptFile(string fileId)
         {
             AesCryptoServiceProvider cryptic = new AesCryptoServiceProvider();
    
             cryptic.Mode = CipherMode.CFB;
             cryptic.Key = ASCIIEncoding.ASCII.GetBytes(docId.ToLower().Substring(0, 32));
             cryptic.IV = ASCIIEncoding.ASCII.GetBytes(docId.ToLower().Substring(0, 16));
     
             using (FileStream fsTarget = new FileStream(fileId, FileMode.CreateNew))
             {
                 using (CryptoStream cs = new CryptoStream(fsTarget, cryptic.CreateEncryptor(), CryptoStreamMode.Write))
                 {
                     using (FileStream fsSource = new FileStream(fileId + ".enc", FileMode.Open, FileAccess.Read)) //, FileShare.ReadWrite);
                     {
                         fsSource.CopyTo(cs);
                     }
                 }
             }
         }
    
         static void DecryptFile(string fileId)
         {
             using (FileStream src = new FileStream(fileId, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
             {
                 AesCryptoServiceProvider cryptic = new AesCryptoServiceProvider();
    
                 cryptic.Mode = CipherMode.CFB;
                 cryptic.Key = ASCIIEncoding.ASCII.GetBytes(fileId.ToLower().Substring(0, 32));
                 cryptic.IV = ASCIIEncoding.ASCII.GetBytes(fileId.ToLower().Substring(0, 16));
    
                 using (CryptoStream cs = new CryptoStream(src, cryptic.CreateDecryptor(), CryptoStreamMode.Read))
                 {
                     using (FileStream tgt = new FileStream(fileId + ".dec", FileMode.CreateNew))
                     {
                         cs.CopyTo(tgt);
                         tgt.Close();
                     }
                 }
             }
         }

dotnet-csharpdotnet-runtime
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Please check the introduction in this document:

CryptoStream.Dispose transforms final block only when writing

Starting from .Net Core3.0, The CryptoStream.Dispose method, which is used to finish CryptoStream operations, no longer attempts to transform the final block when reading.

I think this may be the cause of the problem. When I used .Net 5, I successfully reproduced your problem, but when I used .Net Core 2.1 for testing, the problem disappeared.

0 Votes 0 ·

So what is the solution to this problem?

0 Votes 0 ·

1 Answer

Bruce-SqlWork avatar image
0 Votes"
Bruce-SqlWork answered
                      using (FileStream tgt = new FileStream(fileId + ".dec", FileMode.CreateNew))
                      {
                          cs.CopyTo(tgt);
                          cs.FlushFinalBlock();
                          tgt.Close();
                      }
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.