I am trying to sign a XML document using a Digital Signature. I have the certificate installed and the output seems to resemble the specification (EXCEPT the Namespace, which it seems is something I am not able to touch in .NET), however I am unable to get the WebService I am sending this to accept this, and it returns with the Error:
VerifyXml: Verification failed: Signature is not valid
I am NOT in control of this WebService and the supplier of this service claims that other people have no problem with this WebService.
I have also tried using this verification tool:
http://www.aleksey.com/xmlsec/xmldsig-verifier.html
Which returns with the error: data do not match:signature do not match, ergo, I think I am doing something wrong.
My code looks like this:
X509Store store = new X509Store(StoreName.My);
store.Open(OpenFlags.ReadOnly);
X509Certificate2 cert = store.Certificates.Find(X509FindType.FindByThumbprint, "xxxxxx",
true).OfType<X509Certificate2>().FirstOrDefault();
store.Close();
XmlDocument xmlDoc = new XmlDocument();
XmlNamespaceManager namespaces = new XmlNamespaceManager(xmlDoc.NameTable);
namespaces.AddNamespace("ns", "xxxx");
xmlDoc.PreserveWhitespace = false;
xmlDoc.Load(new XmlTextReader("C:\\Development\\testheader.xml"));
SignedXml signedXml = new SignedXml(xmlDoc);
signedXml.SigningKey = cert.PrivateKey;
Reference reference = new Reference();
reference.Uri = "";
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
XmlDsigC14NTransform c14n = new XmlDsigC14NTransform();
reference.AddTransform(c14n);
signedXml.AddReference(reference);
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(cert));
signedXml.KeyInfo = keyInfo;
signedXml.ComputeSignature();
XmlNode parentNode = xmlDoc.SelectSingleNode("/ns:TopLevelNode", namespaces);
parentNode.InsertAfter(xmlDoc.ImportNode(signedXml.GetXml(), true),
parentNode.FirstChild);
if (xmlDoc.FirstChild is XmlDeclaration)
xmlDoc.RemoveChild(xmlDoc.FirstChild);
XmlTextWriter xmltw = new XmlTextWriter("C:\\Development\\test2.xml",
new UTF8Encoding(false));
xmlDoc.WriteTo(xmltw);
xmltw.Close();
I have tried validating the SignedXML in .NET and this seems to validate, but since it is the language it is written in, I am not putting to much trust in this.
My specification looks like this:
<Signature xmlns="NonStandard">
<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" />
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>…</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>…</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>…</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
Am I doing something obviously wrong? I am unsure of how important the Namespace is with regards to signing the XML, but since this seems to be a .NET "set in stone", I doubt this could be it?