【问题标题】:Decrypting PKCS#5 Padded AES/ECB With Unknown IV使用未知 IV 解密 PKCS#5 填充的 AES/ECB
【发布时间】:2014-01-17 09:54:35
【问题描述】:

所以我正在制作一个程序,该程序从服务器检索图像,该图像在 AES/ECB 中加密并使用 PKCS#5 填充。我知道用于加密图像的单个同步密钥(M02cnQ51Ji97vwT4),但是,在我用来解密它的代码中,它需要我输入一个我不知道其值的 IV。

这是我用来解密它的代码:

public static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
    {
        // Check arguments. 
        if (cipherText == null || cipherText.Length <= 0)
            throw new ArgumentNullException("cipherText");
        if (Key == null || Key.Length <= 0)
            throw new ArgumentNullException("Key");
        if (IV == null || IV.Length <= 0)
            throw new ArgumentNullException("Key");

        // Declare the string used to hold 
        // the decrypted text. 
        string plaintext = null;

        // Create an RijndaelManaged object 
        // with the specified key and IV. 
        using (RijndaelManaged rijAlg = new RijndaelManaged())
        {
            rijAlg.Key = Key;
            rijAlg.IV = IV;

            // Create a decrytor to perform the stream transform.
            ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);

            // Create the streams used for decryption. 
            using (MemoryStream msDecrypt = new MemoryStream(cipherText))
            {
                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;
    }

这是我正在调用的用于解密图像的当前代码,然后将其放到我的桌面:

Byte[] lnByte = Encoding.UTF8.GetBytes(General.DecryptStringFromBytes(reader.ReadBytes(1 * 1024 * 1024 * 10), Encoding.UTF8.GetBytes("M02cnQ51Ji97vwT4"), Encoding.UTF8.GetBytes("\0"))); 
                using (FileStream lxFS = new FileStream("C:\\Users\\Admin\\Desktop\\image.jpg", FileMode.Create))
                {
                    lxFS.Write(lnByte, 0, lnByte.Length);
                }

此代码运行没有任何错误,但是当我打开它保存的图像时,它说它已损坏或损坏。

现在将 IV 设置为“\0”的原因是因为这是我在网上找到的,但它不起作用。

如果我必须将 IV 设置为什么,我们将不胜感激。谢谢。

【问题讨论】:

  • 您不必用rijAlg.Mode = CipherMode.ECB; 指定模式(即ECB)吗?否则,它将默认使用 CBC。
  • @bgamlath 没有意识到我必须这样做,谢谢。现在我该如何处理 IV?
  • 先用0 IV检查一下,如果没有,恐怕你必须以某种方式找到它..:-)
  • @bgamlath ECB 模式不使用 IV,因此您不必出示它。请注意,零 IV 应包含一个零值字节块(在这种情况下为 16,或者属性值 rijAlg.BlockSize / 8
  • 请注意,一般情况下,不应使用 ECB 模式,并且密码与密钥不同。因此,即使它在底层使用了 AES,该协议也并不像应有的那样安全。

标签: c# encryption cryptography aes


【解决方案1】:

ECB 模式不需要 IV。但如果我没记错的话,RijndaelManaged 默认为 CBC。因此,您使用的解密模式与用于加密的模式不同。最好不要对密钥大小、加密模式或填充模式等使用默认值。

在将加密模式显式设置为 ECB 并将填充模式设置为 PKCS#7 填充后重试。您不必为 ECB 提供 IV。

如果您必须为实现提供它,请提供一个全为零的 IV。在 CBC 模式下,IV 与第一个明文块进行异或运算,因此很容易看出全零的 IV 没有多大作用。

如果您使用具有零 IV 的 CBC 而不是 ECB,那么前 16 个字节(一个块)将是正确的。之后的所有块都是随机的。大多数时候你会在最后收到一个填充错误,但你可能是“幸运的”(大约 256 次)并在最后得到一个正确的填充。


此外,您将图像转换为字符编码(字符串)并返回。这将导致大部分时间数据丢失。相反,您应该将图像视为二进制。

public static void DecryptStringFromBytes(byte[] cipherText, byte[] Key, Stream stream)
{
   // ...

   // Don't use StreamReader

   csDecrypt.CopyTo(stream)

   // ...
}

现在将您生成的FileStream 作为最后一个参数提供给方法。

【讨论】:

  • 感谢您的信息。我试过你说的,但是当我打开图像时,它说它损坏了,损坏了,或者太大了。
  • 啊,那是因为图像由字节组成,而不是字符。从等式中删除 StreamReader,并从您的方法中返回 byte[] 而不是字符串。
  • 我应该调用什么方法?我使用 CryptoStream 吗?
  • 是的,CryptoStream 返回二进制文件。
  • 我应该调用哪种方法?
【解决方案2】:

ECB 模式不需要 IV。 CBC 模式需要 IV,CTR 模式需要 Nonce。一个全为零的 IV 等同于没有 IV。在某些情况下,IV 会预先添加到密文中,因此您可以尝试将第一个输入块用作其余部分的 IV。

顺便说一句,ECB 模式并不安全。维基百科中有一个很好的说明:ECB Mode

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-02
    相关资源
    最近更新 更多