0

i tried some tests with code below. The filesize of encrypted size is always +16 Bytes in compare of the filesize of the decrypted files. Should not be the file size the same? So i guess, the RijndaelManaged-Class or the CryptoStream-Class implements the IV in the cipher output!? If it would be so, how can i read the IV from the cipher output? In my sample, i divert the IV from thepassword. And i ask myself it if would be a better method for, e.g. reading the IV from the crypted message.

I try to find the best way for me, to transport the IV in CBC mode. And if there is a possibility to avoid the divertion of the IV in the DecryptFileA (Line: aesCrypto.IV = ASCIIEncoding.ASCII.GetBytes(strPassword)) again because it is easier to get it from the cipher message, so i would prefer the last method.

public static void EncryptFileA(string strInputFilename, string strOutputFilename, string strPassword)
{
    if (File.Exists(strInputFilename))
    {
        // debugger
        if (strInputFilename.Contains("test.pdf"))
            Debug.Print("Encrypt: " + new FileInfo(strInputFilename).FullName + "|" + new FileInfo(strInputFilename).Length);

        RijndaelManaged aesCrypto = new RijndaelManaged();

        // Fileinfo size
        FileInfo fi = new FileInfo(strInputFilename);
        long longFsize = fi.Length;

        // set crypto parameter
        aesCrypto.KeySize = 256;
        aesCrypto.BlockSize = 128;
        aesCrypto.Key = ASCIIEncoding.ASCII.GetBytes(strPassword);
        aesCrypto.Padding = PaddingMode.PKCS7;
        aesCrypto.IV = ASCIIEncoding.ASCII.GetBytes(strPassword);
        aesCrypto.Mode = CipherMode.CBC;

        using (FileStream fsCrypt = new FileStream(strOutputFilename, FileMode.Create))
        {
            using (CryptoStream cs = new CryptoStream(fsCrypt, aesCrypto.CreateEncryptor(), CryptoStreamMode.Write))
            {
                using (FileStream fsIn = new FileStream(strInputFilename, FileMode.Open))
                {
                    try
                    {
                        byte[] buffer = new byte[1024];
                        int read;

                        while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)            // so long data in pipe
                        {
                            cs.Write(buffer, 0, read);      // write encrypted buffer in read stream
                        }
                    }
                    catch (CryptographicException e)
                    {
                        Console.WriteLine("CryptographicException: " + strInputFilename);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Exception: " + strInputFilename);
                    }
                }
            }
        }
    }
}
public static void DecryptFileA(string strInputFilename, string strOutputFilename, string strPassword)
{
    if (File.Exists(strInputFilename))
    {
        // debugger
        if (strInputFilename.Contains("test.pdf"))
            Debug.Print("Decrypt: " + new FileInfo(strInputFilename).FullName + "|" + new FileInfo(strInputFilename).Length);

        RijndaelManaged aesCrypto = new RijndaelManaged();

        // Fileinfo size
        FileInfo fi = new FileInfo(strInputFilename);
        long longFsize = fi.Length;

        // set crypto parameter
        aesCrypto.KeySize = 256;
        aesCrypto.BlockSize = 128;
        aesCrypto.Key = ASCIIEncoding.ASCII.GetBytes(strPassword);
        aesCrypto.Padding = PaddingMode.PKCS7;
        aesCrypto.IV = ASCIIEncoding.ASCII.GetBytes(strPassword);
        aesCrypto.Mode = CipherMode.CBC;
                
        using (FileStream fsCrypt = new FileStream(strInputFilename, FileMode.Open))
        {
            using (CryptoStream cs = new CryptoStream(fsCrypt, aesCrypto.CreateDecryptor(), CryptoStreamMode.Read))
            {
                using (FileStream fsOut = new FileStream(strOutputFilename, FileMode.Create))
                {
                    try
                    {
                        byte[] buffer = new byte[1024];
                        int read;

                        while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            fsOut.Write(buffer, 0, read);
                        }

                    }
                    catch (CryptographicException e)
                    {
                        Console.WriteLine("CryptographicException: " + strInputFilename);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Exception: " + strInputFilename);
                    }
                }
            }
        }
    }
}

I already red the documentation at Microsoft about the IV and the CreateEncryptor. I know, that a nulled IV will be filled with value by the CreateEncryptor... but i can not find a note about reading the IV from somewhere. Additionally, i studied and tried some samples (https://gist.github.com/mazhar-ansari-ardeh/d200d91fbafc1af03a0bc0588ef7ffd0, https://codereview.stackexchange.com/questions/243971/c-aes-encryption-decryption-or-byte-array-with-a-custom-key-iv, How do i use random salt and random iv in aes encryption and decryption algorithm?). But they are implementing the IV "manually" in the cipher OR the initiate the IV for both encrypting/decrypting at first.

Then, its clear so far for me, for what i need the IV in CBC-Mode (for crypting the first clear text block to avoid same-plane-text-attacks). And there is no technical need, to secret the IV.

Eloy
  • 19
  • 4

1 Answers1

0

You can obviously prepend the IV into the cipher since the IV has not to be a secret. But using different IVs for different files is highly recommended.

In your case, you have to read the IV from the file "before" creating the decryptor.

using (FileStream fsCrypt = new FileStream(strInputFilename, FileMode.Open))
        {
            byte[] buffer = new byte[16];  // Since IV is 16 bytes
            fsCrypt.Read(buffer, 0, buffer.Length;  // Reads the first 16 bytes (IV) into the buffer
            aesCrypto.IV = buffer;

            using (CryptoStream cs = new CryptoStream(fsCrypt, aesCrypto.CreateDecryptor(), CryptoStreamMode.Write))
            {
                using (FileStream fsOut = new FileStream(strOutputFilename, FileMode.Create))
                {
                    try
                    {
                        fscrypt.CopyTo(cs);

                    }
                    catch (CryptographicException e)
                    {
                        Console.WriteLine("CryptographicException: " + strInputFilename);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Exception: " + strInputFilename);
                    }
                }
            }
        }
  • 1
    Thanks a lot, Yashoja. But do you know, if the IV is automatically implemented in the cyphre message by crypto framework? The encrypted message is a few bytes larger as the original message...? I want avoid the "double" setting of the IV in the cyphre. – Eloy Jun 11 '23 at 16:42
  • @Eloy one way to find out is by decrypting the file without providing IV and comparing the hashes of the original file and decrypted file. – Yashoja Lakmith Jun 11 '23 at 18:00
  • thanks a lot for your answer. sorry for being late. – Eloy Jul 06 '23 at 08:38