简体   繁体   English

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

[英]AES _Encryption in Mysql , Decryption in C#.Net

Mysql : mysql :

SELECT AES_ENCRYPT('Test','pass')

AES_ENCRYPT() and AES_DECRYPT() enable encryption and decryption of data using the official AES (Advanced Encryption Standard) algorithm, previously known as “Rijndael.” AES_ENCRYPT() 和 AES_DECRYPT() 使用官方 AES(高级加密标准)算法(以前称为“Rijndael”)启用数据加密和解密。 Encoding with a 128-bit key length is used, but you can extend it up to 256 bits by modifying the source.使用了 128 位密钥长度的编码,但您可以通过修改源将其扩展到 256 位。 We chose 128 bits because it is much faster and it is secure enough for most purposes.我们选择 128 位是因为它更快,并且对于大多数用途来说足够安全。

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

I was trying to convert that Encrypted string into Decryped Strig in C#.net but i don't get the results as i expect.我试图在 C#.net 中将该加密字符串转换为 Decryped Strig,但我没有得到预期的结果。

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

C# C#

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

In this method I pass ciphertext,Key value which i usedfrom Mysql and Rijndael.Create().IV for byte[] IV在这种方法中,我传递密文,我使用的密钥值来自 Mysql 和 Rijndael.Create().IV for byte[] IV

I use the code but i don't get expected result.我使用了代码,但没有得到预期的结果。 Review the code and comment Idk where made a mistake查看代码并注释Idk 哪里出错了

What you are doing is following a road of pain.你所做的,是在走一条痛苦的道路。 Either decrypt/encrypt on MySQL and use an encrypted connection to the database (if that matters) or encrypt/decrypt on your .NET application, storing the encrypted data in a suitable column.在 MySQL 上解密/加密并使用到数据库的加密连接(如果重要)或在 .NET 应用程序上加密/解密,将加密数据存储在合适的列中。

Mixing AES implementations is prone to mistakes and things can break more easily if you change versions of .NET or MySQL.混合 AES 实现容易出错,如果您更改 .NET 或 MySQL 的版本,事情会更容易崩溃。

Now, to know what exactly is wrong we need to know if the IV is compatible between MySQL and .NET, or else find out what is MySQL's implementation IV and supply that.现在,要知道究竟出了什么问题,我们需要知道 IV 在 MySQL 和 .NET 之间是否兼容,或者找出 MySQL 的实现 IV 并提供它。

And the other potential source of problems is how you have generated the byte arrays (we are not seeing that in your example).另一个潜在的问题来源是您如何生成字节数组(我们在您的示例中没有看到)。 You have to consider character encoding issues in generating the arrays if the key is textual.如果键是文本键,则在生成数组时必须考虑字符编码问题。

In the comments of this MySQL docs link there is information about the missing parameters.此 MySQL 文档链接的评论中,有关于缺失参数的信息。

After a long hours, I found a solution to this issue.经过很长时间,我找到了解决此问题的方法。

Couple of FYI's:几个仅供参考:

  • MySQL as a default for AES_Encrypt uses 128 bit, with ECB mode, which does not require an IV. MySQL 作为 AES_Encrypt 的默认值使用 128 位,采用 ECB 模式,不需要 IV。
  • What padding mode they use is not specified, but they do say they pad it.没有指定他们使用什么填充模式,但他们确实说他们填充它。 For padding I use PaddingMode.Zeros.对于填充,我使用 PaddingMode.Zeros。
  • In C#, use AesManaged, not RijndaelManaged since that is not recommended anymore.在 C# 中,使用 AesManaged,而不是 RijndaelManaged,因为不再推荐使用。
  • If your Key is longer than 128 bits (16 bytes), then use a function below to create the correct key size, since the default MySQL AES algorithm uses 128 bit keys.如果您的密钥长于 128 位(16 字节),则使用下面的函数来创建正确的密钥大小,因为默认的 MySQL AES 算法使用 128 位密钥。
  • Make sure you play around with the correct Encoding and know exactly what type of character encoding you will receive back when translating the bytes to characters.确保您使用正确的编码,并确切知道在将字节转换为字符时您将收到什么类型的字符编码。

For more info go here: https://forums.mysql.com/read.php?38,193084,195959#msg-195959有关更多信息,请访问: https : //forums.mysql.com/read.php?38,193084,195959#msg-195959

Code:代码:


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

Here is some working code for achieving the same encryption via C# as MySQL:下面是一些通过 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;
}

For details see MySQL Bug # 16713有关详细信息,请参阅MySQL 错误 # 16713

EDIT:编辑:

Since the above is relying on officially non-documented information (though it is working) I would recommend to avoid it and use one of the options described in the answer from Vinko Vrsalovic .由于上述依赖于官方未记录的信息(尽管它正在工作),我建议避免它并使用Vinko Vrsalovic答案中描述的选项之一。

If you run SELECT AES_ENCRYPT('Test','pass') your are sending the pass over the network unencrypted so any one can unencrypted the data.如果您运行 SELECT AES_ENCRYPT('Test','pass') 您正在通过未加密的网络发送通行证,因此任何人都可以对数据进行未加密。

The AES_ENCRYPT is used to store data so if the database gets hacked your data is safe, not to transmit data. AES_ENCRYPT 用于存储数据,因此如果数据库被黑客入侵,您的数据是安全的,而不是传输数据。

if you want data encryption over the net work connect to your mysql server using the ssl socket如果您想通过网络进行数据加密,请使用 ssl 套接字连接到您的 mysql 服务器

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM