0

I implemented methods for symmetric encryption and decryption of a string in .net core 3.1. Now I'm migrating a project from .net core 3.1 to .net 7. Encryption works fine, but when I decrypt the encrypted value (JSON-string) in my .net 7 implementation it shortens the result string. The .net core 3.1 implementation instead returns the full value.

My implementation:

 #region Settings

 private int _iterations = 2;
 private static int _keySize = 256;
 private string _hash = "SHA1";
 private string _salt = "xxx"; // Random
 private string _vector = "xxx"; // Random

 #endregion

 public string Run(string data, string key)
 {
     var jsonstring = Decrypt(data, key);
     return jsonstring;
 }


 private string Decrypt(string value, string password)
 {
     return Decrypt<AesManaged>(value, password);
 }

 private string Decrypt<T>(string value, string password) where T : SymmetricAlgorithm, new()
 {
     byte[] vectorBytes = Encoding.UTF8.GetBytes(_vector);
     byte[] saltBytes = Encoding.UTF8.GetBytes(_salt);
     byte[] valueBytes = Convert.FromBase64String(value);

     byte[] decrypted;
     int decryptedByteCount = 0;

     using (T cipher = new T())
     {
         PasswordDeriveBytes _passwordBytes = new PasswordDeriveBytes(password, saltBytes, _hash, _iterations);
         byte[] keyBytes = _passwordBytes.GetBytes(_keySize / 8);

         cipher.Mode = CipherMode.CBC;

         try
         {
             using (ICryptoTransform decryptor = cipher.CreateDecryptor(keyBytes, vectorBytes))
             {
                 using (MemoryStream from = new MemoryStream(valueBytes))
                 {
                     using (CryptoStream reader = new CryptoStream(from, decryptor, CryptoStreamMode.Read))
                     {
                         decrypted = new byte[valueBytes.Length];
                         decryptedByteCount = reader.Read(decrypted, 0, decrypted.Length);
                     }
                 }
             }
         }
         catch (Exception ex)
         {
             return String.Empty;
         }

         cipher.Clear();
     }

     var decrypt = Encoding.UTF8.GetString(decrypted, 0, decryptedByteCount);
     return decrypt;
 }

I made tests in .net core 3.1 and .net7 and encrypted and decrypted my example string. The encryption works fine and I'm getting the same encrypted value. The decryption in .net core 3.1 returns the full initial value. The decryption in .net 7 returns a shorter version of the initial value (tested with different strings). The last 6 to 8 characters are missing now.

2
  • 1
    This breaking change identified in this post is the usual suspect for this kind of problem. Commented Aug 24, 2023 at 14:24
  • @Topaco thank you that was the problem. I had to resize the buffer at the end... Showing my new implementation in the answer Commented Aug 25, 2023 at 9:23

1 Answer 1

1

Because of Partial and zero-byte reads in DeflateStream, GZipStream, and CryptoStream I had to resize the buffer at the end. Here is my new implementation:

    private string Decrypt<T>(string value, string password) where T : SymmetricAlgorithm, new()
{
    byte[] vectorBytes = Encoding.UTF8.GetBytes(_vector);
    byte[] saltBytes = Encoding.UTF8.GetBytes(_salt);
    byte[] valueBytes = Convert.FromBase64String(value);

    string result = string.Empty;

    using (T cipher = new T())
    {
        PasswordDeriveBytes _passwordBytes = new PasswordDeriveBytes(password, saltBytes, _hash, _iterations);
        byte[] keyBytes = _passwordBytes.GetBytes(_keySize / 8);

        cipher.Mode = CipherMode.CBC;

        try
        {
            using (ICryptoTransform decryptor = cipher.CreateDecryptor(keyBytes, vectorBytes))
            using (MemoryStream memoryStream = new MemoryStream(valueBytes))
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
            {
                byte[] decryptedData = new byte[valueBytes.Length];
                int bytesRead;
                int offset = 0;

                while ((bytesRead = cryptoStream.Read(decryptedData, offset, decryptedData.Length - offset)) > 0)
                {
                    offset += bytesRead;

                    // If the offset reaches the end of the buffer, resize the buffer to accommodate more data
                    if (offset == decryptedData.Length)
                    {
                        Array.Resize(ref decryptedData, decryptedData.Length * 2);
                    }
                }

                Array.Resize(ref decryptedData, offset);

               result = Encoding.UTF8.GetString(decryptedData);
            }

        }
        catch (Exception ex)
        {
            return String.Empty;
        }

        cipher.Clear();
    }

    return result;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.