Bug 7193 - Mono.Security.Cryptography RijndaelManaged class issue using CFB-8 mode
Summary: Mono.Security.Cryptography RijndaelManaged class issue using CFB-8 mode
Status: RESOLVED FIXED
Alias: None
Product: Class Libraries
Classification: Mono
Component: System.Security (show other bugs)
Version: unspecified
Hardware: PC All
: --- normal
Target Milestone: Untriaged
Assignee: Sebastien Pouliot
URL:
Depends on:
Blocks:
 
Reported: 2012-09-15 10:36 UTC by vdm
Modified: 2012-10-10 16:14 UTC (History)
2 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments

Description vdm 2012-09-15 10:36:17 UTC
Hi.

I'm writing to report about cryptography issue. The problem happens using RijndaelManaged class from the System.Security.Cryptography. It is important for me to use RijndaelManaged with CFB-8 (FeedbackSize = 8) mode without padding (PaddingMode.None). Such settings configuration makes encrypted data size equal to the decrypted data size (in my situation it is important). Unfortunately mono [in my pc it is mono compiler for MVS2010 IDE version 2.0.8152] compiled code throws exception on data encryption with message: [Unhandled Exception: System.Security.Cryptography.CryptographicException: invalid block length at Mono.Security.Cryptography.SymmetricTransform.FinalEncrypt]. Also i made tests with the .NET framework 4.0 under Windows XP and Windows 7 using native Visual Studio 2010 compiler and found that microsoft compiler does not throw any exceptions and the code example works well using native .NET compiler. What is the problem with mono compiler, why exception rise? Below i paste two examples (repro code), one for mono which throws exceptions and one for native C# compiler in this case there are no exceptions. Also i paste online compilers links to test the codes.

Why code compiled by mono crashes and how to solve it?

########################################################################################################################

Mono code sample [Link for online compiler to test: http://www.compileonline.com/compile_csharp_online.php]

using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

namespace Dela.Mono.Examples
{
   public class HelloWorld
   {
      public static void Main(string[] args)
      {
         string plainText = "This will be encrypted.";
            string plainText2 = "";
       
            RijndaelManaged aesAlg = new RijndaelManaged();
           
            aesAlg.BlockSize = 128;
            aesAlg.KeySize = 256;
            aesAlg.Mode = CipherMode.CFB;
            aesAlg.FeedbackSize = 8;
            aesAlg.Padding = PaddingMode.None;
           
            aesAlg.GenerateKey();
            aesAlg.GenerateIV();
   
            ICryptoTransform encryptor = aesAlg.CreateEncryptor();
             
            MemoryStream msEncrypt = new MemoryStream();
            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) {
                using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) {
                    swEncrypt.Write(plainText);
                }
            }
           
            Console.WriteLine(msEncrypt.ToArray().Length);
            Console.WriteLine(System.Text.Encoding.UTF8.GetString(msEncrypt.ToArray()));
           
            byte[] customArray = msEncrypt.ToArray();
           
            ICryptoTransform decryptor = aesAlg.CreateDecryptor();
             
            MemoryStream msDecrypt = new MemoryStream(customArray);
            using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) {
                using (StreamReader swDecrypt = new StreamReader(csDecrypt)) {
                    plainText2 = swDecrypt.ReadToEnd();
                }
            }
           
            Console.WriteLine(plainText2.Length);
            Console.WriteLine(plainText2);
           
           
      }
   }
}

########################################################################################################################

Native C# code sample [Link for online compiler to test: http://rextester.com/runcode]

//Title of this code
//Rextester.Program.Main is the entry point for your code. Don't change it.

using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string plainText = "This will be encrypted.";
            string plainText2 = "";
       
            RijndaelManaged aesAlg = new RijndaelManaged();
           
            aesAlg.BlockSize = 128;
            aesAlg.KeySize = 256;
            aesAlg.Mode = CipherMode.CFB;
            aesAlg.FeedbackSize = 8;
            aesAlg.Padding = PaddingMode.None;
           
            aesAlg.GenerateKey();
            aesAlg.GenerateIV();
   
            ICryptoTransform encryptor = aesAlg.CreateEncryptor();
             
            MemoryStream msEncrypt = new MemoryStream();
            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) {
                using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) {
                    swEncrypt.Write(plainText);
                }
            }
           
            Console.WriteLine(msEncrypt.ToArray().Length);
            Console.WriteLine(System.Text.Encoding.UTF8.GetString(msEncrypt.ToArray()));
           
            byte[] customArray = msEncrypt.ToArray();
           
            ICryptoTransform decryptor = aesAlg.CreateDecryptor();
             
            MemoryStream msDecrypt = new MemoryStream(customArray);
            using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) {
                using (StreamReader swDecrypt = new StreamReader(csDecrypt)) {
                    plainText2 = swDecrypt.ReadToEnd();
                }
            }
           
            Console.WriteLine(plainText2.Length);
            Console.WriteLine(plainText2);
        }
    }
}

########################################################################################################################
Comment 1 vdm 2012-09-22 13:08:40 UTC
Also i have found that if data which will be encrypted has length which is devided by 16 then exception does not rise. But in my case i have set FeedBackSize to 8 (1 byte), so with such setting there should not be matter if data length is devided by 16 or not. Impression that mono cryptagraphy library just does not use FeedBackSize parameter correctly with RijndaelManaged class on CFB mode?
Comment 2 Sebastien Pouliot 2012-09-25 14:55:56 UTC
You're right. CFB does not work correctly is the data is not a multiple of the cipher block size.
Comment 3 vdm 2012-09-25 15:02:27 UTC
Oh, hi Sebastien.

I finally received an answer from you. :) Yep, i know what i'm right :) What to do with it? I have a project and must use this algorithm, it is critical situation for me... :( What do you think how long it will take to solve the problem by mono team?
Comment 4 Sebastien Pouliot 2012-09-26 21:00:00 UTC
> What to do with it?

It's open source, you either contribute or wait for a contributor to fix it ;-)

Fixed.
master: e094d3dc0cf186f1de32d5340d847dc18aeca0e2
mono-2-10: 98e4842eb19dfd60000ada19e9bfb265fad7c84b
Comment 5 vdm 2012-10-06 10:32:20 UTC
Hi, Sebastien.

Thanks for your fix.

Also, maybe you know is it possible to debug mono framework using breakpoints in mono core classes?
Comment 6 Marek Safar 2012-10-07 04:12:14 UTC
Yes, it's easy to debug mono bcl.

You need to compile it yourself to have correct path to source files in mdb.
Enable framework debugging in MonoDevelop settings.

Then you can just open a C# file and set a breakpoint or use step-into
Comment 7 vdm 2012-10-10 16:14:47 UTC
Hi Marek.

I'm looking for crypto classes: ECDiffieHellmanCng and ECDsaCng in mono 2.10.8 but my monodevelop on debian says that can't find such names. Maybe these classes has another names in mono or this functionality are absent in mono at all?

Note You need to log in before you can comment on or make changes to this bug.