0

I have below code in .net framework to decrypt some information and it is working fine. I have been tasked to upgrade this code to .net 5 and the same code is not working.

Current code in .net framework works fine

private static string DecryptStringFromBytes(string cypherText, byte[] key)
{
    byte[] cipherTextBytes = Convert.FromBase64String(cipherText);

    if (key == null || key.Length <= 0)
        throw new ArgumentNullException("key");

    string plaintext;
    using (var rijAlg = new RijndaelManaged())
    {
        rijAlg.BlockSize = 256;
        rijAlg.Key = key;
        rijAlg.Mode = CipherMode.CBC;
        rijAlg.Padding = PaddingMode.Zeros;
        rijAlg.IV = ASCIIEncoding.ASCII.GetBytes(MD5(MD5(_encryptionKey)));

        ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
        using (var msDecrypt = new MemoryStream(cipherTextBytes))
        using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
        using (var srDecrypt = new StreamReader(csDecrypt))
            plaintext = srDecrypt.ReadToEnd();
    }
    return plaintext;
}

private static string MD5(string testString)
{
    byte[] asciiBytes = ASCIIEncoding.ASCII.GetBytes(testString);
    byte[] hashedBytes = MD5CryptoServiceProvider.Create().ComputeHash(asciiBytes);
    string hashedString = BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
    return hashedString;
}

The same code when I tried in .net 5 it is giving me the below error. "BlockSize must be 128 in this implementation"

When I changed the block size in the above code to 128- the error disappeared but the decrypted text is all with glibberish text (not in readable format).

I did some research on this and I realized that .net core does not yet support 256 block size and a workaround is to use it with Bouncy Castle library. I did some google search on this and after looking at some samples I updated the code to the below

public static string DecryptFromBouncyCastle(string cipherText, byte[] key)
{
    byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
    if (key == null || key.Length <= 0)
        throw new ArgumentNullException("key");

    var ivStringBytes = new byte[16];

    var engine = new RijndaelEngine(256);
    var blockCipher = new CbcBlockCipher(engine);
    var cipher = new PaddedBufferedBlockCipher(blockCipher, new ZeroBytePadding());
    var keyParam = new KeyParameter(key);
    var keyParamWithIV = new ParametersWithIV(keyParam, ivStringBytes, 0, 32);
    cipher.Init(false, keyParamWithIV);
    var outputBytes = new byte[cipher.GetOutputSize(cipherTextBytes.Length)];
    var length = cipher.ProcessBytes(cipherTextBytes, outputBytes, 0);
    var finalBytes = cipher.DoFinal(outputBytes, 0, length);
    var resultText = Encoding.UTF8.GetString(finalBytes);
    return resultText;
}

private static string MD5(string testString)
{
    byte[] asciiBytes = ASCIIEncoding.ASCII.GetBytes(testString);
    byte[] hashedBytes = MD5CryptoServiceProvider.Create().ComputeHash(asciiBytes);
    string hashedString = BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
    return hashedString;
}

This code is not giving me any error but I see some part of the decryption was working. I see 30% of the decrypted text and rest some junk characters.

I am not so familiar with the encryption/decryption internals and I am struggling to understand where the problem is. It may be a small issue but I could not figure out.

I would appreciate if someone could review this code and let me know where the issue is with my code or suggest if any other better alternate solution.

Topaco
  • 40,594
  • 4
  • 35
  • 62
rednerus
  • 401
  • 2
  • 9
  • 21
  • Your BC implementation doesn't use the IV of the reference function (BTW the IV is 32 bytes in size here). But no reproduction is possible without further ado, since you haven't posted any test data nor the encryption code, so that further bugs can't be ruled out (the `DoFinal()` call and the decoding of `finalBytes` look suspicious). – Topaco Apr 04 '22 at 08:10
  • And the implementation of `MD5` is also missing. – Topaco Apr 04 '22 at 08:34

1 Answers1

1

The IV and the DoFinal() call must be modified:

var ivStringBytes = ASCIIEncoding.ASCII.GetBytes(MD5(MD5(_encryptionKey)));     // Fix 1
...
length += cipher.DoFinal(outputBytes, length);                                  // Fix 2
var resultText = Encoding.UTF8.GetString(outputBytes, 0, length);               // Fix 3

Note that a static IV is insecure. Also, AES should be preferred over Rijndael with a 256 bits blocksize.

Topaco
  • 40,594
  • 4
  • 35
  • 62
  • The code can be run online on .NET Fiddle: https://dotnetfiddle.net/tKeQWH – Topaco Apr 04 '22 at 21:07
  • Thank you so much. You are a genius. The Fix you provided worked for me. Would you mind sharing a code sample with AES for the same use case? – rednerus Apr 04 '22 at 23:38
  • @rednerus - You can use the linked solution and have to replace `new RijndaelManaged()` with `Aes.Create()`, replace `new RijndaelEngine(256)` with `new AesEngine()`, reduce the blocksize from 32 to 16 bytes, and use an IV of 16 bytes (i.e. changes in `ParametersWithIV` (IV length) and in `MD()` (create a 16 bytes IV)). If you get stuck, please ask a new question, post your code so far and describe the problem. – Topaco Apr 05 '22 at 06:43
  • Thank you. I tried writing the decrypt method using AES but could not get that to work. Like you suggested I created another question with details at https://stackoverflow.com/questions/71760017/aes-decryption-in-net-5 – rednerus Apr 06 '22 at 02:41