Reputation: 3110
I have created two methods in C#:
public static string Encrypt(string clearText, string encryptionKey)
{
byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
var pdb = new Rfc2898DeriveBytes(encryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
}
return clearText;
}
public static string Decrypt(string cipherText, string encryptionKey)
{
try
{
byte[] cipherBytes = Convert.FromBase64String(cipherText);
using (Aes encryptor = Aes.Create())
{
var pdb = new Rfc2898DeriveBytes(encryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
cipherText = Encoding.Unicode.GetString(ms.ToArray());
}
}
}
catch (Exception)
{
}
return cipherText;
}
By following the steps given in This Link, I have created a CLR function in SQL Server and I am trying to call it like:
SELECT dbo.Decrypt(MyEncrypted, EncryptionKey)
FROM MyTable
The problem is, it is taking TOO MUCH TIME. Like for only 1000 rows, it took 1.5 minutes. If I call my query without the CLR function, it took less than 1 second.
Is there any thing I can do to improve the performance of the CLR functions?
Upvotes: 1
Views: 1329
Reputation: 42434
I've analyzed your Decrypt
method with the Performance Analyzer in VS2010 by running it 100 times:
As you can see the GetBytes
method of the Rfc2898DeriveBytes
instance take the most time.
I'm not sure why you have these specific encryption/decryption requirements but one way influence the time the GetBytes
method takes is to instantiate the Rfc2898DeriveBytes
using the constructor that takes iterations as the third parameter. Default it is on 1000, I can set it as low as 1. BUT THIS IS STRONGLY ADVISED AGAINST
var pdb = new Rfc2898DeriveBytes(encryptionKey, salt, 10);
This iterations does need to be the same for both the Encrypt
and Decrypt
so you'll have to Decrypt\Encrypt your current values if you want to change that.
One other option might be to cache the IV values as seems to recommended in this answer. I'm not enough of an expert if they talk there about using the same Key as well but if that is an option you might cache the call to GetBytes
for the key as well.
All the described change have impact on how your data is encrypted and the strength of your encryption. Consider both impacts when testing the solutions.
Upvotes: 1