Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

signing a xml document with x509 certificate

Every time I try to send a signed XML, the web service verifier rejects it.

To sign the document I just adapted this sample code provided by Microsoft:

http://msdn.microsoft.com/es-es/library/ms229745(v=vs.110).aspx

My implementation:

    public static XmlDocument FirmarXML(XmlDocument xmlDoc)
    {
        try
        {
            X509Certificate2 myCert = null;
            var store = new X509Store(StoreLocation.CurrentUser); //StoreLocation.LocalMachine fails too
            store.Open(OpenFlags.ReadOnly);
            var certificates = store.Certificates;
            foreach (var certificate in certificates)
            {
                if (certificate.Subject.Contains("xxx"))
                {
                    myCert = certificate;
                    break;
                }
            }

            if (myCert != null)
            {
                RSA rsaKey = ((RSA)myCert.PrivateKey);

                // Sign the XML document. 
                SignXml(xmlDoc, rsaKey);                    
            }

        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        return xmlDoc;
    }


    // Sign an XML file. 
    // This document cannot be verified unless the verifying 
    // code has the key with which it was signed.
    public static void SignXml(XmlDocument xmlDoc, RSA Key)
    {
        // Check arguments.
        if (xmlDoc == null)
            throw new ArgumentException("xmlDoc");
        if (Key == null)
            throw new ArgumentException("Key");

        // Create a SignedXml object.
        SignedXml signedXml = new SignedXml(xmlDoc);

        // Add the key to the SignedXml document.
        signedXml.SigningKey = Key;

        // Create a reference to be signed.
        Reference reference = new Reference();
        reference.Uri = "";

        // Add an enveloped transformation to the reference.
        XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
        reference.AddTransform(env);

        // Add the reference to the SignedXml object.
        signedXml.AddReference(reference);

        // Compute the signature.
        signedXml.ComputeSignature();

        // Get the XML representation of the signature and save
        // it to an XmlElement object.
        XmlElement xmlDigitalSignature = signedXml.GetXml();

        // Append the element to the XML document.
        xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));

    }

I think I am following the same steps using my own certificate, however it doesn't works as expected.

Any suggestion will be welcome.

like image 931
Michael Knight Avatar asked Apr 30 '14 17:04

Michael Knight


People also ask

How does XML signing work?

An XML digital signature (XML DSIG) is an electronic, encrypted, stamp of authentication on digital information such as messages. The digital signature confirms that the information originated from the signer and was not altered in transmission.

How do I sign an XML file in Java?

In order to create an XML Digital Signature, use the following procedure: Generate a pair of Keys called Private Key and Pubic Key. Obtain the original XML document. Sign the original XML document using both Private and Public key by Java API and generate another document that has a XML Digital Signature.


2 Answers

How does the server know what certificate the document is signed with? You seem to not to include the cert in the signed document:

    KeyInfo keyInfo = new KeyInfo();
    KeyInfoX509Data keyInfoData = new KeyInfoX509Data( Key );
    keyInfo.AddClause( keyInfoData );
    signedXml.KeyInfo = keyInfo;

If you need more details, consult my blog entry

http://www.wiktorzychla.com/2012/12/interoperable-xml-digital-signatures-c_20.html

like image 98
Wiktor Zychla Avatar answered Sep 20 '22 12:09

Wiktor Zychla


It's a long time since this post has been created. I got the same problem with the digital signature can not be validated.

For whom who has the same issue. In my case the difference is XmlDocument.PreserveWhitespace option.

When the PreserveWhitespace = true, the document is not valid when checking against the public key. PreserveWhitespace = false makes the signed XML valid.

I guess that when saving the signed XML to file and sending it to server. There is some space or special characters are inserted to the document and make it invalid.

like image 38
Eric Ngo Avatar answered Sep 20 '22 12:09

Eric Ngo