Сжатие и шифрование SOAP - веб-сервис ASP.NET

Мне нужен совет. Я архивирую и шифрую SOAP-сообщение на веб-сервисе и стороне клиента.

Клиент - приложение winforms.

Если я только зашифрую сообщение SOAP, оно работает хорошо.

Если я только почтовое сообщение SOAP, это также работает хорошо.

Я использую расширение SOAP на крипте и zip SOAP.

Я использую AES - Advanced Encryption Standard - Rijndael и при сжатии я использую SharpZipLib с http://sourceforge.net/projects/sharpdevelop/.

Проблема в том, что я отправляю набор данных на клиента.

  1. Во-первых, я заархивирую, а во-вторых, шифрую SOAP на стороне веб-сервиса.

  2. Отправить на клиента.

  3. На стороне клиента я загружаю XML из потока. Но это заканчивается этой ошибкой: данные на корневом уровне недействительны. Строка 1, позиция 2234.

Вот код, куда я загружаю XML из потока:

        var doc = new XmlDocument();
        using (var reader = new XmlTextReader(inputStream))
        {
            doc.Load(reader);
        }

Любой совет? Спасибо...

Вот методы на стороне веб-сервиса, которые архивируют и шифруют SOAP:

    //encrypt string
    private static string EncryptString(string @string, string initialVector, string salt, string password,
                         string hashAlgorithm, int keySize, int passwordIterations)
    {
        byte[] initialVectorBytes = Encoding.ASCII.GetBytes(initialVector);
        byte[] saltValueBytes = Encoding.ASCII.GetBytes(salt);
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(@string);

        var derivedPassword = new PasswordDeriveBytes(password, saltValueBytes, hashAlgorithm, passwordIterations);
        byte[] keyBytes = derivedPassword.GetBytes(keySize / 8);
        var symmetricKey = new RijndaelManaged();
        symmetricKey.Mode = CipherMode.CBC;
        ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initialVectorBytes);

        using (var memStream = new MemoryStream())
        {
            var cryptoStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write);
            cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
            cryptoStream.FlushFinalBlock();

            var serializer = new XmlSerializer(typeof(byte[]));
            var sb = new StringBuilder();
            TextWriter writer = new StringWriter(sb);
            serializer.Serialize(writer, memStream.ToArray());
            writer.Flush();

            var doc = new XmlDocument();
            doc.LoadXml(sb.ToString());
            if (doc.DocumentElement != null) return doc.DocumentElement.InnerXml;
        }
        return "";
    }

    //zip string
    private static byte[] ZipArray(string stringToZip)
    {
        byte[] inputByteArray = Encoding.UTF8.GetBytes(stringToZip);
        var ms = new MemoryStream();

        // SharpZipLib.Zip,
        var zipOut = new ZipOutputStream(ms);
        var zipEntry = new ZipEntry("ZippedFile");
        zipOut.PutNextEntry(zipEntry);


        zipOut.SetLevel(7);
        zipOut.Write(inputByteArray, 0, inputByteArray.Length);
        zipOut.Finish();
        zipOut.Close();

        return ms.ToArray();
    }


    //zip and encrypt SOAP
    public virtual Stream OutSoap(string[] soapElement, Stream inputStream)
    {

            #region Load XML from SOAP

            var doc = new XmlDocument();

            using (XmlReader reader = XmlReader.Create(inputStream))
            {
                doc.Load(reader);
            }

            var nsMan = new XmlNamespaceManager(doc.NameTable);
            nsMan.AddNamespace("soap",
                               "http://schemas.xmlsoap.org/soap/envelope/");

            #endregion Load XML from SOAP

            #region Zip SOAP

            XmlNode bodyNode = doc.SelectSingleNode(@"//soap:Body", nsMan);

            bodyNode = bodyNode.FirstChild.FirstChild;

            while (bodyNode != null)
            {
                if (bodyNode.InnerXml.Length > 0)
                {
                    // Zip
                    byte[] outData = ZipArray(bodyNode.InnerXml);

                    bodyNode.InnerXml = Convert.ToBase64String(outData);

                }
                bodyNode = bodyNode.NextSibling;
            }

            #endregion Zip SOAP

            #region Crypt SOAP

            foreach (string xPathQuery in soapElement)
            {
                XmlNodeList nodesToEncrypt = doc.SelectNodes(xPathQuery, nsMan);
                if (nodesToEncrypt != null)
                    foreach (XmlNode nodeToEncrypt in nodesToEncrypt)
                    {
                        //Encrypt
                        nodeToEncrypt.InnerXml = EncryptString(nodeToEncrypt.InnerXml,
                                                               user.IV, user.Salt, user.Password, user.HashType,
                                                               user.KeySize, user.PasswordIterations);
                    }
            }

            #endregion Crypt SOAP

            inputStream.Position = 0;
            var settings = new XmlWriterSettings { Encoding = Encoding.UTF8 };
            using (XmlWriter writer = XmlWriter.Create(inputStream, settings))
            {

                 doc.WriteTo(writer);
                 return inputStream;
            }

    }

