How to correctly sign an XML file in c#? - c#

I have source file like this:
<LicenseFile xmlns="">
<Object Id="Settings">
<ProductID xmlns="">P2</ProductID>
<FirstName xmlns="">John</FirstName>
<LastName xmlns="">Jackson</LastName>
</Object>
</LicenseFile>
I need to add sign and receive file like this:
<LicenseFile xmlns="">
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
...
<Object Id="Settings">
<ProductID xmlns="">P2</ProductID>
<FirstName xmlns="">John</FirstName>
<LastName xmlns="">Jackson</LastName>
</Object>
</Signature>
</LicenseFile>
But I have the result file like this:
<LicenseFile xmlns="">
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
...
</Signature>
<Object Id="Settings">
<ProductID xmlns="">P2</ProductID>
<FirstName xmlns="">John</FirstName>
<LastName xmlns="">Jackson</LastName>
</Object>
</LicenseFile>
I use that code:
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = false;
doc.Load(new XmlTextReader(FileName));
SignedXml signedXml = new SignedXml(doc);
signedXml.SigningKey = Key;
Signature XMLSignature = signedXml.Signature;
Reference reference = new Reference("#Settings");
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
XMLSignature.SignedInfo.AddReference(reference);
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new RSAKeyValue((RSA)Key));
XMLSignature.KeyInfo = keyInfo;
// Compute the signature.
signedXml.ComputeSignature();
XmlElement xmlDigitalSignature = signedXml.GetXml();
// Append the element to the XML document.
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, true));
if (doc.FirstChild is XmlDeclaration)
{
doc.RemoveChild(doc.FirstChild);
}
// Save the signed XML document to a file specified
// using the passed string.
XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false));
doc.WriteTo(xmltw);
xmltw.Close();
What is incorrect?
Thnx.

The Object Node must be child of the Signature, and not in the same level.

Related

The top XML element 'Data' from namespace '' references distinct types

