2012-01-14 2 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

+0

Имеет ли расшифрованный файл тот же размер файла, что и исходный? –

+0

В Windows я предполагаю? –

ответ

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, но никогда не «unpadded» в C#. –

+1

@Joachim: OP указывает, что процесс работает для текстовых данных, что заставляет меня думать, что настройки заполнения по умолчанию в порядке. –

+0

Да, я определенно не уверен, что это проблема, но это то, что я хотел бы посмотреть, в конце концов, что файлы были одинакового размера :) –

Смежные вопросы