ASP.NET中的加密,可以在MySQL中使用AES_DECRYPT()进行解密
本文关键字:DECRYPT AES 解密 MySQL 加密 NET ASP | 更新日期: 2023-09-27 18:19:40
我希望能够在ASP.NET中执行应用程序级加密,生成一个字节数组,然后将其保存到MySQL blob列中。然后,我希望它是一个选项,如果你有加密密钥,你可以使用MySQL的AES_decrypt()函数对其进行解密。这似乎是可能的,因为AES_DECRYPT是AES/Rijndael的实现。
MySQL AES_ENCRYPT/DECRYPT函数只需将密钥和要加密/解密的字符串作为参数。然而,我在ASP.NET/C#中看到的加密示例也涉及到为Key和IV(初始化向量)指定值。这些是如何影响最终加密的字节数组的,以及在使用AES_DECRYPT)_进行解密时如何将其考虑在内?
您可以通过将RijndaelManaged
设置为使用ECB模式来实现这一点。
然而,ECB模式并不安全,应该避免。
一般来说,数据库是执行加密的一个非常糟糕的地方。
如果你能够加密数据库中的数据,这意味着你将密文和密钥都放在同一个地方;这违背了加密的目的。
您应该将密钥尽可能远离密文存储;使用任何类型的SQL加密函数通常都表明加密策略中存在根本性的设计缺陷,这可能会带来灾难性的后果。
加密
在Mysql中使用HEX(AES_ENCRYPT('unencryptedString', 'Password'))
示例
UPDATE `secrets` SET `value`=HEX(AES_ENCRYPT('unencryptedString', 'Password')) WHERE `Id` = 2;
你会在数据库中看到一个类似于这个D4B5E4CAD92FFB73FCAEB5ED3B31E9EDD8FA7440E9E3F582FE5A9237DB8EE013
的值
现在C#中的等效代码是(原始来源:链接)
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();
}
使用的Helper方法和扩展
参考链接
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;
}
参考链路
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;
}
使用的Helper方法和扩展
参考链路
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;
}
参考链路
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));
}