【问题标题】:Is this cryptography code secure?这个加密代码安全吗?
【发布时间】:2014-08-18 12:59:13
【问题描述】:

将使用此代码的应用程序必须足够安全,才能在 SECRET 级别加密机密数据。

我知道 rijndaelManaged 类未经 FIPS 批准,但这不会影响安全性,所以我认为只要使用同一个应用程序对文件进行加密和解密,就可以使用此类。

此加密代码对于机密信息是否足够安全?

public static class AESEncryption
{
    private static readonly byte[] initVectorBytes = Encoding.ASCII.GetBytes("tu89geji340t89u2");
    private const int keysize = 256;
    public static string Encrypt(string plainText, string passPhrase)
    {
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
        using (PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null))
        {
            byte[] keyBytes = password.GetBytes(keysize / 8);
            using (RijndaelManaged symmetricKey = new RijndaelManaged())
            {
                symmetricKey.Mode = CipherMode.CBC;
                using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes))
                {
                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                        {
                            cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                            cryptoStream.FlushFinalBlock();
                            byte[] cipherTextBytes = memoryStream.ToArray();
                            return Convert.ToBase64String(cipherTextBytes);
                        }
                    }
                }
            }
        }
    }

    public static string Decrypt(string cipherText, string passPhrase)
    {
        byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
        using (PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null))
        {
            byte[] keyBytes = password.GetBytes(keysize / 8);
            using (RijndaelManaged symmetricKey = new RijndaelManaged())
            {
                symmetricKey.Mode = CipherMode.CBC;
                using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes))
                {
                    using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes))
                    {
                        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                        {
                            byte[] plainTextBytes = new byte[cipherTextBytes.Length];
                            int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
                            return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
                        }
                    }
                }
            }
        }
    }
}

【问题讨论】:

  • 现在已经不是了。
  • 来自wikipedia:“对于 CBC 和 CFB,重用 IV 会泄露一些关于第一个明文块以及两条消息共享的任何公共前缀的信息。”。 CBC,检查。固定(并因此重用)IV,检查。
  • @nsgocev 怎么不安全了? IV应该是公共权利?
  • 1) 没有经过身份验证的加密/MAC 2) KDF 中没有盐 3) 修正了 IV 错过了 IV 的点。你不应该重复使用 (IV, Key) 对。如果您使用盐,这将不是问题,因为这样键将是一次性使用。 4) encryptor.TransformFinalBlock 会产生更简单的代码,因为您不需要那些无用的流。

标签: c# security encryption aes rijndaelmanaged


【解决方案1】:

您没有使用经过身份验证的加密。这允许攻击者修改消息,尽管他无法读取它们。

您正在使用常数 IV。这是信息泄露,因为攻击者可以判断您是否多次加密同一消息。

IV 的目的不是硬编码为某个特定值。让加密 API 为您生成一个。

您很容易受到Padding Oracle 攻击,因为您泄露了检测到无效填充的信息。

除了这些问题,这段代码实际上看起来还不错。

我建议您使用适用于 .NET 的 AES-GCM。它是加密和验证数据的集成原语。很难出错。

【讨论】:

  • 你能解释一下padding oracle攻击以及如何避免它
  • 我不需要 iv 来解密数据
  • google.com/… 您需要将 IV 与加密数据一起存储。通常它是前置的。 IV 不是秘密。
  • @usr 我并不是要按字面意思要求生成随机 iv
  • 我不明白你的问题,因为你真的写了“我怎样才能生成随机静脉注射?”。无论如何,希望您的问题得到解答。
猜你喜欢
  • 2014-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-23
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多