输出无效

Ahm*_*jar 2 php c# encryption rijndael rijndaelmanaged

我有一个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;
    }
Run Code Online (Sandbox Code Playgroud)

这是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;
    }
Run Code Online (Sandbox Code Playgroud)

这是我如何在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();
Run Code Online (Sandbox Code Playgroud)

Hen*_*man 5

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

 decrypted = Encoding.UTF8.GetString(encoded);
Run Code Online (Sandbox Code Playgroud)

如果encoded表示二进制数据则没有意义.您应该跳过此步骤并将其定义DecryptString()为返回byte[].然后重命名它.

如果你想要它作为一个字符串,你可能会有更好的运气与ASCII或ANSI编码:

 decrypted = Encoding.ASCII.GetString(encoded);
Run Code Online (Sandbox Code Playgroud)

但错误可能已经发生在PHP方面,我无法分辨.

另外,我刚才注意到:

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

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

 bw.Write(decrypted);
Run Code Online (Sandbox Code Playgroud)

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

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

  File.WriteAllText("C:\\Windows\\Temp\\" + outputFilename, decrypted);
Run Code Online (Sandbox Code Playgroud)

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

 File.WriteAllBytes("C:\\Windows\\Temp\\" + outputFilename, decrypted);
Run Code Online (Sandbox Code Playgroud)