Emil J
Emil J

Reputation: 215

Wrong size of the encrypted data (AES)

I need to perform encryption array of byte []. I used the example available on the Microsoft. Unfortunately, the encrypted data is truncated to the size that is a multiple of 16. If, in the example of the data I will add 8 times byte 0, the data will be encrypted properly. Padding has been set, but I do not see anything to change it. How to solve this problem, the data do not become cut off.

public byte[] EncryptAES(byte[] plainBytes)
{
    System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
    byte[] FKey = encoding.GetBytes("A002AD9AD73C402190C3E733D82CEA00");
    byte[] FIV = encoding.GetBytes("zyxwvutsrqponmlk");

    // Check arguments.
    if (plainBytes == null || plainBytes.Length <= 0)
        throw new ArgumentNullException("plainText");
    if (FKey == null || FKey.Length <= 0)
        throw new ArgumentNullException("Key");
    if (FIV == null || FIV.Length <= 0)
        throw new ArgumentNullException("Key");
    byte[] encrypted;
    // Create an RijndaelManaged object
    // with the specified key and IV.
    using (RijndaelManaged rijAlg = new RijndaelManaged())
    {
        rijAlg.Key = FKey;
        rijAlg.IV = FIV;
        rijAlg.Padding = PaddingMode.Zeros;
        rijAlg.Mode = CipherMode.CBC;

        // Create a decrytor to perform the stream transform.
        ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);

        // Create the streams used for encryption.
        using (MemoryStream msEncrypt = new MemoryStream())
        {
            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            {
                // plainBytes.Length = 2216 
                csEncrypt.Write(plainBytes, 0, plainBytes.Length);

                // encrypted.Length = 2208
                encrypted = msEncrypt.ToArray();
            }
        }
    }

    // Return the encrypted bytes from the memory stream.
    return encrypted;
}

Upvotes: 1

Views: 2042

Answers (4)

Prince Owen
Prince Owen

Reputation: 1505

It is also important to be careful while decrypting data with CryptoStream. It is advisable to read it using a loop. Calling Read only once can lead to truncated results.

using (var crypto = new CryptoStream(stream, decryptor, CryptoStreamMode.Read))
{
    plainTextBytes = new byte[cleanCipherBytes.Length];

    int read = 0, rem = plainTextBytes.Length;

    do
    {
        read = crypto.Read(plainTextBytes, read, rem);
        rem -= read;
    }
    while (read > 0);
}

This took me quite a while to figure out. I hope it saves someone else's time.

Upvotes: 0

Fidel Delgado Mojica
Fidel Delgado Mojica

Reputation: 31

Just calling FlushFinalBlock() resolves the multiple of 16 problem.

Upvotes: 2

Damien_The_Unbeliever
Damien_The_Unbeliever

Reputation: 239664

CryptoStream:

You should always explicitly close your CryptoStream object after you are done using it by calling the Close method. Doing so flushes the stream and causes all remain blocks of data to be processed by the CryptoStream object. However, if an exception occurs before you call the Close method, the CryptoStream object might not be closed. To ensure that the Close method always gets called, place your call to the Close method within the finally block of a try/catch statement.

(My emphasis)

So, call Close before you try to do anything with the results.


Basically, padding is used to deal with the last block of a sequence of encrypted blocks. Since the CryptoStream doesn't know how many times you intend to call Write(), it doesn't apply padding or write any final incomplete block until you call Close.

(Or, as Monkieboy points out, FlushFinalBlock can also be used to indicate that you're finished)

Upvotes: 2

polybios
polybios

Reputation: 1159

try this

    using (MemoryStream msEncrypt = new MemoryStream())
    {
        using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
        {
            csEncrypt.Write(plainBytes, 0, plainBytes.Length);
        }
        encrypted = msEncrypt.ToArray();
    }

Upvotes: 1

Related Questions