I have to send Active Directory data to a third-party application. This third-party application provides a .WSDL URL which I have added as a Service Reference in my .NET application. After this I have to call a function "Import" which looks something like this:
Import(Security security, string Data, int FolderID)
Here 'Data' is the XML data that needs to be transferred. I have an XML something like this:
var xEle = new XElement("Document",
from emp in lstADUsers
select new XElement("Record",
new XElement("UserName", emp.UserName),
new XAttribute("FirstName", "TEST_FNAME"),
new XAttribute("LastName", "Test_LNAME"),
new XAttribute("Email", "test#test.com")
));
I call the Import method as:
Import(token, xEle, 1)
When this method is hit, I am getting below error:
The top XML element 'Data' from namespace '' references distinct types
System.String and System.Byte[]. Use XML attributes to specify another
XML name or namespace for the element or types.
The third-party application expects SOAP data.
Extra details
SOAP envelope looks like this:
<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:sec='http://schemas.xmlsoap.org/ws/2003/06/secext' xmlns:wsu='http://schemas.xmlsoap.org/ws/2003/06/utility'
xmlns:urn='urn:TestApp'>
<soapenv:Header>
<sec:Security>
<sec:UsernameToken wsu:Id='TestApp'>
<sec:Username>TestUser</sec:Username>
<!--Optional:-->
<sec:Password>TestPassword</sec:Password>
</sec:UsernameToken>
</sec:Security>
</soapenv:Header>
<soapenv:Body>
<urn:ImportData>
<Table></Table>
<FolderId>0</FolderId>
<Data><![CDATA[<Document>
<Record></Record>
</Document>
</Data>
Code Changes Below
/// <summary>
/// Summary description for ThirdPArtyApp
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class ThirdParty : System.Web.Services.WebService
{
public Header header;
[WebMethod]
[SoapHeader("header", Direction = SoapHeaderDirection.InOut)]
public void CreateXmlForImport()
{
ThirdParty_Serv thirdParty = new ThirdParty_Serv();
header.Username = "test123";
header.Password = "XYZ123";
const string FILENAME = #"D:\Users\Documents\test.xml";
XDocument doc = XDocument.Load(FILENAME);
XNamespace nsUrn = doc.Root.GetNamespaceOfPrefix("urn");
XElement importData = doc.Descendants(nsUrn + "ImportData").FirstOrDefault();
XElement xCdata = new XElement("Document",
new XElement("Record",
new XAttribute("UserName", "T12345"),
new XAttribute("FirstName", "TEST_RP"),
new XAttribute("LastName", "Test_LNAME"),
new XAttribute("Email", "test#test.com")
));
string cDataStr = xCdata.ToString();
XCData cdata = new XCData(cDataStr);
thirdParty.ImportData("/Do/Persons", 0, cDataStr, 3);
}
}
I used the schema to get correct structure. From VS you can test the syntax by going to menu Project:Add New Item : Xml File. Than past the xml into view. Errors will show like compiler errors in the Error List. Also if you type an opening angle bracket is will show the elements that can be added in any section.
I used following xml
<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:sec='http://schemas.xmlsoap.org/ws/2003/06/secext' xmlns:wsu='http://schemas.xmlsoap.org/ws/2003/06/utility'
xmlns:urn='urn:TestApp'>
<soapenv:Header>
<sec:Security>
<sec:UsernameToken wsu:Id='TestApp'>
<sec:Username>TestUser</sec:Username>
<!--Optional:-->
<sec:Password>TestPassword</sec:Password>
</sec:UsernameToken>
</sec:Security>
</soapenv:Header>
<soapenv:Body>
<urn:ImportData>
<Table></Table>
<FolderId>0</FolderId>
<Record></Record>
</urn:ImportData>
</soapenv:Body>
</soapenv:Envelope>
Here is my code
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XNamespace nsUrn = doc.Root.GetNamespaceOfPrefix("urn");
XElement importData = doc.Descendants(nsUrn + "ImportData").FirstOrDefault();
XElement xCdata = new XElement("Record",
new XElement("UserName", "username"),
new XAttribute("FirstName", "TEST_FNAME"),
new XAttribute("LastName", "Test_LNAME"),
new XAttribute("Email", "test#test.com")
);
string cDataStr = xCdata.ToString();
XCData cdata = new XCData(cDataStr);
importData.Add(cdata);
}
Here is final Xml
<?xml version="1.0"?>
<soapenv:Envelope xmlns:urn="urn:TestApp" xmlns:wsu="http://schemas.xmlsoap.org/ws/2003/06/utility" xmlns:sec="http://schemas.xmlsoap.org/ws/2003/06/secext" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<sec:Security>
<sec:UsernameToken wsu:Id="TestApp">
<sec:Username>TestUser</sec:Username>
<!--Optional:-->
<sec:Password>TestPassword</sec:Password>
</sec:UsernameToken>
</sec:Security>
</soapenv:Header>
<soapenv:Body>
<urn:ImportData>
<Table/>
<FolderId>0</FolderId>
<Record/>
<![CDATA[<Record FirstName="TEST_FNAME" LastName="Test_LNAME" Email="test#test.com"><UserName>username</UserName></Record>]]>
</urn:ImportData>
</soapenv:Body>
</soapenv:Envelope>

SAML Authentication Requested ( Invalid Signature Error)

I am creating signed SAML Request using below code and the certificates are cross checked to be same however getting invalid signature error on IDP , Please suggest
public XmlDocument SignXML(XmlDocument xml)
{
X509Certificate2 cert = new X509Certificate2(#"" + SPCertificateLocation, SPCertificatePassword);// , X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
// set key, signing algorithm, and canonicalization method
var signedXml = new SignedXml(xml.DocumentElement) { SigningKey = cert.GetRSAPrivateKey() };
signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
//signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url;
signedXml.SignedInfo.CanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#";
// sign whole document using "SAML style" transforms
var reference = new Reference { Uri = string.Empty };
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigExcC14NTransform());
signedXml.AddReference(reference);
KeyInfo keyInfo = new KeyInfo();
KeyInfoX509Data keyInfoData = new KeyInfoX509Data(cert);
keyInfo.AddClause(keyInfoData);
signedXml.KeyInfo = keyInfo;
// create signature
signedXml.ComputeSignature();
// get signature XML element and add it as a child of the root element
//signedXml.GetXml();
//XmlElement xmlSignature = signedXml.GetXml();
//AssignNameSpacePrefixToElementTree(xmlSignature, "ds");
// Add prefix "ds:" to signature
XmlElement signature = signedXml.GetXml();
SetPrefix("ds", signature);
// Load modified signature back
signedXml.LoadXml(signature);
// this is workaround for overcoming a bug in the library
signedXml.SignedInfo.References.Clear();
// Recompute the signature
signedXml.ComputeSignature();
string recomputedSignature = Convert.ToBase64String(signedXml.SignatureValue);
// Replace value of the signature with recomputed one
ReplaceSignature(signature, recomputedSignature);
// Append the signature to the XML document.
xml.DocumentElement.InsertAfter(xml.ImportNode(signature, true), xml.DocumentElement.FirstChild);
//xml.DocumentElement?.AppendChild(signedXml.GetXml());
return xml;
}
The code converts the XML correctly into signature enabled XML however it is showing unable to verify the authenticity of signature
<saml2p:AuthnRequest ID="_3a6d2566-68a1-4afc-a784-c125bd94173f" Version="2.0" ForceAuthn="false" IssueInstant="2022-05-09T08:26:33Z" Destination="https://auth.pingone.com/172e7894-5cbe-456b-b451-d2585aeab74f/saml20/idp/sso" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="http://localhost:20630/CASCC/SamlConsume" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://localhost:20630</saml2:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><ds:Reference URI=""><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><ds:DigestValue>EZBisrHSVKE2zS15roaUFG0EnP3ZobisulcQXw0fO18=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>uyniiynlIP6z/g6U4qzWKdmeD8sP7majYwqDhy5n2nTDJyE8MEdaIhEJssIDeuc+VAILueMhzRV/mC4uiAZ5kgAYDa0LYnaO3673dCvuFJPgQxKbJUWYSTnfY89x/VYXsFm6kKgR2pxyGgq4VYGK9W/vvpIi+PKkYwCKtjjb8LKin/zoCPAA7UecMS9mxPeJ/ntdEfjIGTwBcoETsFRRNdVToTdVtQJjc4LBa/5FnJbGNRKFIdRDqx+wr7IbaT+08o5yl+UI2Qogly8JxeOPolVUr94rLXKyY1/n2nkXr+5LoY/sRomoCNJ11wLsMUEmg11j4J3bB93FGtlnmpwm4Q==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIEFzCCAv+gAwIBAgIUeUS7jZnkZLcxjRUQ5uhqrAI7z2gwDQYJKoZIhvcNAQELBQAwgZoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOWTEPMA0GA1UEBwwGQm9zdG9uMRQwEgYDVQQKDAtDb21tYW5kQ29tbTEUMBIGA1UECwwLQ29tbWFuZENvbW0xFDASBgNVBAMMC0NvbW1hbmRDb21tMSswKQYJKoZIhvcNAQkBFhxha2Fwb29yQGNvbW1hbmRjb21wYW5pZXMuY29tMB4XDTIyMDQxNTExNDk1MloXDTIzMDQxNTExNDk1MlowgZoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOWTEPMA0GA1UEBwwGQm9zdG9uMRQwEgYDVQQKDAtDb21tYW5kQ29tbTEUMBIGA1UECwwLQ29tbWFuZENvbW0xFDASBgNVBAMMC0NvbW1hbmRDb21tMSswKQYJKoZIhvcNAQkBFhxha2Fwb29yQGNvbW1hbmRjb21wYW5pZXMuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyTHXlPSUCzHLGXkoSkuXTh2/oONTe+5TcswtFTnq6VDZnZ3m1tNs2EWcOXq6lVjSlfaqByCHUSGa0O54qMAD2WdZjTv08GQS1uYtJhjQvi58P32ost2LBEKYhtyaw8fen81OwJq+tiDHCw8xrx/z610rHGQVRrSojmqC6zLOclkQmrfpAhC2L+enovxfl6xW0FzYJETFYv/jW0ACcaZJBtFb7AfYDlCzvajUQ+dGTpZE1/0UOGdOTNjbMezGxFDyndcJ4ZLQItbG0cE3c1fEQkU06OYgPoOeXGsHM2w1R498oS/pk1ZLB1LtDUfKl7PVmjJGoytCi38Huft/95u0JQIDAQABo1MwUTAdBgNVHQ4EFgQUawg+tyAVohufNTVu7RXqPtu+B4MwHwYDVR0jBBgwFoAUawg+tyAVohufNTVu7RXqPtu+B4MwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAPom0ZUQx3OWXlO7R5Goyv7cEepq+Nikd82chqzUvwhXW5Azb3xsC+cgh0srjYlrRC9QJk7m43yQE1xa0DM4aKi/rA/l9rLJpXfjQj+97V0SA8JMrCxbcxdN+v2mN1vp8xprJ2i+nPtCBPqLM2XA0kUQ44zeygCm+L78zElYu79r3YF6ObzA9D3/Fa794zFWqI/1ggmOdI4T3kzUgFxv1YMTYZ8rgWcICVs1mSU2zkT5ScJq0NJPENR0jpzFHzirzIJUgnAcOWnCnzyCKDgpJI/+9yJNzLaR97LHk12cVfQMuBvLcchRian08sZ/J4a440h54bB9EByp+853rUpHhVQ==</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></saml2p:AuthnRequest>
As #timothy suggested i added the Id = "#" + Id
and below is the XML generated
<saml2p:AuthnRequest ID="_35ab8f46-0ba1-4a29-a153-b02e97bf1397" Version="2.0" ForceAuthn="false" IssueInstant="2022-05-10T09:25:33Z" Destination="https://auth.pingone.com/172e7894-5cbe-456b-b451-d2585aeab74f/saml20/idp/sso" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="http://localhost:20630/CASCC/SamlConsume" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://localhost:20630</saml2:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><ds:Reference URI="#_35ab8f46-0ba1-4a29-a153-b02e97bf1397"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><ds:DigestValue>0iGmT3qeJrHVXJveUe5AboRo65hxD25OjVpbbxWvbUo=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>InYJ2yGLSnL9Q2BVaWBfABpcpiViFgZH6XnvhYU0I67sPI/KTb6g39MZMBM4XiUDNTpjGXHcZn9c2elh+NnVAx/SPX8R0Yjq7dKiVe+Zz6BFKk0DCSA9Q2APFCk2uJZVlvKza3tIjoxrBvQuxZcNZxsMOUm8LEWnhQ3ElgN7pisHj5AiAzc/VluPIl21BG+tTolV/Ab7bg+B7YdBwK4++QEyK0R7dsYoZex+NsLf1+zel1xWg2PbZgTXOi4PXFB9RvIPXDUtfMPCSOUQRUdgbI6GeV5X+ZWCGOs0m0FnnZD7hL1WR1sWOcHUgY0DSIpgtToJintjx0f5HphidWZF9/sjP+zR9QEOtkcBMYl9JacO5tbNp49fZSVuuqN2pMxcSCE2BmPdoWw1t/CHrKFOzOfNyNQsvauP2UpufQQt+lxUePpvE7VZNuXYQ+hGv74FkBpy6NU58x3agqOP0NeMsyrT+R0AOSTCXWqzfogYIOR9t/mOFMTohKJqjPXB7H2+LrlOcmQM/+HHUf21F4KP6w2ujbFESOgCZmoyou0gBDEAtT4xbYvwnplZwSbYaKHQQhunyzesfqtdF8bY9+0jVsfj0+e7tzofoURb+d6HMtbJxDnIg4VUzmI2QHEUhNJzT1nAS2cbVieP/kGzmLQ9TKGhYdTUnWVa16oXZz+qkeo=</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIFqDCCA5ACFAQ5F+2NYAb4N/enCOaeA/V2IVPYMA0GCSqGSIb3DQEBCwUAMIGNMQswCQYDVQQGEwJVUzELMAkGA1UECAwCVVMxCzAJBgNVBAcMAk5ZMRQwEgYDVQQKDAtDb21tYW5kQ29tbTEUMBIGA1UECwwLQ29tbWFuZENvbW0xCzAJBgNVBAMMAkNDMSswKQYJKoZIhvcNAQkBFhxha2Fwb29yQGNvbW1hbmRjb21wYW5pZXMuY29tMB4XDTIyMDUwOTEyMDcyNVoXDTIzMDUwOTEyMDcyNVowgZIxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJVUzELMAkGA1UEBwwCTlkxFDASBgNVBAoMC0NvbW1hbmRDb21tMRQwEgYDVQQLDAtDb21tYW5kQ29tbTEQMA4GA1UEAwwHQ29tbWFuZDErMCkGCSqGSIb3DQEJARYcYWthcG9vckBjb21tYW5kY29tcGFuaWVzLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKoMSbgGecTY5d6bNjCEnpX2YxY+QRNDT0v/zGpO23PZlt+fuaYHr+b0hP3R/3cCxVTmd36o6MNASjT/slq8aFTdk49sW/zwICNa5AtjRRBVHGOmNYz/ntbo1KIQzC1faoGg+1CiTBL/vflQN4EWMyKGg/GfyIeKLODmOzzx41U5Y/Bv22X8bMmnFgYtwBMh2c7X0hNysqUmkc81sJ5cDgcwNbU4tu+sLslxI+1iOmmDtZBfcYmn+5vU4lFy8XZIODqN0eWpOyvH+a6r6rhAe9vIPwjWv2oh1Ktw0HE3b4JIgk/Vk4YvHKeSTjeC0biue7EF1c0sexOac5KpRhaWNxY4tmHY0dxKT1I21ls7TFd1x9E9A+n5Ff+INb9O4V0OmTrJUiXHZ44vpOi2kv1zbf2lSVFXwF6fhcb1KqxP2XQUMr7Fs6P5JUuH9h1AB5Kf7pjcrza7jjWU3LFRQzwISnJZNV+g1f62VM1S3AHpn1YFaI49Kpn9k5kuqWgGPUlIJq+9tWIy19lL6D3vzYI4yzZR4sGp8NcdSlKR8FgMgfB3bU4DtP85agoEOQ5C2DKV8No3jLVEJ8qFMhn/kLzcDy9oWF7ZVQGUmYuNo0q5T9O4dXcX0alXx0PS9UKJwfw23sGfUenwLI9HZEAqK5f3UEaDnfFmhxlajIAMj2hPldODAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAL4Fr2RzIH0O4VJRgYQr1ASeSghzijkhSHpjmL3fCEVrS7WvYtgKr3gXC5tQ/8i3Immh2aqMmbmq1gk/885frCMW76e0I1ZRfSw0ktUa04WlftVLeg9lzqPEmNKwaxzSudcR+WdEnLKrm3DHXltXqXw2yuDzy1SWGeyfZ+Lq62geahBkGWn5YoQqsxbmvhFDZNtDvinUI0GsbmTEsv9oxdWGGfl0spg6y0cO5WW/8fTh6Jrpk2RjOWcx7wUChQbv/Wu4WH9S7g78/F5HSy5hQ2PTg/CVtFXt/zScj6pxXb0Uov4/PXE7zHyLPUqtOxgasov4FurDJZaxUVNE5hu9OVLiHmw0jyU0t6myON+B4+a6I2xeWDBe1EQJyK2G22yISN6o4UILD3YL3gnl/xZoe/64sKP59RU0Gxv3pyYTpCtp+DYR8xYWzN8hVG0KHlxSypkh0TwQ7a4H4x5LOXZ5Qinr1qHgjgJY9LCAYHfvX6i+pctsd+na8ZUEPKZH/ARFz1LDx0RS5RbZhsnyn7GkpJZEuUUeS+aOYkuFLlvBopcKnP8KmKXjjRmrhHaNhPhnK8cJgai377uNk87xUt2WnMankROZajIK+7M6xMTq5WgmmDPE16o6zp+mdn5I8RzglelDFtgCAf9Hz2vupH4v8fcg772fzIf277zZpl8RZc36</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></saml2p:AuthnRequest>
However when i try to validate it using https://tools.chilkat.io/xmlDsigVerify.cshtml
I get valid signature but https://console.pingone.com/ says invalid signature so may be certificates is the one i suggest it is blocking something please suggest
My Latest code looks like
public XmlDocument SignXML(XmlDocument xml)
{
X509Certificate2 cert = new X509Certificate2(#"" + SPCertificateLocation, SPCertificatePassword);// , X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
// set key, signing algorithm, and canonicalization method
var signedXml = new SignedXml(xml.DocumentElement) { SigningKey = cert.GetRSAPrivateKey() };
signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
//signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url;
signedXml.SignedInfo.CanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#";
// sign whole document using "SAML style" transforms
var reference = new Reference { Uri = "#"+_id };
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigExcC14NTransform());
signedXml.AddReference(reference);
KeyInfo keyInfo = new KeyInfo();
KeyInfoX509Data keyInfoData = new KeyInfoX509Data(cert);
keyInfo.AddClause(keyInfoData);
signedXml.KeyInfo = keyInfo;
// create signature
signedXml.ComputeSignature();
// get signature XML element and add it as a child of the root element
//signedXml.GetXml();
//XmlElement xmlSignature = signedXml.GetXml();
//AssignNameSpacePrefixToElementTree(xmlSignature, "ds");
// Add prefix "ds:" to signature
XmlElement signature = signedXml.GetXml();
SetPrefix("ds", signature);
// Load modified signature back
signedXml.LoadXml(signature);
// this is workaround for overcoming a bug in the library
signedXml.SignedInfo.References.Clear();
//var reference2 = new Reference { Uri = "#" + _id };
//reference2.AddTransform(new XmlDsigEnvelopedSignatureTransform());
//reference2.AddTransform(new XmlDsigExcC14NTransform());
//signedXml.AddReference(reference2);
// Recompute the signature
signedXml.ComputeSignature();
string recomputedSignature = Convert.ToBase64String(signedXml.SignatureValue);
// Replace value of the signature with recomputed one
ReplaceSignature(signature, recomputedSignature);
// Append the signature to the XML document.
xml.DocumentElement.InsertAfter(xml.ImportNode(signature, true), xml.DocumentElement.FirstChild);
//xml.DocumentElement?.AppendChild(signedXml.GetXml());
return xml;
}
I was able to validate your XML with perl's XML::Sig after a few changes that I had to make to XML::Sig since it does not currently support SignedInfo without an ID.
https://tools.chilkat.io/xmlDsigVerify.cshtml also validates it fine so the issue is likely in your validation code that you did not show.

How to add new elements to a SOAP XML

I have a SOAP XML file name "LogEvents.xml" that I want to add/remove elements from it.
<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2001/12/soap-envelope" SOAP-ENV:encodingStyle="http://www.w3.org/2001/12/soap-encoding" >
<SOAP-ENV:Body xmlns:lle="http://www.examplee.org/logevents" >
<Event>
<eventid>ID-1</eventid>
<title>title1</title>
<description>desc1</description>
<location>
<lat>1.357207</lat>
<long>103.944880</long>
<address>address1</address>
</location>
<datetimestamp>datetime1</datetimestamp>
</Event>
<Event>
<eventid>ID-2</eventid>
<title>title2</title>
<description>desc2</description>
<location>
<lat>1.304121</lat>
<long>103.831950</long>
<address>addres2</address>
</location>
<datetimestamp>datetime2</datetimestamp>
</Event>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Below shows the code that I have tried but failed using Visual Studio.
XDocument xDoc1 = XDocument.Load(#"C:\LogEvents.xml");
xDoc1.Element("SOAP-ENV").Add(new XElement("Event", new XElement("eventid", "strEventID"),
new XElement("title", "title2"),
new XElement("description", "desc3"),
new XElement("location", new XElement("lat", "lat3"),
new XElement("long", "long3"),
new XElement("address", "addresses3")),
new XElement("datetimestamp", "DateTime3")));
I have tried to remove the SOAP envelope in the XML file and replace it with "Events" and edit the C# code accordingly and it works as shown below.
<?xml version="1.0" encoding="utf-8"?>
<!--Changed to Events-->
<Events>
<Event>
<eventid>ID-1</eventid>
<title>title1</title>
<description>desc1</description>
<location>
<lat>1.357207</lat>
<long>103.944880</long>
<address>address1Edge</address>
</location>
<datetimestamp>datetime1</datetimestamp>
</Event>
<Event>
<eventid>ID-2</eventid>
<title>title2</title>
<description>desc2</description>
<location>
<lat>1.304121</lat>
<long>103.831950</long>
<address>addres2</address>
</location>
<datetimestamp>datetime2</datetimestamp>
<!--Changed to Events-->
</Event>
<Events>
XDocument xDoc1 = XDocument.Load(#"C:\LogEvents.xml");
// Changed SOAP-ENV to Events
xDoc1.Element("Events").Add(new XElement("Event", new XElement("eventid", "ID-3"),
new XElement("title", "title3"),
new XElement("description", "desc3"),
new XElement("location", new XElement("lat", "lat3"),
new XElement("long", "long3"),
new XElement("address", "addresses3")),
new XElement("datetimestamp", "DateTime3")));
Is there any method to ignore the SOAP envelope, or a way to work around it?
Use Root. You can always get the default namespace from the root when needed.
XDocument xDoc1 = XDocument.Load(FILENAME);
XElement soap = xDoc1.Root;
XNamespace ns = soap.GetDefaultNamespace();
soap.Add(new XElement("Event", new XElement("eventid", "strEventID"),
new XElement("title", "title2"),
new XElement("description", "desc3"),
new XElement("location", new XElement("lat", "lat3"),
new XElement("long", "long3"),
new XElement("address", "addresses3")),
new XElement("datetimestamp", "DateTime3")));

XML serialized from classes created with xsd is not correct

I have an XML file (it's a SOAP request to an SAP ME Service).
The file looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:me="http://sap.com/xi/ME">
<soapenv:Header />
<soapenv:Body>
<me:ShopOrderByBasicDataQuery_sync>
<me:ShopOrderByBasicDataQuery>
<me:ShopOrder>BOXBUILD_LASER_TEST</me:ShopOrder>
<me:SiteRef>
<me:Site>TEST1</me:Site>
</me:SiteRef>
</me:ShopOrderByBasicDataQuery>
</me:ShopOrderByBasicDataQuery_sync>
</soapenv:Body>
</soapenv:Envelope>
Using Paste Special I used Paste XML as Classes and got a number of classes.
I the created a new Envelope object
Envelope shoporder = new Envelope();
EnvelopeBody shoporderBody = new EnvelopeBody();
ShopOrderByBasicDataQuery_sync shoporderSync = new ShopOrderByBasicDataQuery_sync();
ShopOrderByBasicDataQuery_syncShopOrderByBasicDataQuery shoporderDataQuery = new ShopOrderByBasicDataQuery_syncShopOrderByBasicDataQuery();
shoporderSync.ShopOrderByBasicDataQuery = shoporderDataQuery;
shoporderDataQuery.ShopOrder = "BOXBUILD_LASER_TEST";
shoporderDataQuery.SiteRef = new ShopOrderByBasicDataQuery_syncShopOrderByBasicDataQuerySiteRef();
shoporderDataQuery.SiteRef.Site = "TEST1";
shoporderSync.ShopOrderByBasicDataQuery = shoporderDataQuery;
shoporderBody.ShopOrderByBasicDataQuery_sync = shoporderSync;
shoporder.Body = shoporderBody;
string tmp = (string)SoapHelper.SerializeToXmlString(shoporder);
The string tmp contains this (after a bit of formatting)
<?xml version="1.0" encoding="utf-16"?>
<Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<ShopOrderByBasicDataQuery_sync xmlns="http://sap.com/xi/ME">
<ShopOrderByBasicDataQuery>
<ShopOrder>BOXBUILD_LASER_TEST</ShopOrder>
<SiteRef>
<Site>TEST1</Site>
</SiteRef>
</ShopOrderByBasicDataQuery>
</ShopOrderByBasicDataQuery_sync>
</Body>
</Envelope>
Which is not a correct file! What have I done wrong?

How to make WCF Client conform to specific WS-Security - sign UsernameToken and SecurityTokenReference

I need to create a wcf client to call a service that I have no control over.
I have been given a wsdl and a working soapui project.
The service uses both a username/password and a x509 certificate.
UPDATE
I now understand what the problem is, but am still unsure what steps I need to take to be able to create the required message, so any help would be much appreciated.
I need to sign both the UsernameToken and the SecurityTokenReference.
The code I had to create the custom binding has been removed from this post as its no longer used. I no longer add a SecurityBindingElement to the binding, instead I add a new behaviour that writes the security element into the header.
So the security node is created from scratch by subclassing the SignedXml class, adding signing references and then calling ComputeSignature to create the Signature node within the Security header.
You need to pass the xml to sign into the SignedXml constructor for this to work. It is no problem passing in the UsernameToken and this appears to be signed correctly.
The problem is that the SecurityTokenReference is only created when ComputeSignature() is called, so I'm not able to add a signing Reference to this element, as it does not exist at the time it is required (within the overridden GetIdElement method of SignedXml which is called prior to ComputeSignature())
The code I'm using to create the signature block to insert into the Security header is as follows
string certificatePath = System.Windows.Forms.Application.StartupPath + "\\" + "Certs\\sign-and- enc.p12";
XmlDocument xd = new XmlDocument();
xd.LoadXml(xml);
// Set Certificate
System.Security.Cryptography.X509Certificates.X509Certificate2 cert = new X509Certificate2(certificatePath, "password");
MySignedXml signedXml = new MySignedXml(xd);
signedXml.SigningKey = cert.PrivateKey;
// Create a new KeyInfo object.
KeyInfo keyInfo = new KeyInfo();
keyInfo.Id = "";
MemoryStream keyInfoStream = new MemoryStream();
XmlWriter keyInfoWriter = XmlWriter.Create(keyInfoStream);
WSSecurityTokenSerializer.DefaultInstance.WriteKeyIdentifierClause(keyInfoWriter, new LocalIdKeyIdentifierClause("token_reference", typeof(X509SecurityToken)));
keyInfoWriter.Flush();
keyInfoStream.Position = 0;
XmlDocument keyInfoDocument = new XmlDocument();
keyInfoDocument.Load(keyInfoStream);
XmlAttribute attrib = keyInfoDocument.CreateAttribute("ValueType");
attrib.InnerText = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3";
keyInfoDocument.ChildNodes[1].ChildNodes[0].Attributes.Append(attrib);
KeyInfoNode keyInfoNode = new KeyInfoNode();
keyInfoNode.LoadXml(keyInfoDocument.DocumentElement);
keyInfo.AddClause(keyInfoNode);
// Add the KeyInfo object to the SignedXml object.
signedXml.KeyInfo = keyInfo;
// Need to use External Canonicalization method.
signedXml.SignedInfo.CanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#";
// Create a reference to be signed.
Reference reference = new Reference();
reference.Uri = "#UsernameToken-1";
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
env.Algorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
reference.AddTransform(env);
reference.DigestMethod = "http://www.w3.org/2000/09/xmldsig#sha1";
signedXml.AddReference(reference);
Reference reference2 = new Reference();
reference2.Uri = "#token_reference";
XmlDsigEnvelopedSignatureTransform env2 = new XmlDsigEnvelopedSignatureTransform();
env2.Algorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
reference2.AddTransform(env2);
reference2.DigestMethod = "http://www.w3.org/2000/09/xmldsig#sha1";
signedXml.AddReference(reference2);
// Add the Signature Id
signedXml.Signature.Id = "MYSIG_ID";
// Compute the signature.
signedXml.ComputeSignature();
XmlElement xmlDigitalSignature = signedXml.GetXml();
where the xml variable is the the UsernameToken xml string, and the MySignedXml class is a subclassed SignedXml with the GetIdElement method overridden (to try to find and correctly refreence the non-existant SecurityTokenReference)
I've spend days researching and testing this now, and unfortunately the company supplying the service isn't any help - but I need to use their service.
Full working soap message (soapUI project)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:XXXXX">
<soapenv:Header xmlns:ebxml="http://docs.oasis-open.org/ebxml-msg/ebms/v3.0/ns/core/200704/">
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<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="CertId-D05E596B5ABC341FEB13505090224061" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">MIIEnDCCBAWgAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBxDELMAkGA1UEBhMCTloxDTALBgNVBAgTBFdHVE4xEzARBgNVBAcTCldlbGxpbmd0b24xGDAWBgNVBAoTD0lSRFN0dWR5bGlua0IyQjEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxHjAcBgNVBAMTFWRldmNhLmIyYi5pcmQuZ292dC5uejEXMBUGA1UEKRMORGV2ZWxvcG1lbnQgQ0ExKDAmBgkqhkiG9w0BCQEWGWNocmlzLnNjaHVsdHpAaXJkLmdvdnQubnowHhcNMTEwOTE1MDIwNjIwWhcNMjEwOTEyMDIwNjIwWjCByTELMAkGA1UEBhMCTloxDTALBgNVBAgTBFdHVE4xEzARBgNVBAcTCldlbGxpbmd0b24xGDAWBgNVBAoTD0lSRFN0dWR5bGlua0IyQjEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxJTAjBgNVBAMTHHNpZ24tYW5kLWVuYy5kZXYuaXJkLmdvdnQubnoxFTATBgNVBCkTDHNpZ24tYW5kLWVuYzEoMCYGCSqGSIb3DQEJARYZY2hyaXMuc2NodWx0ekBpcmQuZ292dC5uejCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAykyZHVnXjsG220zB3kNOsGBeGP2rdNbLlIqW1D8yZO1fcj3/RhRiqsopbUrb8AU1ClpfhbH2K68kg7V91VAY0qrwNxP+pPPo1vYKMU6pT38qJGQzffr+iV2BCJshZvSk9E7QSWO5mFNstdg19xc+5ST1Lgb3fefuRG2KZVxPx0sCAwEAAaOCAZUwggGRMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDQGCWCGSAGG+EIBDQQnFiVFYXN5LVJTQSBHZW5lcmF0ZWQgU2VydmVyIENlcnRpZmljYXRlMB0GA1UdDgQWBBSczRKXKPe3Sin7eFrVXfI7MXckzzCB+QYDVR0jBIHxMIHugBSLWxPSZd9otEj16vhLyovMCI9OMaGByqSBxzCBxDELMAkGA1UEBhMCTloxDTALBgNVBAgTBFdHVE4xEzARBgNVBAcTCldlbGxpbmd0b24xGDAWBgNVBAoTD0lSRFN0dWR5bGlua0IyQjEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxHjAcBgNVBAMTFWRldmNhLmIyYi5pcmQuZ292dC5uejEXMBUGA1UEKRMORGV2ZWxvcG1lbnQgQ0ExKDAmBgkqhkiG9w0BCQEWGWNocmlzLnNjaHVsdHpAaXJkLmdvdnQubnqCCQDL/qDdlx2j6DATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEFBQADgYEAS4ZPIVVpgTOGN4XcIC3SiYlxF8wYg7qnUhH5wJsAD3VCKfj68j9FSJtdBWLlWvvRxEoDP2lZ0IbFl6Rjnl+2ibzFnyac2G1AVm5mwPrNKHBQJ9J5eDJi0iUVY7Wphz86tKnqj34GvlHPNXmrF7oGEcDhPwK0T8zRdE/pvKIUiJc=</wsse:BinarySecurityToken>
<ds:Signature Id="Signature-2" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<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="#CertId-D05E596B5ABC341FEB13505090224061">
<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>3iVAUEAt8vAb7Ku+jf2gwSkSm0Q=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#UsernameToken-1">
<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>r4HLEAWJldJwmEmcAqV6Y8rnTPE=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
YGh2I3VcukqjT0O7hKItiykWN5tlID18ZXRCwQjXriHmnVsO4wGcHjWfmhuNDecq+xRN+SjG8E7M
2Rx/5/BbFKbVlNOkQOSbSxIs1YT9GaThK16pMrX5KRkkJme1W3R0pGIIQh6gGRSUf79RZUIYxyVl
LqdIe561TXXDdtbt/6Q=
</ds:SignatureValue>
<ds:KeyInfo Id="KeyId-D05E596B5ABC341FEB13505090224372">
<wsse:SecurityTokenReference wsu:Id="STRId-D05E596B5ABC341FEB13505090224373" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Reference URI="#CertId-D05E596B5ABC341FEB13505090224061" 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:UsernameToken wsu:Id="UsernameToken-1" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>XXXXXX</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">XXXXXXX</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<ebxml:Messaging xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ebxml:UserMessage>
<ebxml:MessageInfo>
<ebxml:Timestamp>2002-02-02T14:18:02.0Z</ebxml:Timestamp>
<ebxml:MessageId>bf9433d9-c6e9-4c12-9c98-724008a09c21</ebxml:MessageId>
</ebxml:MessageInfo>
<ebxml:PartyInfo>
<ebxml:From>
<ebxml:PartyId type="identifier">Trading Partner X</ebxml:PartyId>
<ebxml:Role>Provider</ebxml:Role>
</ebxml:From>
<ebxml:To>
<ebxml:PartyId type="identifier">XXXXXXX</ebxml:PartyId>
<ebxml:Role>Requestor</ebxml:Role>
</ebxml:To>
</ebxml:PartyInfo>
<ebxml:CollaborationInfo>
<ebxml:AgreementRef>urn:XXXXXXXXX</ebxml:AgreementRef>
<ebxml:Service type="Web Service">urn:XXXXXXXX</ebxml:Service>
<ebxml:Action>customerInformation</ebxml:Action>
<ebxml:ConversationId>e302426a-b2d9-4ff1-a14b-fbbc2f40a017</ebxml:ConversationId>
</ebxml:CollaborationInfo>
</ebxml:UserMessage>
</ebxml:Messaging>
</soapenv:Header>
<soapenv:Body>
<urn:ConnectionTest>
<Message>Bonjour</Message>
</urn:ConnectionTest>
</soapenv:Body>
</soapenv:Envelope>
We were supplied with some documentation. The security section is copied below
The following security must be applied to each request in the following order:
A wsse:UsernameToken must be included and contain:
The Agent‟s Portal Username for the value of the wsse:Username element
The Agent‟s Portal Password for the value of the wsse:PasswordText (clear text) in the Password element
A Signature block:
Digital Signatures are created using x509 certificates. Each software provider is required to hold and protect a valid certificate and private key issued by [To Be Determined]. With each service request the software must:
Include the Certificate that matches the private key used for signing as a wsse:BinarySecurityToken and use it as the wsse:SecurityTokenReference for the Signature
Sign the wsse:BinarySecurityToken
Sign the wsse:UsernameToken
Use Canonicalization Method Algorithm: http://www.w3.org/2001/10/xml-exc-c14n#
Use Signature Method Algorithm: http://www.w3.org/2000/09/xmldsig#rsa-sha1
Use Digest Method Algorithm: http://www.w3.org/2000/09/xmldsig#sha1
Update
Image of the SoapUI configuration I was initially given
Finally sorted the problem today. In terms of terminology, it is not the SecurityTokenReference that I need to sign, but the Binary Security Token.
In order to do this I needed to hide the certificates for Initiator and Recipient and add a signed supporting token.
I went back to using configuration to create and sign the message, rather than trying to add the signature manually.
Other problem that would have stopped this from working is that I had an incorrect namespace on my custom 'Messaging' header, so be mindful of namespaces, I didn't think they would be as important as what they are.
The code to create the binding follows
private System.ServiceModel.Channels.Binding GetCustomBinding()
{
System.ServiceModel.Channels.AsymmetricSecurityBindingElement asbe = new AsymmetricSecurityBindingElement();
asbe.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12;
asbe.InitiatorTokenParameters = new System.ServiceModel.Security.Tokens.X509SecurityTokenParameters { InclusionMode = SecurityTokenInclusionMode.Never };
asbe.RecipientTokenParameters = new System.ServiceModel.Security.Tokens.X509SecurityTokenParameters { InclusionMode = SecurityTokenInclusionMode.Never };
asbe.MessageProtectionOrder = System.ServiceModel.Security.MessageProtectionOrder.SignBeforeEncrypt;
asbe.SecurityHeaderLayout = SecurityHeaderLayout.Strict;
asbe.EnableUnsecuredResponse = true;
asbe.IncludeTimestamp = false;
asbe.SetKeyDerivation(false);
asbe.DefaultAlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic128Rsa15;
asbe.EndpointSupportingTokenParameters.Signed.Add(new UserNameSecurityTokenParameters());
asbe.EndpointSupportingTokenParameters.Signed.Add(new X509SecurityTokenParameters());
CustomBinding myBinding = new CustomBinding();
myBinding.Elements.Add(asbe);
myBinding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
HttpsTransportBindingElement httpsBindingElement = new HttpsTransportBindingElement();
httpsBindingElement.RequireClientCertificate = true;
myBinding.Elements.Add(httpsBindingElement);
return myBinding;
}
When using the binding, I set the ClientCredentials UserName, ServiceCertificate and ClientCertificate, and all works as expected.
Using the code is as follows
using (CredentialingService.SOAPPortTypeClient client = GetCredentialingClient())
{
client.Open();
etc....
}
private static CredentialingService.SOAPPortTypeClient GetCredentialingClient()
{
CredentialingService.SOAPPortTypeClient client = new CredentialingService.SOAPPortTypeClient(GetCustomBinding(), new EndpointAddress(new Uri(Settings.AppSettings.B2BUrl), new DnsEndpointIdentity(Settings.AppSettings.B2BDNSEndpoint), new AddressHeaderCollection()));
client.Endpoint.Contract.ProtectionLevel = System.Net.Security.ProtectionLevel.None;
SetClientCredentialsSecurity(client.ClientCredentials);
return client;
}
where GetCustomBinding is specified in my post
SetClientCredentialsSecurity is where the certificate is set, and is as follows
private static void SetClientCredentialsSecurity(ClientCredentials clientCredentials)
{
clientCredentials.UserName.UserName = Settings.AppSettings.B2BUserName;
clientCredentials.UserName.Password = Settings.AppSettings.B2BPassword;
string directoryName = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
clientCredentials.ServiceCertificate.DefaultCertificate = new X509Certificate2(Path.Combine(directoryName, Settings.AppSettings.B2BServerCertificateName));
clientCredentials.ClientCertificate.Certificate = new X509Certificate2(Path.Combine(directoryName, Settings.AppSettings.B2BClientCertificateName), Settings.AppSettings.B2BClientCertificatePassword);
}
Hopefully that makes it a bit clearer
Maybe it's because your certificate is not publicly valid. Try this:
System.Net.ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(delegate { return true; });
//...
using (var client = new SrvClient())
{
client.ClientCredentials.UserName.UserName = "usr";
client.ClientCredentials.UserName.Password = "psw";
//...
}

Categories

Resources