Home > Net >  How to upgrade from RijndaelManaged to AES?
How to upgrade from RijndaelManaged to AES?

Time:12-03

I have a working solution for crypt/decrypt data in my code (below) but when I have upgraded the project to DOTNET6, RijndaelManaged becomes obsolete:

Warning SYSLIB0022  'RijndaelManaged' is obsolete: 'The Rijndael and RijndaelManaged types are obsolete. Use Aes instead.'

and

SYSLIB0023  'RNGCryptoServiceProvider' is obsolete: 'RNGCryptoServiceProvider is obsolete. To generate a random number, use one of the RandomNumberGenerator static methods instead.'

Now I want to change that to Aes/RandomNumberGenerator as stated but want to keep the output in the same way as is. Unfortunately, I am not familiar with crypt/decrypt.

Can somebody help me to rewrite the current block to work with Aes instead - or at least help me how to change that and keep the public methods works in the same way?

Whole Code I have (it works as is)

using System.Security.Cryptography;

namespace MyApp;

internal static class AES
{
    private static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
    {
        byte[] encryptedBytes;
        byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

        using (MemoryStream ms = new())
        {
            using RijndaelManaged AES = new(); // This reports Warning  SYSLIB0022  'RijndaelManaged' is obsolete: 'The Rijndael and RijndaelManaged types are obsolete. Use Aes instead.
            AES.KeySize = 256;
            AES.BlockSize = 128;
            var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
            AES.Key = key.GetBytes(AES.KeySize / 8);
            AES.IV = key.GetBytes(AES.BlockSize / 8);
            AES.Mode = CipherMode.CBC;
            using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
            {
                cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                cs.Close();
            }
            encryptedBytes = ms.ToArray();
        }
        return encryptedBytes;
    }

    private static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
    {
        byte[] decryptedBytes = null;
        byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
        using (MemoryStream ms = new())
        {
            using RijndaelManaged AES = new(); // This reports Warning  SYSLIB0022  'RijndaelManaged' is obsolete: 'The Rijndael and RijndaelManaged types are obsolete. Use Aes instead.
            AES.KeySize = 256;
            AES.BlockSize = 128;
            var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
            AES.Key = key.GetBytes(AES.KeySize / 8);
            AES.IV = key.GetBytes(AES.BlockSize / 8);
            AES.Mode = CipherMode.CBC;
            using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
            {
                cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
                cs.Close();
            }
            decryptedBytes = ms.ToArray();
        }
        return decryptedBytes;
    }

    public static string EncryptText(string password, string salt = "MySecretSaltWhichIWantToKeepWorking")
    {
        byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(password);
        byte[] passwordBytes = Encoding.UTF8.GetBytes(salt);
        passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
        byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);
        string result = Convert.ToBase64String(bytesEncrypted);
        return result;
    }

    public static string DecryptText(string hash, string salt = "MySecretSaltWhichIWantToKeepWorking")
    {
        try
        {
            byte[] bytesToBeDecrypted = Convert.FromBase64String(hash);
            byte[] passwordBytes = Encoding.UTF8.GetBytes(salt);
            passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
            byte[] bytesDecrypted = AES_Decrypt(bytesToBeDecrypted, passwordBytes);
            string result = Encoding.UTF8.GetString(bytesDecrypted);
            return result;
        }
        catch (Exception e)
        {
            return e.Message;
        }
    }

    private const int SALT_BYTE_SIZE = 24;
    private const int HASH_BYTE_SIZE = 24;
    private const int PBKDF2_ITERATIONS = 1000;
    private const int ITERATION_INDEX = 0;
    private const int SALT_INDEX = 1;
    private const int PBKDF2_INDEX = 2;

    public static string PBKDF2_CreateHash(string password)
    {
        RNGCryptoServiceProvider csprng = new(); // This reports SYSLIB0023 'RNGCryptoServiceProvider' is obsolete: 'RNGCryptoServiceProvider is obsolete. To generate a random number, use one of the RandomNumberGenerator static methods instead.'
        byte[] salt = new byte[SALT_BYTE_SIZE];
        csprng.GetBytes(salt);
        byte[] hash = PBKDF2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE);
        return PBKDF2_ITERATIONS   ":"   Convert.ToBase64String(salt)   ":"   Convert.ToBase64String(hash);
    }

    public static bool PBKDF2_ValidatePassword(string password, string correctHash)
    {
        char[] delimiter = { ':' };
        string[] split = correctHash.Split(delimiter);
        int iterations = Int32.Parse(split[ITERATION_INDEX]);
        byte[] salt = Convert.FromBase64String(split[SALT_INDEX]);
        byte[] hash = Convert.FromBase64String(split[PBKDF2_INDEX]);
        byte[] testHash = PBKDF2(password, salt, iterations, hash.Length);
        return SlowEquals(hash, testHash);
    }

    private static bool SlowEquals(byte[] a, byte[] b)
    {
        uint diff = (uint)a.Length ^ (uint)b.Length;
        for (int i = 0; i < a.Length && i < b.Length; i  )
            diff |= (uint)(a[i] ^ b[i]);
        return diff == 0;
    }

    private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
    {
        Rfc2898DeriveBytes pbkdf2 = new(password, salt)
        {
            IterationCount = iterations
        };
        return pbkdf2.GetBytes(outputBytes);
    }
}

Thank you for any help.

CodePudding user response:

As far as I can tell, you should be able to replace

using RijndaelManaged AES = new();

with

using var AES = Aes.Create("AesManaged");

note that you might want to change your variable name to avoid naming conflicts or confusion.

The only difference between AES and Rijndael should be that Rijndael allows more blocksizes/keysizes. But you seem to be using 256 bit key and 128 bit blocks, and this should be allowed by AES.

  • Related