ASMX web service with Soap extension - problem with Encryption method

1.4k Views Asked by At

I try sing and encrypt SOAP message in ASP.NET Web Service.

//I have Crypt class, which input parameters is Stream:
public class CryptUtility
 {
      public virtual Stream EncryptAndSingXml (Stream inputStream)
      {
         XmlTextReader reader = new XmlTextReader(inputStream);
         XmlDocument doc = new XmlDocument();
         doc.Load(reader);

         // in this place I encrypt and sign SOAP message
         foreach (string xPathQuery in soapElement)
          {
          XmlNodeList nodesToEncrypt = doc.SelectNodes(xPathQuery, nsMan);
            foreach (XmlNode nodeToEncrypt in nodesToEncrypt)
              {
                // method EncryptString crypt only string from XmlNode
                nodeToEncrypt.InnerXml = EncryptString();
              }
           }

         // !!!
         //               I        THINK  HERE IS A PROBLEM 
         //
         //it return plain stream, no encrypt stream
         MemoryStream retStream = new MemoryStream();
         XmlTextWriter writer = new XmlTextWriter(retStream, Encoding.UTF8);
         doc.Save(retStream);
         return retStream;
      }
 }

I used CryptUtility object in Soap extension class:

public class SoapMsg : SoapExtension
 {
     private CryptUtility cryptUtil; //this object crypt and sing SOAP message
     //  ...

     //this method copy stream
     private void CopyStream(Stream from, Stream to)
     {
     TextReader reader = new StreamReader(from);
     TextWriter writer = new StreamWriter(to);
     writer.Write(reader.ReadToEnd());
     writer.Flush();
     }

     //this method sing and encrypt SOAP message, I call this method in stage  AfterSerialize
     private void CryptMessage()
     {
     newStream.Position = 0;
     Stream retStream = cryptUtil.EncryptAndSingXml(newStream);
     retStream.Position = 0;
     CopyStream(retStream, oldStream);
     }

     public override void ProcessMessage(SoapMessage message)
     {
       switch (message.Stage)
         {
           case SoapMessageStage.BeforeSerialize:
              break;
           case SoapMessageStage.AfterSerialize:
           {
           // call the crypt and sing method
           CryptMessage();
           //save the SOAP message, the message is not encrypt
           Log(message, "AfterSerialize");
           }
             break;
           case SoapMessageStage.BeforeDeserialize:
              break;
           case SoapMessageStage.AfterDeserialize:
               break;
            default:
              throw new ArgumentException("error.");
           }

        }
     // ...
 }

Problem is, when I log SOAP message in AfterDeserialize the XML is plain text, but it should be encrypt Can somebody help me, where can be problem , or what can I do bad?

Because first I use method EncryptAndSingXml as void in class SoapMsg, and it work correct!!! Something like this :

 public class SoapMsg : SoapExtension
 {
 //...
      public void EncryptAndSingXml()
      {...}
 //...
     public override void ProcessMessage(SoapMessage message)
     {
       switch (message.Stage)
         {
           //...
           case SoapMessageStage.AfterSerialize:
           EncryptAndSingXml();
               break;
           //...
        }
     // ...
 }

But when I makec class CryptUtility and method EncryptAndSingXml() as virtual it doesn't work. :( Can somebody help me ?

1

There are 1 best solutions below

3
John Saunders On

It doesn't look like you are modifying message at all!

And, please show where you create an instance of CryptUtility.

Also, your code is pretty bad. Try this:

public class CryptUtility
{
    public virtual Stream EncryptAndSingXml(Stream inputStream, IEnumerable<string> soapElement)
    {
        XmlDocument doc = new XmlDocument();
        using (XmlReader reader = XmlReader.Create(inputStream))
        {
            doc.Load(reader);
        }

        // in this place I encrypt and sign SOAP message
        XmlNamespaceManager nsMan = new XmlNamespaceManager(doc.NameTable);
        foreach (string xPathQuery in soapElement)
        {
            XmlNodeList nodesToEncrypt = doc.SelectNodes(xPathQuery, nsMan);
            foreach (XmlNode nodeToEncrypt in nodesToEncrypt)
            {
                // method EncryptString crypt only string from XmlNode
                nodeToEncrypt.InnerXml = EncryptString(nodeToEncrypt.InnerXml);
            }
        }

        // !!!
        //               I        THINK  HERE IS A PROBLEM 
        //
        //it return plain stream, no encrypt stream
        using (MemoryStream retStream = new MemoryStream())
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Encoding = Encoding.UTF8;
            using (XmlWriter writer = XmlWriter.Create(retStream, settings))
            {
                doc.WriteTo(writer);
            }
            return retStream;
        }
    }
}

and

public class SoapMsg : SoapExtension
{
    private CryptUtility cryptUtil; //this object crypt and sing SOAP message
    //  ...

    //this method copy stream
    private void CopyStream(Stream from, Stream to)
    {
        using (TextReader reader = new StreamReader(from))
        {
            using (TextWriter writer = new StreamWriter(to))
            {
                writer.Write(reader.ReadToEnd());
                writer.Flush();
            }
        }
    }

    //this method sing and encrypt SOAP message, I call this method in stage  AfterSerialize
    private void CryptMessage()
    {
        newStream.Position = 0;
        using (Stream retStream = cryptUtil.EncryptAndSingXml(newStream))
        {
            retStream.Position = 0;
            CopyStream(retStream, oldStream);
        }
    }

    public override void ProcessMessage(SoapMessage message)
    {
        switch (message.Stage)
        {
            case SoapMessageStage.BeforeSerialize:
                break;
            case SoapMessageStage.AfterSerialize:
                {
                    // call the crypt and sing method
                    CryptMessage();
                    //save the SOAP message, the message is not encrypt
                    Log(message, "AfterSerialize");
                }
                break;
            case SoapMessageStage.BeforeDeserialize:
                break;
            case SoapMessageStage.AfterDeserialize:
                break;
            default:
                throw new ArgumentException("error.");
        }

    }
    // ...
}