Function generating invalid digital signature

1.4k views Asked by At

I am trying to digitally sign a XML document using SHA-1 algorithm, but the resulting signed XML has SHA-256 parts in it. I saw this question and tried to adapt it to my function, but it does not work, as it references both SHA-1 and SHA-256 on the resulting XML.

Here is my actual code:

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

    try
    {
        SR = System.IO.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;
                    }
                    else if (childElemen.GetAttributeNode("id") != null)
                    {
                        reference.Uri = "#" + childElemen.GetAttributeNode("id").Value;
                    }
                    //reference.DigestMethod = "http://www.w3.org/2000/09/xmldsig#sha1";
                    // Create a SignedXml object.
                    SignedXml signedXml = new SignedXml(doc);
                    // Add the key to the SignedXml document
                    signedXml.SigningKey = x509Cert.PrivateKey;

                    signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url;
                    // 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;

            string conteudoXMLAssinado = XMLDoc.OuterXml;

            using (StreamWriter sw = System.IO.File.CreateText(arquivo))
            {
                sw.Write(conteudoXMLAssinado);
                sw.Close();
            }
        }
    }
    finally
    {
        if (SR != null)
            SR.Close();
    }
}

How to make this function sign just as SHA1?
Here is an example of the output signature:

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
   <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/2001/04/xmlenc#sha256" />
         <DigestValue>pp8br9Yd9SdFWQhFdCOJmJlEsKGnlbpovZ6Ssp7VwC4=</DigestValue>
      </Reference>
   </SignedInfo>
   <SignatureValue>ZSWsXhFu6qw5NGy8+hVAA8oW7nUp1vX2Wv+YpnFiC9UWTdRdYlUDjAiah9symfOX2tOEUk69aJjaL/bSZoc5BFFYqQOm2kBVnlbEYQ0lQpvy4sEJodTWiVGaikVldFWUjPkhjwxy9SpreOKBHpEOPkdkyb8SS8k5bE1yA6IbTE3JfyCmeojDSha3lVZzbX8rBN6R2Mwkwg9Eh9dOPjk4+Wu/V5APDQfDa9viQlDAG+gtBTQacMb2aZrNR8fYqm8fSbwhfxgBaMbCqp3A/KqEm9M5Tj8ql/5flRRJ1zmlrwvByfff5+unhdhMzhKcPeoEAkBBJu4RlJVDgf1BNnexNw==</SignatureValue>
   <KeyInfo>
      <X509Data>
         <X509Certificate>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</X509Certificate>
      </X509Data>
   </KeyInfo>
</Signature>

EDIT

Using the suggested code, it returned an error in the line Reference reference = new Reference($"#{list[0].Attributes["id"].Value}");:

NullReferenceException: Object reference not set to an instance of an object.

I'm using the function this way:

SignXmlFile("E:\\nota.xml", "InfDeclaracaoPrestacaoServico", EscolherCertificado());

And here is an example of XML file I'm using with the function:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.issweb.fiorilli.com.br/" xmlns:xd="http://www.w3.org/2000/09/xmldsig#">
   <soapenv:Header />
   <soapenv:Body>
      <ws:gerarNfse>
         <GerarNfseEnvio xmlns="http://www.abrasf.org.br/nfse.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <Rps>
               <InfDeclaracaoPrestacaoServico>
                  <Rps>
                     <IdentificacaoRps>
                        <Numero>1</Numero>
                        <Serie>999</Serie>
                        <Tipo>1</Tipo>
                     </IdentificacaoRps>
                     <DataEmissao>2018-11-27</DataEmissao>
                     <Status>1</Status>
                  </Rps>
                  <Competencia>2018-11-27</Competencia>
                  <Servico>
                     <Valores>
                        <ValorServicos>209000</ValorServicos>
                     </Valores>
                     <IssRetido>2</IssRetido>
                     <ItemListaServico>01.05</ItemListaServico>
                     <Discriminacao>Discriminacao teste blablabla</Discriminacao>
                     <CodigoMunicipio>3504800</CodigoMunicipio>
                     <ExigibilidadeISS>1</ExigibilidadeISS>
                  </Servico>
                  <Prestador>
                     <CpfCnpj>
                        <Cnpj>01001001000113</Cnpj>
                     </CpfCnpj>
                     <InscricaoMunicipal>15000</InscricaoMunicipal>
                  </Prestador>
                  <Tomador>
                     <IdentificacaoTomador>
                        <CpfCnpj>
                           <Cpf>35770121025</Cpf>
                        </CpfCnpj>
                     </IdentificacaoTomador>
                     <RazaoSocial>DADOS TOMADOR</RazaoSocial>
                     <Endereco>
                        <Endereco>RUA TOMADOR</Endereco>
                        <Numero>23</Numero>
                        <Complemento>COMPLEMENTO TOMADOR</Complemento>
                        <Bairro>BAIRRO TOMADOR</Bairro>
                        <Uf>MG</Uf>
                        <CodigoPais>1058</CodigoPais>
                        <Cep>37170000</Cep>
                     </Endereco>
                     <Contato>
                        <Telefone>(35) 38511836</Telefone>
                        <Email>[email protected]</Email>
                     </Contato>
                  </Tomador>
                  <OptanteSimplesNacional>2</OptanteSimplesNacional>
                  <IncentivoFiscal>2</IncentivoFiscal>
               </InfDeclaracaoPrestacaoServico>
               <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
                  <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>s8BhRVqeQKRh4H6nlHJEQudBJ+w=</DigestValue>
                     </Reference>
                  </SignedInfo>
                  <SignatureValue>IxrI+sqg6XEg7Dl0utAlJviTKT5fTu1NTErntiSjb61B5q/nP68r4wZ12vqXW5/G92pr+ZUZfLVwnG8vrFx8tsX/eObfpwOxZRfissuuOVQrLmFmHOvLs08VpbkffQpvLIhkpDzLV3pcIPsjgo7UQu+99mB4K+iEZYnfedgmJ8s/6EIcJLoWs9TvJHfpANgbEXSndi0nua1uDr9/FN4oO0jD2lRX+JHp7XJNjcjzS1N/kFG+JSyq0R017Ul0F/qR7dcOsBlFvbXtPcYfT6jiZxHjNf5n0xuK1vBHiwGgFHRFf2oF+2/LwqrCVZxiIMZK3ICdGWfdKkc3YCJ5A4px/g==</SignatureValue>
                  <KeyInfo>
                     <X509Data>
                        <X509Certificate>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</X509Certificate>
                     </X509Data>
                  </KeyInfo>
               </Signature>
            </Rps>
         </GerarNfseEnvio>
         <username>01001001000113</username>
         <password>123456</password>
      </ws:gerarNfse>
   </soapenv:Body>
