C# 正确使用AESCryptServiceProvider

C# 正确使用AESCryptServiceProvider,c#,encryption,cryptography,aes,C#,Encryption,Cryptography,Aes,我正在尝试编写一些直接的加密例程。以下是我在网上搜索的结果 public string Encrypt(string plainText) { byte[] encrypted; // Create an AesCryptoServiceProvider object // with the specified key and IV. using (AesCryptoServiceProvider aesAlg = new AesCryptoServicePro

我正在尝试编写一些直接的加密例程。以下是我在网上搜索的结果

public string Encrypt(string plainText)
{
    byte[] encrypted;

    // Create an AesCryptoServiceProvider object
    // with the specified key and IV.
    using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
    {
        // Create an encryptor to perform the stream transform.
        ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

        // Create the streams used for encryption.
        using (MemoryStream msEncrypt = new MemoryStream())
        {
            msEncrypt.WriteByte((byte)aesAlg.Key.Length);
            msEncrypt.Write(aesAlg.Key, 0, aesAlg.Key.Length);
            msEncrypt.WriteByte((byte)aesAlg.IV.Length);
            msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length);

            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            {
                using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                {
                    //Write all data to the stream.
                    swEncrypt.Write(plainText);
                }
                encrypted = msEncrypt.ToArray();
            }
        }
    }
    return Convert.ToBase64String(encrypted);
}

public string Decrypt(string cipherText)
{
    string plaintext = null;

    using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
    {
        // Create the streams used for decryption.
        using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
        {
            int l = msDecrypt.ReadByte();
            byte[] key = new byte[l];
            msDecrypt.Read(key, 0, l);
            l = msDecrypt.ReadByte();
            byte[] IV = new byte[l];
            msDecrypt.Read(IV, 0, l);

            // Create a decryptor to perform the stream transform.
            ICryptoTransform decryptor = aesAlg.CreateDecryptor(key, IV);

            using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
            using (StreamReader srDecrypt = new StreamReader(csDecrypt))
            {

                // Read the decrypted bytes from the decrypting stream
                // and place them in a string.
                plaintext = srDecrypt.ReadToEnd();
            }
        }
    }
    return plaintext;
}
两个问题:

  • 首先,我找到的大多数示例都是硬编码的
    IV
    。所以我要做的是将它写入加密的字节。这将使我的加密数据更大。有更好的办法吗
  • 另外,我没有使用任何密码。是否会使用密码生成自定义
    密钥
    ?如果是这样,我怎么知道钥匙需要多长时间
首先,我发现的大多数示例都是硬编码的密钥和IV。所以我要做的是将其写入加密的字节。这将使我的加密数据更大。有更好的办法吗

显然,您不应该将密钥写入未受保护的流,因为密钥需要提前共享或建立并保持机密。秘密密钥的共享可以通过多种方式执行,从密钥协商到密钥派生、棘轮等

另外,我没有使用任何密码。会使用密码生成自定义密钥吗?如果是这样,我怎么知道钥匙需要多长时间

这是可能的。然而,提醒自己,密码通常不是很强,所以如果可以避免基于密码的加密(PBE),那么这样做可能是一个好主意

如果从密码派生密钥,则应使用基于密码的密钥派生函数(有时也称为密码哈希)。在C#中,有一个PBKDF2(糟糕)的实现,称为
Rfc2898DeriveBytes
。到目前为止,这也不是很先进,但它应该足够了——不管怎样,只要您设置了足够高的迭代计数


当您从人类记忆的密码中派生出密钥时,128位就足够了。几乎没有任何方法可以比用来派生密钥的密码更容易找到密钥。

谢谢。我将研究如何对密码进行哈希运算。那
IV
呢?解密时确保我拥有正确的
IV
数据的最佳方法是什么?哦,对不起。是的,如果静脉注射是随机的,你可以简单地加上前缀,然后像你看起来已经做的那样读回。对于CBC模式(默认模式),IV需要对攻击者不可预测,但不需要保密。如果您使用的是CBC模式,那么处理IV和填充开销是很棘手的。我需要为模式或填充做些什么吗,或者我应该在那里做些什么吗?没有默认设置是可以的。通常我会建议去使用CTR模式,但对于.NET,由于一些奇怪的原因或其他原因,它默认不包括在内。有了CTR,您可以使用nonce作为“IV”,CTR模式不需要任何填充。我认为CFB在那个里,但CFB和OFB几乎不再使用了。