Mysql中的AES _Encryption,C#.Net中的解密

时间:2011-10-10 11:56:29

标签: c# .net mysql security aes

Mysql:

SELECT AES_ENCRYPT('Test','pass')

AES_ENCRYPT()和AES_DECRYPT()使用官方AES(高级加密标准)算法(以前称为“Rijndael”)启用数据加密和解密。使用128位密钥长度的编码,但您可以扩展它通过修改源最多256位。我们选择了128位,因为它更快,并且对于大多数用途来说足够安全。

http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html#function_aes-encrypt

我试图将该加密字符串转换为C#.net中的Decryped Strig,但我没有得到我期望的结果。

http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndael.aspx#Y0

C#

static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)

在这个方法中,我传递密文,我使用的密钥值来自Mysql和 Rijndael.Create()。IV for byte [] IV

我使用代码,但我没有得到预期的结果。 查看代码并评论Idk哪里出错了

4 个答案:

答案 0 :(得分:1)

以下是一些通过C#实现与MySQL相同加密的工作代码:

public byte[] AESEncrypt(byte[] plaintext, byte[] key) {
/* 
* Block Length: 128bit
* Block Mode: ECB
* Data Padding: Padded by bytes which Asc() equal for number of padded bytes (done automagically)
* Key Padding: 0x00 padded to multiple of 16 bytes
* IV: None
*/
RijndaelManaged aes = new RijndaelManaged();
aes.BlockSize = 128;
aes.Mode = CipherMode.ECB;
aes.Key = key;

ICryptoTransform encryptor = aes.CreateEncryptor();
MemoryStream mem = new MemoryStream();
CryptoStream cryptStream = new CryptoStream(mem, encryptor,
CryptoStreamMode.Write);

cryptStream.Write(plaintext, 0, plaintext.Length);
cryptStream.FlushFinalBlock();

byte[] cypher = mem.ToArray();

cryptStream.Close();
cryptStream = null;
encryptor.Dispose();
aes = null;

return cypher;
}

有关详细信息,请参阅MySQL Bug # 16713

编辑:

由于上述内容依赖于官方未记录的信息(尽管它有效),我建议避免使用它并使用answer from Vinko Vrsalovic中描述的其中一个选项。

答案 1 :(得分:1)

你正在做的是走一条痛苦的道路。要么对MySQL进行解密/加密,要么使用加密连接到数据库(如果这很重要),要么在.NET应用程序上加密/解密,将加密数据存储在合适的列中。

混合AES实现容易出错,如果更改.NET或MySQL的版本,事情就会更容易破解。

现在,要知道究竟什么是错的,我们需要知道IV和MySQL是否兼容,或者找出MySQL的实现IV并提供它。

另一个潜在的问题来源是如何生成字节数组(我们在您的示例中没有看到)。如果密钥是文本的,则必须考虑生成数组时的字符编码问题。

this MySQL docs link的评论中,有关于缺失参数的信息。

答案 2 :(得分:1)

如果你运行SELECT AES_ENCRYPT('Test','pass') 您正在通过网络发送未加密的通行证,以便任何人都可以解密数据。

AES_ENCRYPT用于存储数据,因此如果数据库被黑客攻击,您的数据是安全的,而不是传输数据。

如果您希望通过网络连接到您的mysql服务器的数据加密使用ssl套接字

答案 3 :(得分:1)

经过很长时间,我找到了解决此问题的方法。

仅供参考:

  • MySQL作为AES_Encrypt的默认设置,使用ECB模式的128位,不需要IV。
  • 未指定他们使用哪种填充模式,但他们确实说要填充它。对于填充,我使用PaddingMode.Zeros。
  • 在C#中,请使用AesManaged,而不要使用RijndaelManaged,因为不再建议这样做。
  • 如果您的密钥长于128位(16字节),请使用下面的函数创建正确的密钥大小,因为默认的MySQL AES算法使用128位密钥。
  • 请确保您使用正确的编码,并确切知道将字节转换为字符时将收到的哪种字符编码。

有关更多信息,请访问此处:https://forums.mysql.com/read.php?38,193084,195959#msg-195959

代码:


public static string DecryptAESStringFromBytes(byte[] encryptedText, byte[] key)
{
    // Check arguments.
    if ((encryptedText == null || encryptedText.Length <= 0) || (key == null || key.Length <= 0))
    {
        throw new ArgumentNullException("Missing arguments");
    }

    string decryptedText = null;

    // Create an AES object with the specified key and IV.
    using (AesManaged aesFactory = new AesManaged())
    {
        aesFactory.KeySize = 128;
        aesFactory.Key = AESCreateKey(key, aesFactory.KeySize / 8);
        aesFactory.IV = new byte[16];
        aesFactory.BlockSize = 128;
        aesFactory.Mode = CipherMode.ECB;
        aesFactory.Padding = PaddingMode.Zeros;

        // Create a decryptor to perform the stream transform.
        ICryptoTransform decryptor = aesFactory.CreateDecryptor();

        // Create the streams used for decryption.
        using (MemoryStream stream = new MemoryStream())
        {
            using (CryptoStream decryptStream = new CryptoStream(stream, decryptor, CryptoStreamMode.Write))
            {
                decryptStream.Write(encryptedText, 0, encryptedText.Length);
            }

            decryptedText = Encoding.Default.GetString(stream.ToArray());
        }
    }

    return decryptedText.Trim();
}

public static byte[] AESCreateKey(byte[] key, int keyLength)
{
    // Create the real key with the given key length.
    byte[] realkey = new byte[keyLength];

    // XOR each byte of the Key given with the real key until there's nothing left.
    // This allows for keys longer than our Key Length and pads short keys to the required length. 

    for (int i = 0; i < key.Length; i++)
    {
        realkey[i % keyLength] ^= key[i];
    }

    return realkey;
}