After migrating our encryption project (library) from .NET Framework 4.6x to .NET Core 6, we are getting the error Padding is invalid and cannot be removed.. The code is the same, with the same encryptions settings. The encryption is working in .NET Framework, it is not working in .NET Core.
All settings have been verified as the same, such as padding, the key, the initialization vector, etc..
Is the cyphered string being effected some by the new .NET Core CLR between the database and the library in a different way than the CLR in the .NET Framework 4.6?
What should we do differently to fix this issue?
This is legacy code we plan to eliminate, but we need to use it for now.
Old code:
using Previdence.Common.Security.Cryptography.Interfaces;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace DatabaseTableExport.Common.Security.Cryptography
{
public class AESEncryption : IEncryptionProvider
{
private readonly byte[] _key;
private readonly byte[] _iv;
public AESEncryption(string key)
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(key, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
_key = pdb.GetBytes(32);
_iv = pdb.GetBytes(16);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public string Encrypt(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
return value;
}
byte[] clearBytes = Encoding.Unicode.GetBytes(value);
using (Aes encryptor = Aes.Create())
{
if (encryptor != null)
{
encryptor.Padding = PaddingMode.PKCS7;
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(_key, _iv), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.FlushFinalBlock();
value = Convert.ToBase64String(ms.ToArray());
}
}
}
return value;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public string Decrypt(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
return value;
}
byte[] cipherBytes = Convert.FromBase64String(value);
using (Aes encryptor = Aes.Create())
{
if (encryptor != null)
{
encryptor.Padding = PaddingMode.PKCS7;
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(_key, _iv), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.FlushFinalBlock();
value = Encoding.Unicode.GetString(ms.ToArray());
}
}
}
return value;
}
public void Dispose()
{
}
}
}
using System;
namespace Security_Legacy.Cryptography.Interfaces
{
public interface IEncryptionProvider : IDisposable
{
string Decrypt(string cypheredText);
string Encrypt(string plainText);
}
}
New code:
using DatabaseTableExport.Services.Cryptography.Interfaces;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace DatabaseTableExport.Services.Cryptography
{
public class AesEncryption : IEncryptionProvider
{
private readonly byte[] _key;
private readonly byte[] _iv;
public AesEncryption(string key)
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(key, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
_key = pdb.GetBytes(32);
_iv = pdb.GetBytes(16);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public string Encrypt(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
return value;
}
byte[] clearBytes = Encoding.Unicode.GetBytes(value);
using (Aes encryptor = Aes.Create())
{
if (encryptor != null)
{
encryptor.Padding = PaddingMode.PKCS7;
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(_key, _iv), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.FlushFinalBlock();
value = Convert.ToBase64String(ms.ToArray());
}
}
}
return value;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public string Decrypt(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
return value;
}
byte[] cipherBytes = Convert.FromBase64String(value);
using (Aes encryptor = Aes.Create())
{
if (encryptor != null)
{
encryptor.Padding = PaddingMode.PKCS7;
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(_key, _iv), CryptoStreamMode.Write))
{
try
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.FlushFinalBlock();
value = Encoding.Unicode.GetString(ms.ToArray());
}
catch (Exception e)
{
value = $"Failed to decrypt: {e.Message}";
var errorString = $"{e.Message}";
}
}
}
}
return value;
}
public void Dispose()
{
// nothing to dispose
throw new NotImplementedException();
}
}
}
using System;
namespace Security_Legacy.Cryptography.Interfaces
{
public interface IEncryptionProvider : IDisposable
{
string Decrypt(string cypheredText);
string Encrypt(string plainText);
}
}