我希望能够在ASP.NET中执行应用程序级加密,生成一个字节数组,然后将其保存到MySQL blob列。我希望它是一个选项,如果你有加密密钥,你将能够使用MySQL的AES_DECRYPT()函数解密它。这似乎应该是可能的,因为AES_DECRYPT是AES / Rijndael的实现。
MySQL AES_ENCRYPT / DECRYPT函数只需要一个密钥和字符串来加密/解密作为参数。但是,我在ASP.NET / C#中看到的用于加密的示例还涉及指定Key和IV(初始化向量)的值。这些如何影响最终的加密字节数组,以及在使用AES_DECRYPT解密时如何将它们考虑在内?_)
答案 0 :(得分:5)
can do that设置RijndaelManaged
以使用ECB mode。
但是,ECB模式并不安全,应该避免使用。
通常,数据库是执行加密的非常糟糕的地方。
如果您能够加密数据库中的数据,这意味着您在同一个地方同时拥有密文和密钥;这违背了加密的目的。
您应该尽可能远离密文存储密钥;使用任何类型的SQL加密函数通常表示加密策略中的基本设计缺陷可能带来灾难性的后果。
答案 1 :(得分:0)
加密
在Mysql中使用HEX(AES_ENCRYPT('unencryptedString', 'Password'))
示例
UPDATE `secrets` SET `value`=HEX(AES_ENCRYPT('unencryptedString', 'Password')) WHERE `Id` = 2;
您将在数据库中看到一个与此D4B5E4CAD92FFB73FCAEB5ED3B31E9EDD8FA7440E9E3F582FE5A9237DB8EE013
现在C#中的等效代码为(原始来源:link)
public static String AES_encrypt(String Input, string key)
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 128;
aes.BlockSize = 128;
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.PKCS7;
aes.Key = mkey(key);
aes.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] xBuff = null;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
{
byte[] xXml = Encoding.UTF8.GetBytes(Input);
cs.Write(xXml, 0, xXml.Length);
cs.FlushFinalBlock();
}
xBuff = ms.ToArray();
}
return xBuff.ToHexString();
}
使用的辅助方法和扩展
参考Link
private static byte[] mkey(string skey)
{
byte[] key = Encoding.UTF8.GetBytes(skey);
byte[] k = new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
for (int i = 0; i < key.Length; i++)
{
k[i % 16] = (byte)(k[i % 16] ^ key[i]);
}
return k;
}
参考Link
public static class ByteArrayExtensions
{
public static string ToHexString(this byte[] ba)
{
return BitConverter.ToString(ba).Replace("-", "");
}
}
解密
在Mysql中使用CAST(AES_DECRYPT(UNHEX(c.value), 'Password') as char)
示例
SELECT c.*,CAST(AES_DECRYPT(UNHEX(c.`value`), 'Password') as char) FROM `secrets` as c where `Id` = 2;
C#中的等效代码是
public static String AES_decrypt(String Input, string key)
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 128;
aes.BlockSize = 128;
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.PKCS7;
aes.Key = mkey(key);
aes.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
var decrypt = aes.CreateDecryptor();
byte[] encryptedStr = Input.FromHex2ByteArray();
string Plain_Text;
using (var ms = new MemoryStream(encryptedStr))
{
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(cs))
{
Plain_Text = reader.ReadToEnd();
}
}
}
return Plain_Text;
}
使用的辅助方法和扩展
参考Link
private static byte[] mkey(string skey)
{
byte[] key = Encoding.UTF8.GetBytes(skey);
byte[] k = new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
for (int i = 0; i < key.Length; i++)
{
k[i % 16] = (byte)(k[i % 16] ^ key[i]);
}
return k;
}
参考Link
public static byte[] FromHex2ByteArray(this string hex)
{
if (hex.Length % 2 == 1)
throw new Exception("The binary key cannot have an odd number of digits");
byte[] arr = new byte[hex.Length >> 1];
for (int i = 0; i < hex.Length >> 1; ++i)
{
arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1])));
}
return arr;
}
private static int GetHexVal(char hex)
{
int val = (int)hex;
//For uppercase A-F letters:
//return val - (val < 58 ? 48 : 55);
//For lowercase a-f letters:
//return val - (val < 58 ? 48 : 87);
//Or the two combined, but a bit slower:
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
}