C # XML digital signature, ill-formed reference element

0

I have a c # code that generates an xml with the digital signature, but when calling the function signedXml.ComputeSignature() it shows the following error:

  

Malformed Reference Element.

However, I searched for this error and most sites or forums mention removal of the KB3136000 update, except that windows 10 I'm using does not have this update installed .

What can it be?

Follow the code below highlighting the error line:

public static void AssinaDocumento(X509Certificate2 certificadoDigital, string Uri, string xmlOrigem)
{
    int countTagsUri;
    XmlDocument xmlDocument = new XmlDocument();
    XmlDocument xmlDocument2 = new XmlDocument();
    xmlDocument.PreserveWhitespace = false;
    XmlNodeList xmlNodeList;
    Reference reference = new Reference();

    xmlDocument.Load(xmlOrigem);

    xmlDocument2 = xmlDocument;

    XmlDocument xmlAssinado = xmlDocument;
    SignedXml signedXml = new SignedXml(xmlDocument);
    signedXml.SigningKey = certificadoDigital.PrivateKey;

    countTagsUri = xmlDocument.GetElementsByTagName(Uri).Count;
    if (countTagsUri == 0)
    {
        throw new Exception("Uri " + Uri + " não encontrada no XML");
    }

    xmlNodeList = xmlDocument.GetElementsByTagName(Uri);

    foreach (XmlNode xmlnl in xmlNodeList)
    {
        XmlAttributeCollection attributeCollection = xmlnl.FirstChild.Attributes;
        reference.Uri = "#" + attributeCollection["id"].InnerText;

        string res = xmlnl.OuterXml;

        XmlDsigEnvelopedSignatureTransform envelope = new XmlDsigEnvelopedSignatureTransform();
        XmlDsigC14NTransform c14NTransform = new XmlDsigC14NTransform();
        KeyInfo keyInfo = new KeyInfo();

        reference.AddTransform(envelope);
        reference.AddTransform(c14NTransform);

        signedXml.AddReference(reference);

        keyInfo.AddClause(new KeyInfoX509Data(certificadoDigital));

        signedXml.KeyInfo = keyInfo;

        signedXml.ComputeSignature(); // O erro Ocorre aqui

        XmlElement xmlDigitalSignature = signedXml.GetXml();

        XmlNode xmlNode = xmlDocument.ImportNode(xmlDigitalSignature, true);


        xmlDocument.FirstChild.NextSibling.LastChild.InsertAfter(xmlNode, xmlnl.LastChild);


        xmlDocument.PreserveWhitespace = true;
        xmlDocument.Save(@"C:\Users\ter0038\Desktop\assinado.xml");
    }
}
    
asked by anonymous 09.04.2018 / 20:34

1 answer

0

Try this code:

        private XmlDocument AssinarXml(string arquivo, string tagAssinatura, string tagAtributoId, X509Certificate2 x509Cert)
    {
        StreamReader SR = null;

        try
        {
            SR = File.OpenText(arquivo);
            string xmlString = SR.ReadToEnd();
            SR.Close();
            SR = null;

            // Create a new XML document.
            XmlDocument doc = new XmlDocument();

            // Format the document to ignore white spaces.
            doc.PreserveWhitespace = false;

            // Load the passed XML file using it’s name.
            doc.LoadXml(xmlString);

            if (doc.GetElementsByTagName(tagAssinatura).Count == 0)
            {
                throw new Exception("A tag de assinatura " + tagAssinatura.Trim() + " não existe no XML. (Código do Erro: 5)");
            }
            else if (doc.GetElementsByTagName(tagAtributoId).Count == 0)
            {
                throw new Exception("A tag de assinatura " + tagAtributoId.Trim() + " não existe no XML. (Código do Erro: 4)");
            }
            else
            {
                XmlDocument XMLDoc;

                XmlNodeList lists = doc.GetElementsByTagName(tagAssinatura);
                foreach (XmlNode nodes in lists)
                {
                    foreach (XmlNode childNodes in nodes.ChildNodes)
                    {
                        if (!childNodes.Name.Equals(tagAtributoId))
                            continue;

                        if (childNodes.NextSibling != null && childNodes.NextSibling.Name.Equals("Signature"))
                            continue;

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

                        XmlElement childElemen = (XmlElement)childNodes;
                        if (childElemen.GetAttributeNode("Id") != null)
                        {
                            //reference.Uri = ""; // "#" + childElemen.GetAttributeNode("Id").Value;
                            reference.Uri = "#" + childElemen.GetAttributeNode("Id").Value;
                        }
                        else if (childElemen.GetAttributeNode("id") != null)
                        {
                            reference.Uri = "#" + childElemen.GetAttributeNode("id").Value;
                        }

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

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

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

                        XmlDsigC14NTransform c14 = new XmlDsigC14NTransform();
                        reference.AddTransform(c14);

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

                        // Create a new KeyInfo object
                        KeyInfo keyInfo = new KeyInfo();

                        // Load the certificate into a KeyInfoX509Data object
                        // and add it to the KeyInfo object.
                        keyInfo.AddClause(new KeyInfoX509Data(x509Cert));

                        // Add the KeyInfo object to the SignedXml object.
                        signedXml.KeyInfo = keyInfo;
                        signedXml.ComputeSignature();

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

                        nodes.AppendChild(doc.ImportNode(xmlDigitalSignature, true));
                    }
                }

                XMLDoc = new XmlDocument();
                XMLDoc.PreserveWhitespace = false;
                XMLDoc = doc;

                return XMLDoc;
                //string conteudoXMLAssinado = XMLDoc.OuterXml;

                //using (StreamWriter sw = File.CreateText(arquivo))
                //{
                //    sw.Write(conteudoXMLAssinado);
                //    sw.Close();
                //}
            }
        }
        finally
        {
            if (SR != null)
                SR.Close();
        }
    }
    
10.04.2018 / 18:22