Question

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?

Was it helpful?

Solution

The above code works as intended, just if anyone wants to know how to sign XML (other than the numerous examples there already are). There was a problem with the WebService.

Best regards Andreas

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top