TransWikia.com

C# assinatura digital de XML, elemento reference mal formado

Stack Overflow em Português Asked by Lucas Ferreira on January 27, 2021

Tenho um código c# que gera um xml com a assinatura digital, porém ao chamar a função signedXml.ComputeSignature() ele mostra o seguinte erro:

Elemento Reference mal formado.

Entretanto, eu pesquisei sobre esse erro e maioria dos sites ou fóruns cita a remoção da atualização KB3136000, só que no windows 10 que estou usando não tem essa atualização instalada.

O que pode ser?

Segue o código abaixo com destaque para a linha de erro:

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:Userster0038Desktopassinado.xml");
    }
}

2 Answers

Olá, Com a desativação do Win7 e todos migrarem para o Win10 então você deve COMEÇAR o Id com letra e não com número. (Isso acontece muito com o pessoal que implementa NFSe para prefeituras). Digo isso, pelo fato de alguns developers indicarem a Remoção de algumas atualizações do Win7 Exemplo:

(ERRADO)       
        <EnviarLoteRpsEnvio xmlns="http://www.abrasf.org.br/ABRASF/arquivos/nfse.xsd">
            <LoteRps id="002">
        </EnviarLoteRpsEnvio>

(CERTO)    
    <EnviarLoteRpsEnvio xmlns="http://www.abrasf.org.br/ABRASF/arquivos/nfse.xsd">
        <LoteRps id="A002">, onde A pode ser qualquer letra não especial 
    </EnviarLoteRpsEnvio>

Answered by Marinpietri on January 27, 2021

Tenta com este código:

        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();
        }
    }

Answered by Matheus Rizzi on January 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP