0

After upgrading from .net 5 to .net 6 my decrypt method not decrypting properly. As RijndaelManaged class declared as obsolete what is way to solve this issue.

My service class looks like:

// This constant is used to determine the keysize of the encryption algorithm in bits.
    // We divide this by 8 within the code below to get the equivalent number of bytes.
    private const int Keysize = 128;

    // This constant determines the number of iterations for the password bytes generation function.
    private const int DerivationIterations = 10000;

    public string Encrypt(string plainText, string passPhrase)
    {
        // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text
        // so that the same Salt and IV values can be used when decrypting.  
        var saltStringBytes = GenerateBitsOfRandomEntropy(16);
        var ivStringBytes = GenerateBitsOfRandomEntropy(16);
        var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
        using var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations);
        var keyBytes = password.GetBytes(Keysize / 8);
        using var symmetricKey = new RijndaelManaged
        {
            BlockSize = 128,
            Mode = CipherMode.CBC,
            Padding = PaddingMode.PKCS7
        };
        using var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes);
        using var memoryStream = new MemoryStream();
        using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
        cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
        cryptoStream.FlushFinalBlock();
        // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes.
        var cipherTextBytes = saltStringBytes;
        cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray();
        cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray();
        memoryStream.Close();
        cryptoStream.Close();
        return Convert.ToBase64String(cipherTextBytes);
    }

    public string Decrypt(string cipherText, string passPhrase)
    {
        // Get the complete stream of bytes that represent:
        // [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText]
        var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
        // Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes.
        var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
        // Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes.
        var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
        // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
        var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2)
            .Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray();

        using var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations);
        var keyBytes = password.GetBytes(Keysize / 8);
        using var symmetricKey = new RijndaelManaged
        {
            BlockSize = 128,
            Mode = CipherMode.CBC,
            Padding = PaddingMode.PKCS7
        };
        using var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes);
        using var memoryStream = new MemoryStream(cipherTextBytes);
        using var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
        var plainTextBytes = new byte[cipherTextBytes.Length];
        var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
        memoryStream.Close();
        cryptoStream.Close();
        return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
    }

    private static byte[] GenerateBitsOfRandomEntropy(int size)
    {
        // 32 Bytes will give us 256 bits.
        // 16 Bytes will give us 128 bits.
        var randomBytes = new byte[size];
        using (var rngCsp = new RNGCryptoServiceProvider())
        {
            // Fill the array with cryptographically secure random bytes.
            rngCsp.GetBytes(randomBytes);
        }

        return randomBytes;
    }

I see microsoft suggest to use Aes.Create() method, but if already some data encrypted with RijndaelManaged class how it will decrypt them correctly? As Aes and RijndaelManaged are using different cryptography algorithm.

P.S. I tried to create new .net 5 class library and posted my code to nuget and used this library in my project but issue does not solved. But in .net 5 all works fine.

Arzu Suleymanov
  • 671
  • 2
  • 11
  • 33
  • Did you try using AES? Quick search said that AES is the same thing but has a smaller set of allowed key and block sizes. You have 128 and 128, which are allowed in AES. – juunas Nov 10 '21 at 12:44
  • 1
    See this question: https://stackoverflow.com/a/69911553/5311735 – Evk Nov 10 '21 at 12:46
  • @juunas problem is i am not saving byte array as encrypted text, both they are strings – Arzu Suleymanov Nov 10 '21 at 12:46

0 Answers0