【问题标题】:Output is invalid输出无效
【发布时间】:2023-03-28 22:34:02
【问题描述】:

我有一个 PHP 程序,可以将 PDF 文件加密为 .xxx 文件,这个输出正在被一个 C# 程序读取,该程序将这个 .xxx 文件解密回 PDF 文件。

我的问题是,当我打开由 C# 解密的文件时,PDF 阅读器告诉我文件已损坏.. 当我在 PHP 中加密纯文本并在 C# 上解密时,我得到了我加密的文件.. 所以问题仅出现在 PDF 文件中,或者换句话说,它出现在 BINARY 文件中

有什么建议吗?!

注意事项:

  1. 在 PHP 中我使用 mcrypt 扩展 Rijndael 算法 CBC PKCS7 填充(填充是手动完成的)
  2. 在 C# 中,我使用 RijndaelManaged 类来加密和解密数据

编辑

这是我在 PHP 中使用的加密方法:

    function encrypt($key, $iv, $text) {
        ini_set ( 'memory_limit', '-1' );
        $mcrypt_cipher = MCRYPT_RIJNDAEL_256;
        $mcrypt_mode = MCRYPT_MODE_CBC;
        $text=addpadding($text,mcrypt_get_block_size($mcrypt_cipher,'cbc'));
        $encrypted = rtrim ( mcrypt_encrypt ( $mcrypt_cipher, $key, $text, $mcrypt_mode, $iv ), "\0" );
        $encrypted = base64_encode ( $encrypted );
        return $encrypted;
    }

这里是C#中的解密方法:

    public static string DecryptString(string message, string KeyString, string IVString)
    {
        byte[] Key = Encoding.UTF8.GetBytes(KeyString);
        byte[] IV = Encoding.UTF8.GetBytes(IVString);

        string decrypted = null;
        RijndaelManaged rj = new RijndaelManaged();
        rj.BlockSize = 256;
        rj.Key = Key;
        rj.IV = IV;
        rj.Mode = CipherMode.CBC;
        rj.Padding = PaddingMode.PKCS7;
        try
        {
            MemoryStream ms = new MemoryStream();
            //Encoding enc = new UTF8Encoding();
            byte[] messageBytes = Convert.FromBase64String(message);
            using (CryptoStream cs = new CryptoStream(ms, rj.CreateDecryptor(Key, IV), CryptoStreamMode.Write))
            {
                //byte[] messageBytes = enc.GetBytes(message);

                cs.Write(messageBytes, 0, messageBytes.Length);
                cs.Close();
            }
            byte[] encoded = ms.ToArray();
            decrypted = Encoding.UTF8.GetString(encoded);

            ms.Close();
        }
        catch (Exception e)
        {
            MessageBox.Show("An error occurred:"+ e.Message);
        }
        finally
        {
            rj.Clear();
        }

        return decrypted;
    }

这是我在 C# 中如何调用解密以及如何编写输出:

                string Key = cryptography.MD5("X-Ware" + cryptography.MD5("123"));
                string IV = cryptography.MD5("XWare");
                string decrypted = cryptography.DecryptString(contents, Key, IV);
                string outputFilename = cryptography.MD5(OFD.FileName) + ".tmp";

                StreamWriter sw = new StreamWriter("C:\\Windows\\Temp\\" + outputFilename, false, Encoding.UTF8);
                BinaryWriter bw = new BinaryWriter(sw.BaseStream, Encoding.UTF8);
                //sw.Write(decrypted);
                bw.Write(decrypted);
                sw.Close();
                bw.Close();

【问题讨论】:

  • 您能粘贴一下您是如何进行编码/解码的吗?
  • 解密后的文件大小和原来的一样吗?
  • @JoachimIsaksson 在 Windows 上是 .......
  • @Bandpay 实际上没有...解密的比原来的大
  • 我很确定问题出在fopen,你用'rb'吗?

标签: c# php encryption rijndaelmanaged rijndael


【解决方案1】:

我认为问题在于您在 PHP 和 C# 端都将二进制 PDF 数据视为文本。

 decrypted = Encoding.UTF8.GetString(encoded);

如果encoded 代表二进制数据,则没有意义。您可能应该跳过这一步并将您的DecryptString() 定义为返回byte[]。然后也重命名它。

如果您确实希望将其作为字符串,则使用 ASCII 或 ANSI 编码可能会更好:

 decrypted = Encoding.ASCII.GetString(encoded);

但错误可能已经发生在 PHP 端,我不知道。

另外,我刚刚注意到:

    StreamWriter sw = new StreamWriter("C:\\Windows\\Temp\\" + outputFilename,  
           false, Encoding.UTF8);
    BinaryWriter bw = new BinaryWriter(sw.BaseStream, Encoding.UTF8);

这是创建 BinaryWriter 的一种非常复杂的方法。将不使用编码。和

 bw.Write(decrypted);

这将写入带有长度前缀的字符串,这肯定会使您的 PDF 无效。

当你保持 Decrypt 的返回为string 时,使用

  File.WriteAllText("C:\\Windows\\Temp\\" + outputFilename, decrypted);

当您将其返回为byte[](推荐)时,请使用

 File.WriteAllBytes("C:\\Windows\\Temp\\" + outputFilename, decrypted);

【讨论】:

  • 另外,虽然我在不阅读有关方法的所有文档的情况下不确定这一点,但数据似乎在 php 中填充,但在 C# 中从未“未填充”。
  • @Joachim:OP 声明该过程适用于文本数据,这让我认为默认填充设置是可以的。
  • 是的,我绝对不确定这是否是个问题,但我最终会看到文件大小相同 :)
  • @HenkHolterman 非常感谢它现在工作正常,通过编辑代码返回字节数组而不是字符串
  • @JoachimIsaksson 我在 PHP 中构建了一个填充方法以兼容 C# 填充模式 =PKCS#7
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-17
  • 1970-01-01
  • 1970-01-01
  • 2019-11-11
  • 1970-01-01
  • 2016-11-14
  • 2018-06-16
相关资源
最近更新 更多