Распакуйте поток - PullRequest
4 голосов
/ 24 июня 2011

Я пытаюсь распаковать поток, используя GZipStream и BinaryStream, но у меня не получается.

Вы можете мне помочь?

    public static LicenseOwnerRoot GetLicenseFromStream(Stream stream)
    {
        using (BinaryReader br = new BinaryReader(stream))
        {
            string keyCrypto = br.ReadString();
            string xmlCrypto = br.ReadString();
            string key = Cryptography.Decrypt(keyCrypto);
            string xml = Cryptography.Decrypt(key, xmlCrypto);
            byte[] data = Encoding.UTF8.GetBytes(xml.ToCharArray());

            using (MemoryStream ms = new MemoryStream(data))
            {
                using (GZipStream decompress = new GZipStream(ms, CompressionMode.Decompress))
                {
                    xml = Encoding.UTF8.GetString(data);
                    LicenseOwnerRoot root = (LicenseOwnerRoot)Utility.XmlDeserialization(typeof(LicenseOwnerRoot), xml);
                    foreach (LicenseOwnerItem loi in root.Licenses)
                        loi.Root = root;
                    return root;
                }
            }
        }
    }

Этот xml сжат и зашифрован, поэтому мне нужно распаковать, а затем расшифровать. Когда я пытаюсь прочитать, выдает одно ожидание с этим сообщением: магическое число в заголовке GZip не является правильным. Я пытался исправить это много раз, но это звучит вполне реально. Вопрос в том, как мне использовать «употребления», и если этот путь верен или существует другой способ сделать то, что я пытаюсь сделать? Я должен распаковать, прежде чем использовать BinaryReader?

На самом деле, я должен сделать обратный метод:

    public static void GenerateLicenseStream(string key, LicenseOwnerRoot root, Stream stream)
    {
        using (BinaryWriter sw = new BinaryWriter(stream))
        {
            string xml = Utility.XmlSerialization(root);
            using (MemoryStream ms = new MemoryStream())
            {
                using (GZipStream compress = new GZipStream(ms, CompressionMode.Compress))
                {
                    byte[] data = Encoding.UTF8.GetBytes(xml.ToCharArray());
                    compress.Write(data, 0, data.Length);
                    string keyCrypto = Cryptography.Encrypt(key);
                    string xmlCrypto = Cryptography.Encrypt(key, Encoding.UTF8.GetString(ms.ToArray()));
                    sw.Write(keyCrypto);
                    sw.Write(xmlCrypto);
                }
            }
        }
   } 

Ответы [ 3 ]

2 голосов
/ 24 июня 2011

Вы ничего не читаете из "распаковки". Вам нужно прочитать все данные из «декомпрессии» (поскольку нет длины сохраненных данных, которые вы должны прочитать, пока поток не станет пустым), а затем преобразовать их в строку, как вы делаете.

2 голосов
/ 24 июня 2011

Я написал для вас быстрый пример, он не выполняет шифрование, но показывает, где должно происходить шифрование / дешифрование. Это содержимое консольного приложения .NET, которое вы можете запускать «как есть»:

    static void Main(string[] args)
    {
        var content = @"someTextOrXMLContentGoesHereCanBeAnything#$&%&*(@#$^";
        var data = Encoding.UTF8.GetBytes(content.ToCharArray());
        var fs = new StreamWriter(@"c:\users\stackoverflow\desktop\sample.bin");
        using (var bw = new BinaryWriter(fs.BaseStream))
        {
            using (var ms = new MemoryStream())
            {
                using (var compress = new GZipStream(ms, CompressionMode.Compress, true))
                {
                    compress.Write(data, 0, data.Length);
                }
                // encrypt goes here
                var compressedData = ms.ToArray();
                Console.WriteLine(compressedData.Length); // 179
                bw.Write(compressedData);
            }
        }
        // and the reverse...
        using (var fs2 = new StreamReader(@"c:\users\stackoverflow\desktop\sample.bin"))
        {
            using (var br = new BinaryReader(fs2.BaseStream))
            {
                var len = (int)br.BaseStream.Length;
                var encrypted = br.ReadBytes(len);
                // decrypt here
                var decrypted = encrypted; // <== new result after decryption
                using (var ms = new MemoryStream(decrypted))
                {
                    List<byte> bytesList = new List<byte>();
                    using (var decompress = new GZipStream(ms, CompressionMode.Decompress, true))
                    {
                        int val = decompress.ReadByte();
                        while (val > -1)
                        {
                            bytesList.Add((byte)val);
                            val = decompress.ReadByte();
                        }  
                    }
                    var final_result = new String(Encoding.UTF8.GetChars(bytesList.ToArray()));
                    Console.WriteLine(final_result);
                }
            }
        }

        Console.ReadLine();
    }
2 голосов
/ 24 июня 2011

Вы рассматриваете сжатые данные как массив байтов utf-8. UTF-8 на самом деле имеет очень строгие правила, поэтому на этом этапе половина ваших сжатых данных, вероятно, заменяется вопросительными знаками (заполнителями для недопустимого символа).

Вам необходимо зашифровать / расшифровать необработанные двоичные данные и потерять преобразование строк. Сжатые данные не являются строкой и не должны рассматриваться как таковые.

Если ваш метод шифрования может работать только со строками (у меня нет определения вашего Cryptography класса), то у вас нет выбора, кроме как сначала зашифровать данные XML, а , а затем сжать (хотя это, вероятно, не будет сжиматься так же).

Вы также фактически не делаете никакой декомпрессии; вы создаете MemoryStream и GZipStream для сжатых данных, но затем ничего не делаете с ними и пытаетесь использовать data напрямую.

...