Вот код на стороне клиента, который расшифровывает и распаковывает SOAP:

   //decrypt string
   private static string DecryptString(string @string, string initialVector, string salt, string password,
                         string hashAlgorithm, int keySize, int passwordIterations)
    {
        byte[] initialVectorBytes = Encoding.ASCII.GetBytes(initialVector);
        byte[] saltValueBytes = Encoding.ASCII.GetBytes(salt);
        byte[] cipherTextBytes = Convert.FromBase64String(@string);

        var derivedPassword = new PasswordDeriveBytes(password, saltValueBytes, hashAlgorithm, passwordIterations);
        byte[] keyBytes = derivedPassword.GetBytes(keySize / 8);
        var symmetricKey = new RijndaelManaged { Mode = CipherMode.CBC };
        ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initialVectorBytes);

        using (var memStream = new MemoryStream(cipherTextBytes))
        {
            var cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read);

            var plainTextBytes = new byte[cipherTextBytes.Length];
            int byteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);

            return Encoding.UTF8.GetString(plainTextBytes, 0, byteCount);
        }
    }


    //unzip string
    private static byte[] UnzipArray(string stringToUnzip)
    {

        byte[] inputByteArray = Convert.FromBase64String(stringToUnzip);
        var ms = new MemoryStream(inputByteArray);
        var ret = new MemoryStream();

        // SharpZipLib.Zip
        var zipIn = new ZipInputStream(ms);
        var theEntry = zipIn.GetNextEntry();
        var buffer = new Byte[2048];
        int size = 2048;

        while (true)
        {
            size = zipIn.Read(buffer, 0, buffer.Length);
            if (size > 0)
            {
                ret.Write(buffer, 0, size);
            }
            else
            {
                break;
            }
        }
        return ret.ToArray();
    }


    public virtual Stream  InSoap(Stream inputStream, string[] soapElement)
    {

        #region Load XML from SOAP

        var doc = new XmlDocument();
        using (var reader = new XmlTextReader(inputStream))
        {
            doc.Load(reader);
        }
        var nsMan = new XmlNamespaceManager(doc.NameTable);
        nsMan.AddNamespace("soap",
                           "http://schemas.xmlsoap.org/soap/envelope/");

        #endregion Load XML from SOAP


        #region Decrypt SOAP

        foreach (string xPathQuery in soapElement)
            {
                XmlNodeList nodesToEncrypt = doc.SelectNodes(xPathQuery, nsMan);
                if (nodesToEncrypt != null)
                    foreach (XmlNode nodeToEncrypt in nodesToEncrypt)
                    {
                        nodeToEncrypt.InnerXml = DecryptString(nodeToEncrypt.InnerXml, saltPhrase, passwordPhrase, initialVector,
                                          hashAlgorithm, passwordIterations, keySize);
                    }
            }

         #endregion Decrypt SOAP

         #region UnZip SOAP

         XmlNode node = doc.SelectSingleNode("//soap:Body", nsMan);
         node = node.FirstChild.FirstChild;


         while (node != null)
            {
                if (node.InnerXml.Length > 0)
                {

                    byte[] outData = UnzipArray(node.InnerXml);
                    string sTmp = Encoding.UTF8.GetString(outData);

                    node.InnerXml = sTmp;
                }

                node = node.NextSibling;
            }

         #endregion UnZip SOAP

        var retStream = new MemoryStream();
        doc.Save(retStream);
        return retStream;
    }

сильный текст

1 ответ

Я не уверен, почему ваш незашифрованный xml не будет проанализирован, но я думаю, что вы должны сделать первый шаг - сбросить расшифрованные данные в терминал, чтобы точно узнать, какой текст вы получаете. Возможно, процесс как-то повреждает ваши данные, или у вас есть проблема с кодировкой.

Кроме того, вы можете настроить свой сервер на использование сжатия https и gzip для достижения той же цели. При таком подходе вы не потеряете безопасность, и это гораздо более стандартный способ сделать что-либо. Вы также можете взглянуть на поддержку MS стандарта WS-Security.

Другие вопросы по тегам