C# CryptoStream.Close() writes additional block into an attached MemoryStream

157 Views Asked by At

I have an encryption function based on the standard library AES with the block size of 16 bytes.

I'm encrypting a single block of size 16 bytes with a 16 byte key, using CryptoStream and MemoryStream.

If I Write and Flush, the result has 16 bytes. If I Write, Flush, and Close, it's 32 bytes.

Consider the example with the following encryption function:

public static byte[] EncryptBytes(byte[] data, string password, bool close)
{
    var myAes = Aes.Create();
    myAes.BlockSize = 128;
    myAes.IV = new byte[16];
    myAes.Key = Encoding.ASCII.GetBytes(password);
    var encryptor = myAes.CreateEncryptor(myAes.Key, myAes.IV);

    using var memoryStream = new MemoryStream();
    using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
    cryptoStream.Write(data, 0, data.Length);
    cryptoStream.Flush();
    if (close)
    {
        cryptoStream.Close(); // The offending line
    }
    byte[] cipher = memoryStream.ToArray();

    return cipher;
}

Then running the following program:

string key = "0123456789ABCDEF";
byte[] data = key.Select(c => (byte) c).ToArray();
string a = EncryptBytes(data, key, true).Aggregate("", (s, b) => s + b.ToString("X2"));
string b = EncryptBytes(data, key, false).Aggregate("", (s, b) => s + b.ToString("X2"));
Console.WriteLine($"A: {a}");
Console.WriteLine($"B: {b}");

Results in:

A: 8D835D0CFFD8BAD585FE8B4294C42188786F695CF204DC5AA109BA26653DFD97
B: 8D835D0CFFD8BAD585FE8B4294C42188

It's clear that A is the same as B for the first 16 bytes, but I would expect the B result and do not understand why the two are different.

0

There are 0 best solutions below