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)_进行解密时如何将其考虑在内?

ASP.NET中的加密,可以在MySQL中使用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));
    }