我有一个项目要求,我需要使用AES和我提供的密钥/ IV(初始化向量)加密/解密我的应用程序(c#.net)中的字符串。
很容易。
如果它变得更加混乱,我还要求我必须能够使用SQL解密字符串。这是我开始挣扎的地方。
以下是我使用的代码(c#.net)来加密我的字符串:
public string Encrypt(string str)
{
byte[] IV = { 57, 87, 122, 110, 97, 109, 111, 53, 65, 95, 114, 101, 120, 73, 72, 84 };
string key = "MKE7612Y4ADF8JD1";
byte[] clearBytes = Encoding.UTF8.GetBytes(str);
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
using (Aes encryptor = Aes.Create())
{
encryptor.Key = keyBytes;
encryptor.IV = IV;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
str = Convert.ToBase64String(ms.ToArray());
}
}
return str;
}
这一切都很有效:
string encrypted = Encrypt("UAT-6127592");
// returns: 9ZzHICvqQsm/ZI/Uuh8QLQ==
这正是我所期待的。现在到了我正在努力的部分 - 能够从SQL解密它。
我正在尝试使用对称密钥执行此操作,如下所示:
USE tempdb;
CREATE SYMMETRIC KEY AES128SecureSymmetricKey
WITH
ALGORITHM = AES_128, -- based on the length of my key
IDENTITY_VALUE = N'9Wznamo5A_rexIHT', -- the UTF8 equivalent of the decimal IV entered from my c# code above
KEY_SOURCE = N'MKE7612Y4ADF8JD1' -- the same key I used in my c# code above
ENCRYPTION BY PASSWORD = N'MKE7612Y4ADF8JD1';
OPEN SYMMETRIC KEY AES128SecureSymmetricKey
DECRYPTION BY PASSWORD = N'MKE7612Y4ADF8JD1';
DECLARE @strBase64 NVARCHAR(max);
SET @strBase64 = N'9ZzHICvqQsm/ZI/Uuh8QLQ=='; -- for testing, just hard coding the same string I encoded above
-- Converting the base64 string to HEX
DECLARE @strHex VARBINARY(MAX);
SET @strHex = CAST(N'' as xml).value('xs:base64Binary(sql:variable("@strBase64"))', 'varbinary(MAX)');
-- Try to decrypt the value
DECLARE @decrypted_hex_with_key NVARCHAR(MAX);
SET @decrypted_hex_with_key = DecryptByKey(@strHex);
SELECT CONVERT(NVARCHAR(256), @decrypted_hex_with_key) AS DecryptedValue;
-- close and drop the key
CLOSE SYMMETRIC KEY AES128SecureSymmetricKey;
DROP SYMMETRIC KEY AES128SecureSymmetricKey;
上面的查询结果为“DecryptedValue”返回NULL。
我很确定我没有在上面的查询中正确使用键值和IV值。我已经尝试了(看起来像)一千种组合,但却无法使其正常工作。
任何人都能对我做错了什么提供一些见解吗?
我对密码学世界有点新意,所以我很有可能离开这里! :)
感谢您的帮助!!!
答案 0 :(得分:0)
您的代码存在问题,就是将SQL Server中的IDENTITY_VALUE和.NET中的初始化矢量(IV)视为相同。他们不是。 IV是用于随机化密文的标准参数,而IDENTITY_VALUE是SQL Server特定的密钥标识符。有关更多详细信息,请参见我的答案here。
SQL Server的方法需要包含特定元数据的密文,并且不允许您显式传递IV。最好的选择是将解密留给应用程序层。如果确实需要,可以尝试在SQL Server中将SQLCLR与.NET代码一起使用。听起来这是个坏主意,因为您必须以某种方式与SQL Server共享主密钥。