I was struggling while trying to digitally sign soap envelope in Microsoft .NET. Webservice was rejecting my .NET signed request, saying “invalid signature”. In this case webservice was written in Java by third party, so i couldn't make any changes in server side.
Server side was expecting signature element with ds prefix. SignedXml class by default was not producing xml with ds prefix for signature element and child elements. Another problem was related to ds:KeyInfo which should have KeyValue and X509IssuerSerial elements - by default in .NET it is X509Data element. So the structure of message should look like this for the server to accept request:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<wsse:Security SOAP-ENV:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#ea43a55321b243c082dadae4f53f32b5">
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>.........</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>.......</ds:SignatureValue>
<ds:KeyInfo>
<ds:KeyValue>
<ds:RSAKeyValue>
<ds:Modulus>.......</ds:Modulus>
<ds:Exponent>....</ds:Exponent>
</ds:RSAKeyValue>
</ds:KeyValue>
<ds:X509IssuerSerial>
<ds:X509IssuerName>.......</ds:X509IssuerName>
<ds:X509SerialNumber>.......</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body ds:id="ea43a55321b243c082dadae4f53f32b5" xmlns:ds="http://schemas.xmlsoap.org/soap/security/2000-12">
.................
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I want to share my solution. Maybe this will be helpful to others, struggling with similar problems.
I created this with .NET 3.5 and was using Microsoft Web Services Enhancements (WSE) 3.0.
So i overrided default XmlDocument to have SetPrefix and GetPrefix methods:
Then overrided SignedXml class to support id attribute of namespace http://schemas.xmlsoap.org/soap/security/2000-12 in body element
And then a bit messy, but working code to sign xml document:
In my case input XmlDocument passed to method SignSoapBody looks like this:
Hope this will be helpful to someone...