输出无效

时间:2012-01-14 13:19:23

标签: c# php encryption rijndaelmanaged rijndael

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

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

有什么建议吗?!

注意:

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

    这是我在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();
    

1 个答案:

答案 0 :(得分:5)

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

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