WCF - How to debug "The signature verification failed" messages - c#

I've created a WCF client that is calling a Spring Web Services 2.1.0 + Apache WSS4J 1.6.7 (WS-Sec 1.1) server and returning a response.
WCF is complaining that the "Message security verification failed" with an InnerException of "The signature verification failed"
Problem is, I've no other way of debugging this as it's on a production server. I've got WCF logging the SOAP going to and from and the exceptions being thrown, and the guys who run the server say they can process responses fine on their end (i.e. they dont get a problem verifying the signature )
Any idea's on how to debug this further? Would I be able to create a console app to validate the SOAP?
I've been able to send requests through to their server OK and am getting responses so I've been trying to validate this via a console app so that I can see where the response is going wrong, but cant get the Console app to verify the XML either - CheckSignature is always returning false when I run the request and response through.
Note: I've tried setting xmlDoc.PreserveWhitespace as true and false
Any help at all is appreciated
Just to note also - the code below is just something I put together to test the signature. The actual service binding / service client is a seperate app. The binding for this is below:
<customBinding>
<binding name="MY_BINDING">
<transactionFlow/>
<security defaultAlgorithmSuite="Basic256Rsa15" authenticationMode="MutualCertificate"
messageSecurityVersion="WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10"
requireDerivedKeys="false" messageProtectionOrder="SignBeforeEncrypt"
allowSerializedSigningTokenOnReply="true" securityHeaderLayout="Lax" >
<secureConversationBootstrap authenticationMode="CertificateOverTransport"
messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
requireDerivedKeys="false" />
</security>
<textMessageEncoding messageVersion="Soap11WSAddressing10"/>
<httpsTransport requireClientCertificate="true"/>
</binding>
</customBinding>
Binding from code - Config XML binding is retrieved and modified
public static CustomBinding GetServiceBinding()
{
//Get custom binding reference from app.config
CustomBinding binding = new CustomBinding(SettingsLookup.WcfCustomBindingName);
binding.ReceiveTimeout = new TimeSpan(0, 0, 15, 0);
binding.SendTimeout = new TimeSpan(0, 0, 15, 0);
// Get the x509ProtectionParams from the security element
X509SecurityTokenParameters tokenParameters = new X509SecurityTokenParameters();
tokenParameters.X509ReferenceStyle = X509KeyIdentifierClauseType.IssuerSerial;
tokenParameters.RequireDerivedKeys = false;
tokenParameters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
// Reference the asymettric security element
AsymmetricSecurityBindingElement securityBindingElement = binding.Elements.Find<AsymmetricSecurityBindingElement>();
// Set the X509SecurityTokenParameters to point to the one's just configured. This is for symetric encryption, for asymetric this line needs to change
//securityBindingElement.ProtectionTokenParameters = tokenParameters;
securityBindingElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
securityBindingElement.InitiatorTokenParameters = tokenParameters;
securityBindingElement.LocalClientSettings.DetectReplays = false;
securityBindingElement.RequireSignatureConfirmation = true;
//Set timestamp to false as it's not in the VHI request
securityBindingElement.IncludeTimestamp = true;
securityBindingElement.LocalClientSettings.TimestampValidityDuration = new TimeSpan(12,0,0);
return binding;
}
This app is just for checking the signature i was feeding in the SOAP envelope directly in a hope to debug the signature and see what was failing
// TEST PROGRAM JUST FOR CHECKING SIGNATURE, CONSOLE APP SEPERATE FROM MAIN APP
class Program
{
static void Main(string[] args)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true;
xmlDoc.LoadXml(Resource1.request);
X509Certificate2 cert = new X509Certificate2(#"D:\TEMP\certs\pub_and_private_key.pfx", "password");
bool result = ValidateSoapBodySignature(xmlDoc, cert);
}
public static bool ValidateSoapBodySignature(XmlDocument doc, X509Certificate2 cert)
{
// *** Load the doc this time
SignedXmlWithId sdoc = new SignedXmlWithId(doc);
// *** Find the signature and load it into SignedXml
XmlNodeList nodeList = doc.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#");
sdoc.LoadXml((XmlElement)nodeList[0]);
// *** Now read the actual signature and validate
bool result = sdoc.CheckSignature(cert, true);
return result;
}
}
public class SignedXmlWithId : SignedXml
{
public SignedXmlWithId(XmlDocument xml)
: base(xml)
{
}
public SignedXmlWithId(XmlElement xmlElement)
: base(xmlElement)
{
}
public override XmlElement GetIdElement(XmlDocument doc, string id)
{
// check to see if it's a standard ID reference
XmlElement idElem = base.GetIdElement(doc, id);
if (idElem == null)
{
XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
nsManager.AddNamespace("u", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
idElem = doc.SelectSingleNode("//*[#u:Id=\"" + id + "\"]", nsManager) as XmlElement;
}
return idElem;
}
}
Exceptions
System.ServiceModel.Security.MessageSecurityException: Message security verification failed.
---&gt; System.Security.Cryptography.CryptographicException: The signature verification failed.
at System.IdentityModel.SignedXml.VerifySignature(HashAlgorithm hash, AsymmetricSignatureDeformatter deformatter, String signatureMethod)
at System.IdentityModel.SignedXml.StartSignatureVerification(SecurityKey verificationKey)
at System.ServiceModel.Security.WSSecurityOneDotZeroReceiveSecurityHeader.VerifySignature(SignedXml signedXml, Boolean isPrimarySignature, SecurityHeaderTokenResolver resolver, Object signatureTarget, String id)
at System.ServiceModel.Security.ReceiveSecurityHeader.ProcessPrimarySignature(SignedXml signedXml, Boolean isFromDecryptedSource)
at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteSignatureEncryptionProcessingPass()
at System.ServiceModel.Security.LaxModeSecurityHeaderElementInferenceEngine.ExecuteProcessingPasses(ReceiveSecurityHeader securityHeader, XmlDictionaryReader reader)
at System.ServiceModel.Security.ReceiveSecurityHeader.Process(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy)
at System.ServiceModel.Security.MessageSecurityProtocol.ProcessSecurityHeader(ReceiveSecurityHeader securityHeader, Message&amp; message, SecurityToken requiredSigningToken, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
at System.ServiceModel.Security.AsymmetricSecurityProtocol.VerifyIncomingMessageCore(Message&amp; message, String actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message&amp; message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
--- End of inner exception stack trace ---</ExceptionString><InnerException><ExceptionType>System.Security.Cryptography.CryptographicException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>The signature verification failed.</Message><StackTrace> at System.IdentityModel.SignedXml.VerifySignature(HashAlgorithm hash, AsymmetricSignatureDeformatter deformatter, String signatureMethod)
at System.IdentityModel.SignedXml.StartSignatureVerification(SecurityKey verificationKey)
at System.ServiceModel.Security.WSSecurityOneDotZeroReceiveSecurityHeader.VerifySignature(SignedXml signedXml, Boolean isPrimarySignature, SecurityHeaderTokenResolver resolver, Object signatureTarget, String id)
at System.ServiceModel.Security.ReceiveSecurityHeader.ProcessPrimarySignature(SignedXml signedXml, Boolean isFromDecryptedSource)
at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteSignatureEncryptionProcessingPass()
at System.ServiceModel.Security.LaxModeSecurityHeaderElementInferenceEngine.ExecuteProcessingPasses(ReceiveSecurityHeader securityHeader, XmlDictionaryReader reader)
at System.ServiceModel.Security.ReceiveSecurityHeader.Process(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy)
at System.ServiceModel.Security.MessageSecurityProtocol.ProcessSecurityHeader(ReceiveSecurityHeader securityHeader, Message&amp; message, SecurityToken requiredSigningToken, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
at System.ServiceModel.Security.AsymmetricSecurityProtocol.VerifyIncomingMessageCore(Message&amp; message, String actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message&amp; message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)</StackTrace><ExceptionString>System.Security.Cryptography.CryptographicException: The signature verification failed.
at System.IdentityModel.SignedXml.VerifySignature(HashAlgorithm hash, AsymmetricSignatureDeformatter deformatter, String signatureMethod)
at System.IdentityModel.SignedXml.StartSignatureVerification(SecurityKey verificationKey)
at System.ServiceModel.Security.WSSecurityOneDotZeroReceiveSecurityHeader.VerifySignature(SignedXml signedXml, Boolean isPrimarySignature, SecurityHeaderTokenResolver resolver, Object signatureTarget, String id)
at System.ServiceModel.Security.ReceiveSecurityHeader.ProcessPrimarySignature(SignedXml signedXml, Boolean isFromDecryptedSource)
at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteSignatureEncryptionProcessingPass()
at System.ServiceModel.Security.LaxModeSecurityHeaderElementInferenceEngine.ExecuteProcessingPasses(ReceiveSecurityHeader securityHeader, XmlDictionaryReader reader)
at System.ServiceModel.Security.ReceiveSecurityHeader.Process(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy)
at System.ServiceModel.Security.MessageSecurityProtocol.ProcessSecurityHeader(ReceiveSecurityHeader securityHeader, Message&amp; message, SecurityToken requiredSigningToken, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
at System.ServiceModel.Security.AsymmetricSecurityProtocol.VerifyIncomingMessageCore(Message&amp; message, String actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message&amp; message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
SOAP
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1" u:Id="_3">http://www.xxx.com/xxx/v1/submitRequest</a:Action>
<a:MessageID u:Id="_4">urn:uuid:d9d6ae53-4e63-4e2d-86bf-954684d26fd8</a:MessageID>
<a:To s:mustUnderstand="1" u:Id="_5">https://urigoeshere.com/</a:To>
<a:From u:Id="_6">
<a:Address>http://ourcompany.com/</a:Address>
</a:From>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="uuid-01f867d2-f5c2-4587-a83d-0878a2342bd9-1">
<u:Created>2013-01-21T17:12:31.213Z</u:Created>
<u:Expires>2013-01-22T05:12:31.213Z</u:Expires>
</u:Timestamp>
<o:BinarySecurityToken u:Id="uuid-81deba4d-1a68-4f53-bb59-3c618914d683-2" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">OMITTED</o:BinarySecurityToken>
<e:EncryptedKey Id="_0" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<o:SecurityTokenReference>
<o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">oNEIRj8uPIkIP4+BfAo/CmYDwzk=</o:KeyIdentifier>
</o:SecurityTokenReference>
</KeyInfo>
<e:CipherData>
<e:CipherValue>OMITTED</e:CipherValue>
</e:CipherData>
<e:ReferenceList>
<e:DataReference URI="#_2"/>
</e:ReferenceList>
</e:EncryptedKey>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#_1">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>17c5Wuh9MNl4i/ytgwm9flLkAnY=</DigestValue>
</Reference>
<Reference URI="#_3">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>2YgeR5vFw0ICk8r+wiaVYknO4E8=</DigestValue>
</Reference>
<Reference URI="#_4">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>NepAQ8htbWWBy0ghljlVfMw5lr0=</DigestValue>
</Reference>
<Reference URI="#_5">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>ynr1icJszUi4OG5vt0usO0419As=</DigestValue>
</Reference>
<Reference URI="#_6">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>y8jXxE1bLmeg6vJi9iqKczNvEDo=</DigestValue>
</Reference>
<Reference URI="#uuid-01f867d2-f5c2-4587-a83d-0878a2342bd9-1">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>qlv+YHU/bxsWvEo/HYVZY9RfqQY=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>O6MK3Etk/OIXkSTngGaN+W1JPTrbV2/K0ulnTS69o1/NvmDfpdlkb67TR+UNnCBwVEiV0ILZfQkl9zVhMMpB0lOeM3zzJ5f97dh1WLkGeQm7U2G+ZTN0QFA/O4HZ2yADhzRlPLp29hNdjGBdky99b0oeFyU2hq8qdpIWwKMCDkHlGyftKb4t51yZSc+6uJKYhv3uXSmFMJAYZ6tlTfYa5Cc0jLileNx6I9+tyg73oJZsTEyc+cDZZqdxEmXLrAyt0kz0fcpGWrNKCrKuQlaMsV/KkJYVHSohPpJYWUrrtGmOfiWWhQuwlCIUIxCwR8HBpspFOK8IHEuu+kBQgKrx3g==</SignatureValue>
<KeyInfo>
<o:SecurityTokenReference>
<o:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" URI="#uuid-81deba4d-1a68-4f53-bb59-3c618914d683-2"/>
</o:SecurityTokenReference>
</KeyInfo>
</Signature>
</o:Security>
</s:Header>
<s:Body u:Id="_1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<e:EncryptedData Id="_2" Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
<e:CipherData>
<e:CipherValue>OMITTED</e:CipherValue>
</e:CipherData>
</e:EncryptedData>
</s:Body>
</s:Envelope>

Apart from enabling WCF security traces I can recommend you debugging .net framework code.
To do this you have to configure VS as described here:
http://referencesource.microsoft.com/setup.html
You can also download framework source code and based on wcf traces examine what exactly is happening in part of code from where exceptions are thrown.

Related

C# SAML Signature Verification

I'm trying to replicate a behavior of SAMl signature verification from one of the system into C# and I'm trying locally on my system. However, I'm not able to crack it so far, I always get false when I try to verify the signed XML with X509 certificate.
What am I missing, and is there a way to get logs to explain why it is failing?
public static bool VerifyXml(XmlDocument Doc,X509Certificate2 cert1) {
if (Doc == null)
throw new ArgumentException("Doc");
SignedXml signedXml = new SignedXml(Doc);
var nsManager = new XmlNamespaceManager(Doc.NameTable);
nsManager.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");
var node = Doc.SelectSingleNode("//ds:Signature", nsManager);
// find signature node
var certElement = Doc.SelectSingleNode("//ds:X509Certificate", nsManager);
// find certificate node
var cert = new X509Certificate2(Convert.FromBase64String(certElement.InnerText));
signedXml.LoadXml((XmlElement)node);
if (cert1.GetPublicKeyString() != cert.GetPublicKeyString())
{
Console.WriteLine("certificate verification failed.");
return false;
}
return signedXml.CheckSignature(cert);
}
Below is the SAML Response that I'm trying to verify, I have trimmed some data for security reasons:
<samlp:Response ID="_0d04b5df-77ff-4e90-9796-82b46105dbbf" Version="2.0" IssueInstant="2023-01-21T03:39:23Z" Destination="https://uat.xyz.com" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://idp-test.xyz.com</saml:Issuer>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<Reference URI="#_0d04b5df-77ff-4e90-9796-82b46105dbbf">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<InclusiveNamespaces PrefixList="#default samlp saml ds xs xsi" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transform>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue>Vrn6ZWIg7Q3zKTbGnVdKlsfgjqmHHLv0+KilO2gAZ5s=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>MGjQp9uCT/pkHPuVKC8+8I3tbLHS7Y2fXFyoGfLpIwlNEWOqbTFzU1dco1Bzw9MsmAEen6Wq</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIDzTCCArWgAwIBAgIJAMIRqxzkLqE8MA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdGbG9yaWRhMRYwFAYDVQQHDA1TdCBQZXRlcnNidXJnMRwwGgYDVQQKDBNLb2JpZSBNYXJrZXRpbmcgSU5DMSUwIwYDVQQDDBxj</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</samlp:Status>
<saml:Assertion Version="2.0" ID="_6d46cc16-cb04-4e44-88b3-e6a3a3d3357d" IssueInstant="2023-01-21T03:39:23Z" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:Issuer>https://idp-test.xyz.com</saml:Issuer>
<saml:Subject>
<saml:NameID>e58c9aaa-9b68-4328-ad65-4f1b82086406</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2023-01-21T03:42:23Z" Recipient="https://uat.xyz.com/" />
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2023-01-21T03:36:23Z" NotOnOrAfter="2023-01-21T03:42:23Z">
<saml:AudienceRestriction>
<saml:Audience>https://idp-test.xyz.com</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2023-01-21T03:39:23Z" SessionIndex="_6d46cc16-cb04-4e44-88b3-e6a3a3d3357d">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
</saml:Assertion>
</samlp:Response>

Adding wsse:Security token with message signature

I am trying to send a request via web service (SoapHttpClientProtocol) method. Unfortunately for me, this request requires to have wsse:Security Token in soap header, with signature of request xml, and raw data of public key (as I understand).
Soap exammple how it should be:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
soap:mustUnderstand="1">
<wsse:BinarySecurityToken
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
wsu:Id="X509-D517D5F699516D846F15717371831011">
MIIE_certificate_raw_data_==
</wsse:BinarySecurityToken>
<wsu:Timestamp wsu:Id="TS-1">
<wsu:Created>2021-03-15T09:39:43.086Z</wsu:Created>
<wsu:Expires>2021-03-15T09:44:43.086Z</wsu:Expires>
</wsu:Timestamp>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-3">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap"/>
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#TS-1">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="wsse soap"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>Digest_Value</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#id-2">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList=""/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>Digest_Value</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>Signature_Value</ds:SignatureValue>
<ds:KeyInfo Id="KI-D517D5F699516">
<wsse:SecurityTokenReference wsu:Id="STR-D517D5F6">
<wsse:Reference URI="#X509-D517D5F699516D846F" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</soap:Header>
<soap:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-2">
<Tag1>
<T>12345678</T>
<B>2342</B>
<C>3456345435</C>
</Tag1>
</soap:Body>
</soap:Envelope>
What I have done:
Created class
public class SecurityHeader : SoapHeader, IXmlSerializable
{
public XmlElement Xml { get; set; }
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader) { }
public void WriteXml(XmlWriter writer)
{
writer.WriteRaw(Xml.InnerXml);
}
}
added class which adds SecurityHeader
SecurityHeaderExtension : SoapExtension
into web.config:
<system.web>
</system.web>
And finally I am getting soap:Header <wsse_x003A_Security ...> instead of soap:Header <wsse:Security ...>
Can somebody give me a hand of help? I have read a lot links already, with no result at the moment...
UPD:
Partialy solved this issue by:
var requestContext = myWebService.RequestSoapContext;
var token = new Microsoft.Web.Services2.Security.Tokens.X509SecurityToken(certX);
requestContext.Security.Tokens.Add(token);
requestContext.Security.Timestamp.TtlInSeconds = 5;
// Sign the message using the X509 certificate.
var messageSign = new Microsoft.Web.Services2.Security.MessageSignature(token);
messageSign.SignatureOptions = Microsoft.Web.Services2.Security.SignatureOptions.IncludeSoapBody | Microsoft.Web.Services2.Security.SignatureOptions.IncludeTimestamp;
requestContext.Security.Elements.Add(messageSign);
var resp = myWebService.ExecuteCall(req);
Now I have problem with reading response, I am getting error: 'The signature or decryption was invalid'.
As I understand the problem is on my side, but not sure...

I need a "BinarySecurityToken" when I call "SOAP Service" using ".Net Core"

I want to create something like below:
<SOAP-ENV:Header>
<wsse:Security SOAP-ENV:mustUnderstand="1">
<wsse:BinarySecurityToken EncodingType="…#Base64Binary" ValueType="…#X509v3" wsu:Id="CertId-1776694">
MIIDDDCCAfSgAwIBAgIQM6YEf7FVYx/tZyEXgVComTANBgkqhkiG9w0SDGBSDJHBK34...
</wsse:BinarySecurityToken>
<ds:Signature>
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<ds:Reference URI="#id-1464350">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue">1JmC1C0FrlPB42xfFKolgaCew5k=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue">
H1b7jH2bHpbrzJXkFS0msdUYycDMH4n6m4oTRtbo4Yk35/JzGcuwUYZ3...
</ds:SignatureValue>
<ds:KeyInfo>
<wsse:SecurityTokenReference wsu:Id="STRId-13498124">
<wsse:Reference URI="#CertId-1776694" ValueType="…#X509v3" />
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body wsu:Id="id-1464350">
...
</SOAP-ENV:Body>
I have the next code:
OperationsClient client = new OperationsClient();
var response = await client.MarketInfoAsync(request);
...
internal partial class OperationsClient
{
static partial void ConfigureEndpoint(ServiceEndpoint serviceEndpoint, ClientCredentials clientCredentials)
{
serviceEndpoint.Address = new EndpointAddress("https://testmisapi.ercot.com/2007-08/Nodal/eEDS/EWS/");
(serviceEndpoint.Binding as BasicHttpBinding).Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
(serviceEndpoint.Binding as BasicHttpBinding).Security.Mode = BasicHttpSecurityMode.Transport;
clientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, 509FindType.FindBySerialNumber, "XXXXX");
}
}
I recieve the error:
SECU1075: An error was discovered processing the <wsse:Security> header
I have tried changig this:
(serviceEndpoint.Binding as BasicHttpBinding).Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential;
(serviceEndpoint.Binding as BasicHttpBinding).Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;
But in this case I recieve following error:
Could not establish trust relationship for the SSL/TLS secure channel with authority 'testmisapi.ercot.com'.
I have read that I can use IClientMessageInspector but I don't know how can I add the complete Security header.
Thank you very much!

WCF Client consuming WS-Security webservice

I managed to consume a java based web service (third party) with WS-Security 1.1 protocol. The web service needs only to be signed over a x509 certificate, not encrypted.
But I'm getting this error:
The signature confirmation elements cannot occur after the primary signature.
The captured server response package looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="true">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="Signature-501">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#id-502">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>...</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#SigConf-500">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<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 Id="KeyId-...">
<wsse:SecurityTokenReference xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="STRId-...">
<ds:X509Data>
<ds:X509IssuerSerial>
<ds:X509IssuerName>CN=COMODO RSA Organization Validation Secure Server CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB</ds:X509IssuerName>
<ds:X509SerialNumber>...</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
<wsse11:SignatureConfirmation xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" Value="..." wsu:Id="SigConf-500"/>
</wsse:Security>
</soapenv:Header>
<soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-502">
<altaClienteResponse xmlns="...">
<altaClienteReturn>
<codigoError>7</codigoError>
<descripcionError>El código de banco no es válido.</descripcionError>
<idTransaccion xsi:nil="true"/>
</altaClienteReturn>
</altaClienteResponse>
</soapenv:Body>
</soapenv:Envelope>
The server is responding what it should but my app seems not to be interpreting it correctly. It seems that the <wsse11:SignatureConfirmation .../> tag must be before <ds:Signature></ds:Signature> tag.
I couldn't find any reference to a order standard of this.
EDIT: Adding my code.
try
{
var certificate = new X509Certificate2(#"C:\Users\...\cert.pfx", PassKeyStore);
var binding = new CustomBinding();
var security = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateDuplexBindingElement(MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10);
security.EndpointSupportingTokenParameters.Signed.Add(new X509SecurityTokenParameters
{
InclusionMode = SecurityTokenInclusionMode.Never,
ReferenceStyle = SecurityTokenReferenceStyle.Internal,
});
security.RecipientTokenParameters.InclusionMode = SecurityTokenInclusionMode.Never;
security.RecipientTokenParameters.ReferenceStyle = SecurityTokenReferenceStyle.Internal;
security.MessageSecurityVersion =
MessageSecurityVersion.
WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;
security.IncludeTimestamp = false;
security.MessageProtectionOrder = System.ServiceModel.Security.MessageProtectionOrder.EncryptBeforeSign;
security.RequireSignatureConfirmation = true;
security.AllowSerializedSigningTokenOnReply = true;
binding.Elements.Add(security);
binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
binding.Elements.Add(new HttpsTransportBindingElement());
var client = new SistarbancService.WsMediosPagoClient(binding, new EndpointAddress(new Uri(UrlSistarbanc), new DnsEndpointIdentity("..."), new AddressHeaderCollection()));
client.ClientCredentials.ServiceCertificate.DefaultCertificate = new X509Certificate2("C:\\Users\\...\\servidor.cer");
client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode =
System.ServiceModel.Security.X509CertificateValidationMode.None;
client.ClientCredentials.ClientCertificate.Certificate = certificate;
client.Endpoint.Contract.ProtectionLevel = System.Net.Security.ProtectionLevel.Sign;
var response = await client.altaClienteAsync("XXX", "0", "0", "0", "0", "0");
}
catch (Exception ex)
{
}
The exception is thrown by the ReceiveSecurityHeader class - see the source code of it here:
https://referencesource.microsoft.com/#system.servicemodel/system/servicemodel/Security/ReceiveSecurityHeader.cs
Search for SignatureConfirmationsOccursAfterPrimarySignature and see this line:
if (this.orderTracker.PrimarySignatureDone)
{
throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.SignatureConfirmationsOccursAfterPrimarySignature)), this.Message);
}
I can't find any references to any kind of standard supporting this either...
You might be better off asking this question to Microsoft.

Signature xml tags in another position

I'm doing the signing of a document with c #
  with this code
public class program
{
static void Main(String[] arg)
{
string xmlString = File.ReadAllText(#"D:\E-Billing\Demo.xml");
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlString);
//doc.Load(#"D:\E-Billing\Demo.xml");
string pfxStr = #"D:\E-Billing\jojolete.pfx";
X509Certificate2 cert = new X509Certificate2(File.ReadAllBytes(pfxStr),"cabanillas");
SignedXMLWithCertificate(doc, cert);
Console.WriteLine(doc.OuterXml);
doc.Save(#"D:\E-Billing\Demo2.xml");
}
public static void SignedXMLWithCertificate(XmlDocument doc, X509Certificate2 cert)
{
SignedXml signedXML = new SignedXml(doc);
signedXML.SigningKey = cert.PrivateKey;
Reference reference = new Reference();
reference.Uri = "";
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
signedXML.AddReference(reference);
KeyInfo keyinfo = new KeyInfo();
keyinfo.AddClause(new KeyInfoX509Data(cert));
signedXML.KeyInfo = keyinfo;
signedXML.ComputeSignature();
XmlElement xmlsig = signedXML.GetXml();
//doc.DocumentElement.AppendChild(doc.ImportNode(xmlsig, true));
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ext", "");
doc.SelectSingleNode("/Invoice/ext:ExtensionContent", nsmgr).AppendChild(doc.ImportNode(xmlsig, true));
}
Xml document I want to sign has the following tags where to insert the signature
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<Invoice>
<ext:UBLExtensions>
<ext:UBLExtension>
<ext:ExtensionContent>
<sac:AdditionalInformation>
<sac:AdditionalMonetaryTotal>
<cbc:ID>1001</cbc:ID>
<cbc:PayableAmount currencyID="PEN">348199.15</cbc:PayableAmount>
</sac:AdditionalMonetaryTotal>
<sac:AdditionalMonetaryTotal>
<cbc:ID>1003</cbc:ID>
<cbc:PayableAmount currencyID="PEN">12350.00</cbc:PayableAmount>
</sac:AdditionalMonetaryTotal>
<sac:AdditionalMonetaryTotal>
<cbc:ID>1004</cbc:ID>
<cbc:PayableAmount currencyID="PEN">30.00</cbc:PayableAmount>
</sac:AdditionalMonetaryTotal>
<sac:AdditionalMonetaryTotal>
<cbc:ID>2005</cbc:ID>
<cbc:PayableAmount currencyID="PEN">59230.51</cbc:PayableAmount>
</sac:AdditionalMonetaryTotal>
<sac:AdditionalProperty>
<cbc:ID>1000</cbc:ID>
<cbc:Value>CUATROCIENTOS VEINTITRES MIL DOSCIENTOS VEINTICINCO Y
00/100</cbc:Value>
</sac:AdditionalProperty>
</sac:AdditionalInformation>
</ext:ExtensionContent>
</ext:UBLExtension>
<ext:UBLExtension>
<ext:ExtensionContent>
<ds:Signature Id="SignatureSP">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#envelopedsignature"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>ryg5Vl+...Qjk=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>SOiGQp....ffb0=</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509SubjectName>1.2IMA,ST=LIMA,C=PE</ds:X509SubjectName>
<ds:X509Certificate>MIIESTCCAzGgAwIBAgIKWOC++GxDtaK/5EiVKSqzJ6geIfz</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
</ext:ExtensionContent>
</ext:UBLExtension>
</ext:UBLExtensions>
more tags
</Invoice>
but the tags signature appears at the end
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>GF0......OR/nXwTxw=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>JQLyp...wEN6Th</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>o6pQR6K.......XJODMUu</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Invoice>
As I can move or assign where they will sign the xml?
You can change the last line of your code
doc.DocumentElement.AppendChild(doc.ImportNode(xmlsig, true));
to
doc.SelectSingleNode("/Invoice/ext:ExtensionContent", nsmgr).AppendChild(doc.ImportNode(xmlsig, true));
The document node is the root node, so it will append there. SelectSingleNode() uses XPath to select a different node for importing. Note that you need a namespace manager for the extprefix.
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ext","uri-of-ext");

Categories

Resources