</soapenv:Envelope>
1

There are 1 answers

9
Pedro Gaspar On BEST ANSWER

For the problem you are pointing out, the reason is that you are informing the SignatureMethod as SHA-1:

signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url;

but you are not informing the reference.DigestMethod as SHA-1, you can see that's just the XML part that is going out as SHA-256, so you have to add this line (actually you did, but it's commented out):

reference.DigestMethod = SignedXml.XmlDsigSHA1Url;

That a look at this answer (on Stack Overflow in Portuguese, but the code part is all in english), it uses SHA-256, but the idea is the same:

E-Social. Assinatura do evento inválida

However, your code is a little bit confusing and you are doing things that don't seem necessary, like opening the XML file as a stream, then loading a XmlDocument using the string read from the stream (why not open the XML file direct as a XmlDocument?), and them you open another XmlDocument again in the end...

But I think that the most important part is that you are expecting that a Signature tag already exists in your input XML, but it should not be that way, you should sign a non-signed XML file, and if a signature already exists in the file, you should remove the old signature before signing it again, since the sign process take the whole document to generate a signature.


Here is a suggestion of how you could do your function for signing a XML file using SHA-1 algorithm:

using System;
using System.Xml;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;

private void SignXmlNodes(
   string filename,
   string mainChildTag,
   string idAttributeTag,
   X509Certificate2 x509Cert)
{
   XmlDocument xmlDoc = new XmlDocument();
   // Format the document to ignore white spaces.
   xmlDoc.PreserveWhitespace = false;
   xmlDoc.Load(filename);

   XmlNodeList mainChildList = xmlDoc.GetElementsByTagName(mainChildTag);
   // Loop through the nodes that need to be signed.
   foreach (XmlNode mainChildNode in mainChildList)
   {
      XmlNode nodeForSigning = mainChildNode.ParentNode;

      // It's necessary to create a namespace manager to use with SelectNode methods,
      // otherwise they won't work, because the node has a specific namespace.
      var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
      nsmgr.AddNamespace("ns", nodeForSigning.NamespaceURI);
      nsmgr.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);

      XmlNode nodeWithTheId = nodeForSigning.SelectSingleNode($"ns:{idAttributeTag}", nsmgr);
      if (nodeWithTheId == null)
      {
         throw new Exception($"The tag with ID attribute '{idAttributeTag}' does not exist in the XML file. (Error code: 4)");
      }
      // Uses null-conditional (?.) and null-coalescing (??) operators to set the reference Uri.
      string refUri = nodeWithTheId.Attributes?["id"]?.Value ?? "";
      if (!string.IsNullOrEmpty(refUri))
      {
         refUri = $"#{refUri}";
      }

      // Remove existing signatures in the node, if there's any.
      foreach (XmlNode node in nodeForSigning.SelectNodes("ds:Signature", nsmgr))
      {
         node.ParentNode.RemoveChild(node);
      }

      SignedXml signedXml = new SignedXml((XmlElement) nodeForSigning);
      // Add the key to the SignedXml document
      signedXml.SigningKey = x509Cert.PrivateKey;
      signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url;

      // Create a reference with the specified Uri (id of the informed tag).
      Reference reference = new Reference(refUri);
      reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
      reference.AddTransform(new XmlDsigC14NTransform());
      reference.DigestMethod = SignedXml.XmlDsigSHA1Url;
      // Add the reference to the SignedXml object.
      signedXml.AddReference(reference);

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

      // 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 signature element to the XML document.
      //xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
      nodeForSigning.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
   }

   xmlDoc.Save(filename);
}

You can use it like this:

SignXmlNodes("E:\\nota.xml",
             "InfDeclaracaoPrestacaoServico",
             "InfDeclaracaoPrestacaoServico",
             SelectCertificate());