简体   繁体   English

示例代码 PHP / C# AES 加密 - 随机 IV

[英]Example code PHP / C# AES encryption - random IV

I found an implementation for AES encryption/decryption that's supposed to work in PHP and C#: https://odan.github.io/2017/08/10/aes-256-encryption-and-decryption-in-php-and-csharp.html我发现了一个 AES 加密/解密的实现,它应该在 PHP 和 C# 中工作: https : //odan.github.io/2017/08/10/aes-256-encryption-and-decryption-in-php-and- csharp.html

However, in this example, the IV is always 0, which is not good.但是,在本例中,IV 始终为 0,这并不好。 So, as the author suggests, I use the openssl_random_pseudo_bytes() function:所以,正如作者所建议的,我使用 openssl_random_pseudo_bytes() 函数:

  $ivlen = openssl_cipher_iv_length($method);
  $iv = openssl_random_pseudo_bytes($ivlen);

However, the problem now is, that I have to store the IV somewhere so that the C# app can use it for decryption.但是,现在的问题是,我必须将 IV 存储在某处,以便 C# 应用程序可以使用它进行解密。 My idea was to base64_encode it and prepend it to the encrypted message with ":" separating both, so that I can simply split the string, then base64 decode it in C# and can use the IV.我的想法是对它进行 base64_encode 并将其添加到加密消息中,并使用“:”将两者分开,这样我就可以简单地拆分字符串,然后在 C# 中对其进行 base64 解码并可以使用 IV。 However, this does not work.但是,这不起作用。 This is the code:这是代码:

public string DecryptString(string cipherText, byte[] key, byte[] iv)
{
    // Instantiate a new Aes object to perform string symmetric encryption
    Aes encryptor = Aes.Create();

    encryptor.Mode = CipherMode.CBC;

    // Set key and IV
    byte[] aesKey = new byte[32];
    Array.Copy(key, 0, aesKey, 0, 32);
    encryptor.Key = aesKey;
    encryptor.IV = iv;

    // Instantiate a new MemoryStream object to contain the encrypted bytes
    MemoryStream memoryStream = new MemoryStream();

    // Instantiate a new encryptor from our Aes object
    ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();

    // Instantiate a new CryptoStream object to process the data and write it to the 
    // memory stream
    CryptoStream cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);

    // Will contain decrypted plaintext
    string plainText = String.Empty;

    try {
        // Convert the ciphertext string into a byte array
        byte[] cipherBytes = Convert.FromBase64String(cipherText);

        // Decrypt the input ciphertext string
        cryptoStream.Write(cipherBytes, 0, cipherBytes . Length);

        // Complete the decryption process
        cryptoStream.FlushFinalBlock();

        // Convert the decrypted data from a MemoryStream to a byte array
        byte[] plainBytes = memoryStream.ToArray();

        // Convert the decrypted byte array to string
        plainText = Encoding.ASCII.GetString(plainBytes, 0, plainBytes.Length);
    } finally {
        // Close both the MemoryStream and the CryptoStream
        memoryStream.Close();
        cryptoStream.Close();
    }

    // Return the decrypted data as a string
    return plainText;
}

And this is how I try to call the function with the IV prepended to the encrypted message:这就是我尝试在加密消息前添加 IV 来调用函数的方式:

private void btnDecrypt_Click(object sender, EventArgs e)
        {
            string encrypted = txtEncrypted.Text;
            string password = txtPW.Text;
            string[] temp = encrypted.Split(":".ToCharArray());
            string iv_str = temp[0];
            encrypted = temp[1];
            SHA256 mySHA256 = SHA256Managed.Create();
            byte[] key = mySHA256.ComputeHash(Encoding.ASCII.GetBytes(password));
            iv_str = Encoding.Default.GetString(Convert.FromBase64String(iv_str));
            byte[] iv = Encoding.ASCII.GetBytes(iv_str);

            txtDecrypted.Text = this.DecryptString(encrypted, key, iv); 
        }

Doesn't work.不起作用。 It decrypts something, but that's just gibberish and not the message I encrypted in PHP.它解密了一些东西,但这只是胡言乱语,而不是我用 PHP 加密的消息。 I think it has to do with the IV somehow.我认为这与 IV 有某种关系。

@Topaco: Thank you very much... now I see what my mistake was. @Topaco:非常感谢……现在我明白我的错误是什么了。 It works now with generated IV.它现在适用于生成的 IV。 By the way, two more questions on the strength of the encryption:顺便说一下,还有两个关于加密强度的问题:

  1. Is it ok to use the following function to generate an IV (GenerateIV() for some reason won't work):是否可以使用以下函数生成 IV(GenerateIV() 由于某种原因不起作用):

    byte[] iv = new byte[16];字节[] iv = 新字节[16]; Random rnd = new Random();随机 rnd = 新随机(); rnd.NextBytes(iv); rnd.NextBytes(iv);

  2. I added a randomly generated salt to the password of the user, so that the key is a hash from the user password and a salt.我在用户的密码中添加了一个随机生成的盐,因此密钥是用户密码和盐的散列。 I also prepend the salt, together with the now randomly generated IV, to the message.我还将盐与现在随机生成的 IV 一起添加到消息中。 Then for the decryption process I use the prepended salt and the key the user enters.然后对于解密过程,我使用预先添加的盐和用户输入的密钥。 Works so far.到目前为止工作。 But does it weaken the encryption?但是它会削弱加密吗? No, right?没有权利?

Thank you very much.非常感谢。

// Edit: Code format doesn't work, don't know why. // 编辑:代码格式不起作用,不知道为什么。

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

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