I have inherited some legacy code originally built in .NET 4.6 which is something as follows:
static void Main(string[] args)
{
Console.WriteLine(Encrypt("B9519163"));
}
public static string Encrypt(string text)
{
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.IV = Encoding.UTF8.GetBytes("WiPB5/SrFvq6fu93"); // Dummy IV value
aes.Key = Encoding.UTF8.GetBytes("I9qKwOuZpWtt64Nl"); // Dummy key
aes.Mode = CipherMode.CFB;
aes.Padding = PaddingMode.PKCS7;
byte[] src = Encoding.Unicode.GetBytes(text);
using (ICryptoTransform encrypt = aes.CreateEncryptor())
{
byte[] dest = encrypt.TransformFinalBlock(src, 0, src.Length);
return Convert.ToBase64String(dest);
}
}
I'm building a new desktop application in .NET 8 that needs to decrypt data created by the legacy code and it's not working due to what seems to be incompatibility between how aes encryption/decryption works between the different .NET versions.
In .NET 4.6 the byte array dest returned by encrypt.TransformFinalBlock() has 32 bytes. According my understanding of the PKCS7 documentation the remainder of the 32-byte array with all the padded bytes will have the same value. However, the padded bytes are being populated with seemingly random values. Here they are as seen in the debugger: {245, 51, 180, 226, 20, 222, 24, 183, 72, 152, 102, 17, 219, 215, 37, 233, 123, 119, 154, 204, 218, 52, 139, 81, 119, 59, 42, 206, 13, 185, 247, 122}
I'm not sure if my understanding of how this is supposed to work is correct.
When I run the same code in .NET 8 it returns a 17-byte array which is not a multiple of the blocksize. The first 16 bytes are the same as expected. {245, 51, 180, 226, 20, 222, 24, 183, 72, 152, 102, 17, 219, 215, 37, 233, 106}
How can I make my .NET 8 code backwards compatible to decrypt values generated by the legacy code? Any help with this would be greatly appreciated! Thanks in advance.
Thanks to @Topaco for guiding me to the solution. Your help is much appreciated. Here's what I ended up with to solve this issue and make it backwards compatible with .NET Framework.
static void Main(string[] args)
{
Console.WriteLine(Encrypt("B9519163"));
}
public static string Encrypt(string text)
{
var aes = Aes.Create();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.IV = Encoding.UTF8.GetBytes("WiPB5/SrFvq6fu93");
aes.Key = Encoding.UTF8.GetBytes("I9qKwOuZpWtt64Nl");
aes.Mode = CipherMode.CFB;
aes.Padding = PaddingMode.None;
byte[] src = Encoding.Unicode.GetBytes(text);
byte[] paddedSrc = PerformPKCS7Padding(src, 16);
using (ICryptoTransform encrypt = aes.CreateEncryptor())
{
byte[] dest = encrypt.TransformFinalBlock(paddedSrc, 0, paddedSrc.Length);
return Convert.ToBase64String(dest);
}
}
static byte[] PerformPKCS7Padding(byte[] input, int blockSize)
{
int paddingLength = blockSize - (input.Length % blockSize);
byte[] paddedData = new byte[input.Length + paddingLength];
// Copy original data
Array.Copy(input, paddedData, input.Length);
// Add padding bytes
for (int i = input.Length; i < paddedData.Length; i++)
{
paddedData[i] = (byte)paddingLength;
}
return paddedData;
}