2009-12-13 107 views
0

我需要建议。我在Web服务和客户端上压缩和隐藏SOAP消息。压缩和加密SOAP - ASP.NET web服务

客户端是winforms应用程序。

如果我只隐藏SOAP消息,它的效果很好。

如果我只压缩SOAP消息,它也很好。

我在crypt和zip SOAP上使用SOAP扩展。

我使用AES - 高级加密标准 - Rijndael和compresion我使用SharpZipLib从http://sourceforge.net/projects/sharpdevelop/

问题是我在客户端发送数据集。

  1. 首先,我在zip服务端对SOAP进行二次加密。

  2. 发送到客户端。

  3. 在客户端,我从流中加载XML。但它以此错误结束: 根级别的数据无效。 1号线位置2234

下面是代码,在那里我从流加载XML:

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

有什么建议?谢谢...

下面是关于Web服务端的方法,其拉链和隐窝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; 
      } 

    } 

这里是一个客户端一个代码解密和uzip 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; 
    } 

strong text

+1

为什么不直接使用WCF来完成这一切? – 2010-01-24 19:56:43

回答

1

我不知道为什么你的未加密的XML不会解析,但我认为你的第一步应该是将解密的数据转储到终端看到你正在回来的文字。也许这个过程破坏你的数据,或者你有一个编码问题。

或者,您可以将服务器配置为使用httpsgzip compression来实现相同的目标。用这种方法你不会失去任何安全性,这是迄今为止更为标准的做事方式。你也可以看看MS对WS-Security标准的支持