1

I would like to be able to perform application-level encryption in ASP.NET, producing an array of bytes that would then be saved to a MySQL blob column. I would then like it to be an option that, if you have the encryption key, you would be able to decrypt it using MySQL's AES_DECRYPT() function. This seems like it should be possible, since AES_DECRYPT is an implementation of AES/Rijndael.

The MySQL AES_ENCRYPT/DECRYPT functions simply take a key and the string to encrypt/decrypt as parameters. The examples i've seen for encryption in ASP.NET/C#, however, involve also specifying values for Key and IV (initialization vector). How do these affect the final, encrypted byte array, and how can they be taken into account when decrypting with AES_DECRYPT)_?

4

2 回答 2

5

可以通过设置RijndaelManaged使用ECB 模式来做到这一点。

但是,ECB 模式并不安全,应该避免。


通常,数据库是执行加密的非常糟糕的地方。

如果您能够加密数据库中的数据,则意味着您将密文和密钥放在同一个地方;这违背了加密的目的。

您应该将密钥尽可能远离密文存储;使用任何类型的 SQL 加密函数通常表明您的加密策略存在根本设计缺陷,这可能会产生灾难性后果。

于 2013-06-25T00:04:57.343 回答
1

加密

在 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();
    }

使用的辅助方法和扩展

参考链接

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;
    }

使用的辅助方法和扩展

参考链接

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));
    }
于 2020-04-18T22:51:45.340 回答