Quantcast
Channel: WCF, ASMX and other Web Services
Viewing all articles
Browse latest Browse all 555

Build SOAP Envelope With Digital Signature C#

$
0
0

I need to assign digital signature on header for my soap request, here are the example of the SOAP request.

<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelopexmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12"xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"xmlns:xsd="http://www.w3.org/2001/XMLSchema"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Header><SOAP-SEC:Signaturesoapenv:actor=""soapenv:mustUnderstand="0"><ds:Signaturexmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethodAlgorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><ds:SignatureMethodAlgorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:ReferenceURI="#Body"><ds:DigestMethodAlgorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue></ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue></ds:SignatureValue></ds:Signature></SOAP-SEC:Signature></soapenv:Header><soapenv:BodyId="Body"><CalFireRequestsoapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><DETAFFReqhref="#id0"/></CalFireRequest><multiRefid="id0"soapenc:root="0"soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"xmlns:ns1="urn:DETAFFServices"xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"xsi:type="ns1:CalFireRequest"><inputFieldNamexsi:type="soapenc:string"></inputFieldName><inputFieldValuexsi:type="soapenc:string"></inputFieldValue><usrIdxsi:type="soapenc:string"></usrId></multiRef></soapenv:Body></soapenv:Envelope>

Then I decided to generated the request by using XML Writer which show as below:

privatestaticstringBuildEnvelope(X509Certificate2 certificate)
        {string envelope = null;// note - lots of bits here specific to my thirdpartyusing (var stream = new MemoryStream())
            {
                Encoding utf8 = new UTF8Encoding(false); // omit BOMusing (var writer = new XmlTextWriter(stream, utf8))
                {// soap envelope
                    writer.WriteStartDocument();
                    writer.WriteStartElement("soapenv:Envelope");
                        writer.WriteAttributeString("xmlns", "SOAP-SEC", null, "http://schemas.xmlsoap.org/soap/security/2000-12");
                        writer.WriteAttributeString("xmlns", "soapenv", null, "http://schemas.xmlsoap.org/soap/envelope/");
                        writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");
                        writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");

                            writer.WriteStartElement("soapenv", "Header", null);                                   
                                writer.WriteStartElement("SOAP-SEC","Signature",null);
                                    writer.WriteAttributeString("soapenv", "actor", null, "");
                                    writer.WriteAttributeString("soapenv", "mustUnderstand", null, "0");
                                writer.WriteEndElement(); //Security
                            writer.WriteEndElement(); //Header////<s:Body xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">//writer.WriteStartElement("soapenv", "Body", null);//writer.WriteAttributeString(null , "Id", null, "Body");//writer.WriteStartElement("CalFireRequest", null, null);//writer.WriteAttributeString("soapenv", "encodingStyle", null, "http://schemas.xmlsoap.org/soap/encoding/");//writer.WriteStartElement("DETAFFReq", null, null);//writer.WriteAttributeString("null", "href", null, "#id0");//writer.WriteEndElement(); // CalFireRequest//// your 3rd-party soap payload goes here//writer.WriteStartElement("???", "http://docs.oasis-open.org/ws-sx/ws-trust/200512");//// ...                //writer.WriteEndElement(); // //writer.WriteEndElement(); // Body


                    writer.WriteEndElement(); //Envelope
                }// signing passvar signable = Encoding.UTF8.GetString(stream.ToArray());
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(signable);// see https://stackoverflow.com/a/6467877var signedXml = new SignedXml(doc);

                RSACryptoServiceProvider rsaKey = (RSACryptoServiceProvider)certificate.PrivateKey;
                signedXml.SigningKey = rsaKey;
                // these values may not be supported by your 3rd party - they may use e.g. SHA256 miniumum
                signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
                signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url;// 
                KeyInfo keyInfo = new KeyInfo();
                KeyInfoX509Data x509data = new KeyInfoX509Data(certificate);
                keyInfo.AddClause(x509data);
                signedXml.KeyInfo = keyInfo;// 3rd party wants us to only sign the timestamp fragment- ymmv
                Reference reference0 = new Reference();
                reference0.Uri = "BODY";var t0 = new XmlDsigExcC14NTransform();
                reference0.AddTransform(t0);
                reference0.DigestMethod = SignedXml.XmlDsigSHA1Url;
                signedXml.AddReference(reference0);// etc// get the sig fragment
                signedXml.ComputeSignature();
                XmlElement xmlDigitalSignature = signedXml.GetXml();var nsmgr = new XmlNamespaceManager(doc.NameTable);
                nsmgr.AddNamespace("o", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
                nsmgr.AddNamespace("s", "http://www.w3.org/2003/05/soap-envelope");var security_node = doc.SelectSingleNode("/soapenv:Envelope/soapenv:Header/SOAP-SEC:Signature", nsmgr);
                security_node.AppendChild(xmlDigitalSignature);

                envelope = doc.OuterXml;
            }

            return envelope;
        }

When I run the program I found out that, this part the tag SOAP-SEC can't be close using writer.WriteEndElement()

writer.WriteStartElement("soapenv", "Header", null);                                   writer.WriteStartElement("SOAP-SEC","Signature",null);writer.WriteAttributeString("soapenv", "actor", null, "");writer.WriteAttributeString("soapenv", "mustUnderstand", null, "0");writer.WriteEndElement(); //Securitywriter.WriteEndElement(); //Header

Example of XML result generate

<?xml version="1.0" encoding="utf-8"?><soapenv:Envelopexmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12"xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"xmlns:xsd="http://www.w3.org/2001/XMLSchema"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Header><SOAP-SEC:Signaturesoapenv:actor=""soapenv:mustUnderstand="0" /></soapenv:Header></soapenv:Envelope>

Is there anything I am missing? or can anyone provide a better solution on the SOAP request from the example of SOAP Request above?


Viewing all articles
Browse latest Browse all 555

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>