2012-01-14 70 views
2

我有一個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(); 
+1

你可以粘貼你是怎麼做到的編碼/解碼? – greut 2012-01-14 13:20:46

+0

解密文件與原文件大小相同嗎? – 2012-01-14 13:24:53

+0

在Windows上我想? – 2012-01-14 13:25:50

回答

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無效。

當你把解密的回報string,使用

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

當您返回它作爲byte[](推薦),使用

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

此外,雖然我不確定如果沒有閱讀方法的所有文檔,它似乎數據填充在PHP中,但從來沒有在C#中「無襯墊」。 – 2012-01-14 14:32:56

+1

@Joachim:OP聲明該過程適用於文本數據,這讓我認爲默認的填充設置是可以的。 – 2012-01-14 14:38:41

+0

是的,我絕對不知道這是一個問題,但我最終會注意到這些文件的大小相同:) – 2012-01-14 14:51:41