Вывод неверен - PullRequest
       65

Вывод неверен

2 голосов
/ 14 января 2012

У меня есть программа 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 Ответ

5 голосов
/ 14 января 2012

Мне кажется, проблема в том, что вы обрабатываете двоичные данные 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);
...