输出无效

发布于 2024-12-26 18:51:14 字数 2889 浏览 2 评论 0原文

我有一个 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();

I have a PHP program that encrypts a PDF file into .xxx file this output is being read by a C# program that decrypts this .xxx file back into PDF file.

My problem is that when I open the file decrypted by C# , the PDF reader tells me that the file is corrupted .. when I encrypt plain text in PHP and decrypt on C# I got the file I encrypted .. so the problem is appearing only in PDF files or in other words it appears in BINARY files

any suggestions ?!

Notes:

  1. In PHP I use mcrypt extension Rijndael algorithm CBC PKCS7 padding (padding is done manually)
  2. In C# I use RijndaelManaged class to encrypt and decrypt data

Edit:

Here is encryption method that I use in 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;
    }

And here is the decryption method in 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;
    }

and here is how I call the decrypt in C# and how I write output:

                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();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

尐偏执 2025-01-02 18:51:14

我认为问题在于您在 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);

I think the problem is that you treat the binary PDF data as text on both the PHP and the C# side.

 decrypted = Encoding.UTF8.GetString(encoded);

makes no sense if encoded represents binary data. You should probably skip this step and define your DecryptString() as returning byte[]. And then rename it too.

If you do want it as a string you might have better luck with ASCII or ANSI encoding:

 decrypted = Encoding.ASCII.GetString(encoded);

but the error may already be happening on the PHP side, I can't tell.

Additional, I just noted:

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

This is a very over-complicated way to create a BinaryWriter. The Encoding will not be used. And

 bw.Write(decrypted);

This will write the string with a length-prefix, that certainly will make your PDF invalid.

When you keep the return of Decrypt as string, use

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

And when you return it as byte[] (recommended), use

 File.WriteAllBytes("C:\\Windows\\Temp\\" + outputFilename, decrypted);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文