runtime: CipherMode.CFB does not Encrypt the same in .NET 5.0 RC1 as in .NET 4.7

When using CipherMode.CFB as Mode in the System.Security.Cryptography.TripleDES to Encrypt e.g. a password you don’t get the same encryption string back in .NET 5.0 RC1 as you get in .NET 4.7. We have used code like this since .net 4.5 and it’s worked exactly the same since, i should work exactly the same in .NET 5.0 as in 4.x or all apps using this for e.g. saving password encrypted will stop working after upgrade to .NET 5.

I did a test console app to reproduce this, it’s the exact the same code for both .NET 5.0 RC1 as for .NET 4.7. Both apps where created in VS 2019 Preview (16…8.0 Preview 3.2). And they do not generate the same result.

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

namespace TestConsole.net5
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, Typ in you text to be Encrypted!");
            string text = Console.ReadLine();
            TripleDESHelper tripleDESHelper = new TripleDESHelper();
            string encryptedtext = tripleDESHelper.Encrypt(text);
            Console.WriteLine("Your encrypted text results in this: " + encryptedtext);
            Console.ReadLine();
        }
    }
    public class TripleDESHelper
    {

        private readonly byte[] KEY_BYTES = { 2, 24, 1, 114, 15, 74, 23, 43, 81, 23, 87, 34, 55, 72, 32, 34 };
        private readonly byte[] IV_BYTES = { 90, 12, 54, 27, 62, 3, 45, 23 };

        private TripleDES tripleDES;

        public TripleDESHelper()
        {
            tripleDES = TripleDESCryptoServiceProvider.Create();
            tripleDES.Key = KEY_BYTES;
            tripleDES.IV = IV_BYTES;

            // Used for small chunck of data. In this one, we use it for user's password.
            tripleDES.Mode = CipherMode.CFB;
        }

        /// <summary>
        /// Encrypts the given plain text string into an encrypted, base 64 encoded value; using the Triple Data Encryption Standard algorithms
        /// </summary>
        /// <param name="clearText">The plain text.</param>
        /// <returns>A string representing the encrypted text.</returns>
        public string Encrypt(string clearText)
        {
            if (tripleDES == null || String.IsNullOrEmpty(clearText))
                return String.Empty;

            String encryptedText = String.Empty;

            ICryptoTransform encryptor = tripleDES.CreateEncryptor();


            byte[] textBytes = Encoding.UTF8.GetBytes(clearText);

            encryptedText = System.Convert.ToBase64String(encryptor.TransformFinalBlock(textBytes, 0, textBytes.Length));

            return encryptedText;
        }

        /// <summary>
        /// Decrypts the given cipher text string into an plain text using the Triple Data Encryption Standard algorithms
        /// </summary>
        /// <param name="cipherText">The cipher text.</param>
        /// <returns>A string representing the plain text</returns>
        public string Decrypt(string cipherText)
        {
            if (tripleDES == null || String.IsNullOrEmpty(cipherText))
                return String.Empty;

            String decryptedText = String.Empty;

            byte[] encryptedBytes = System.Convert.FromBase64String(cipherText);

            ICryptoTransform decryptor = tripleDES.CreateDecryptor();

            decryptedText = Encoding.UTF8.GetString(decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length));

            return decryptedText;

        }
    }
}

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 17 (17 by maintainers)

Most upvoted comments

I will guess 80% chance they take it…

Thanks, @vcsjones. I so owe you a cup of coffee for the help you’ve given while I’ve been juggling multiple projects.

I’ll work on this over the weekend and you can decide if you want to port to release/5.0.

The reverse is not a problem: we can de-pad .NET Framework encrypted data in .NET 5.

Then I think at this point we stick with “We do nothing.” (for padding, vs feedback size). Upgrading succeeds (old data can be read), but side-by-side is hampered (since old programs can’t read new program data). Callers who need the padding to be there can do their encrypts with no padding and manually append the padding data. It’s not great, but the workaround is required in the newer application, so it’s at least not something that requires a time machine.

@bartonjs so if I understand right

  • one value is much as good as the other, ie., we don’t lose anything
  • it would make us meaningfully more (ie., code didn’t prevoiusly work) compatible with .NET Framework
  • it would not break any customers coming from 3.1 because the mode didn’t exist then
  • we have only one customer report but it’s also the case that we haven’t actually shipped yet
  • you believe the risk of the change is low or very low?

If so this sounds like worth taking to tactics for approval, but note @vcsjones we won’t know their decision before Monday, in case that influences whether you want to spend time on it 😃