EFD-Reinf: Invalid signature - Failed to verify XML document signature (using C#)

Asked

Viewed 1,720 times

5

Good afternoon, someone managed to hold the signing of the EFD-Reinf event using C#?

I am sending the event signed and is returning the following occurrence:

{
<?xml version=""1.0"" encoding=""utf-8""?>
<dadosRegistroOcorrenciaEvento>
    <ocorrencias>
        <tipo>1</tipo>
        <localizacaoErroAviso/>
        <codigo>MS0017</codigo>
        <descricao>Assinatura do evento inválida. Falha ao verificar a assinatura do documento XML</descricao>
    </ocorrencias>
</dadosRegistroOcorrenciaEvento>
}

I am using the following code to sign the event:

 String id = @event.Attributes.GetNamedItem("id").Value;


 SignedXml signature = new SignedXml(@event);

 Reference reference = new Reference();
 reference.Uri = "#" + id;

 XmlDsigEnvelopedSignatureTransform env = new 
 XmlDsigEnvelopedSignatureTransform();
 reference.AddTransform(env);

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

 reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";

 KeyInfo keyInfo = new KeyInfo();

 keyInfo.AddClause(new KeyInfoX509Data(certificate));

 signature.SigningKey = certificate.GetRSAPrivateKey();
 signature.AddReference(reference);
 signature.KeyInfo = keyInfo;
 signature.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
 signature.ComputeSignature();

 var reinfEvent = @event.GetElementsByTagName("Reinf").Item(0);
 reinfEvent.AppendChild(signature.GetXml());

Someone’s been through this before?

1 answer

3

Muriel, I’ve been through this and today I can successfully sign the events. I am working with eSocial, but the code is basically the same and I even tested the sending of an R-1000 in the EFD-Reinf, also successfully.

Some basic tips that should be followed to successfully subscribe:

  • You must use only the event XML to generate the signature, and then the signed event XML is embedded in the batch XML. Batch XML should never be signed, only events individually are signed.
  • The root tag of the event, Reinf, shall not contain the elements xmlns:xsi and xmlns:xsd, which are normally automatically added by the serializer.
  • Once signed, the event XML should not suffer none change because otherwise the signature becomes invalid. I’ve seen people manually change things in XML after signing, and it’s happened to me that the event’s XML is written to disk using an encoding and batch XML recording, with the event signed in, using another enconding, which also invalidated the signature.

I made a page a while back with some tips on signing an eSocial event XML:

http://suporte.quarta.com.br/eSocial/AssinaturaXml.htm

But in short, the code I’m using for eSocial is as follows::

  //
  // SignedXml.CheckSignature Method (X509Certificate2, Boolean) -> Examples [SHA1]
  // https://msdn.microsoft.com/en-us/library/ms148731(v=vs.110).aspx
  //
  // Using SHA256 with the SignedXml Class
  // https://blogs.msdn.microsoft.com/winsdk/2015/11/14/using-sha256-with-the-signedxml-class/
  //
  private static void SignXmlDoc(XmlDocument xmlDoc, X509Certificate2 certificate)
  {
     //
     // https://docs.microsoft.com/en-us/dotnet/framework/whats-new/#Crypto462
     //
     // SignedXml support for SHA-2 hashing The .NET Framework 4.6.2 adds support
     // to the SignedXml class for RSA-SHA256, RSA-SHA384, and RSA-SHA512 PKCS#1
     // signature methods, and SHA256, SHA384, and SHA512 reference digest algorithms.
     //
     // Any programs that have registered a custom SignatureDescription handler into CryptoConfig
     // to add support for these algorithms will continue to function as they did in the past, but
     // since there are now platform defaults, the CryptoConfig registration is no longer necessary.
     //
     //// First of all, we need to register a SignatureDescription class that defines the DigestAlgorithm as SHA256.
     //// You have to reference the System.Deployment assembly in your project.
     //CryptoConfig.AddAlgorithm(
     //   typeof(System.Deployment.Internal.CodeSigning.RSAPKCS1SHA256SignatureDescription),
     //   "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
     // RSAPKCS1SHA256SignatureDescription -> Disponível desde .NET Framework 4.5

     SignedXml signedXml = new SignedXml(xmlDoc);

     // Add the key to the SignedXml document. 
     signedXml.SigningKey = certificate.GetRSAPrivateKey();   // Disponível desde .NET Framework 4.6
     //signedXml.SigningKey = GetRSAPrivateKey(certificate);

     //
     // https://docs.microsoft.com/en-us/dotnet/framework/whats-new/#Crypto462
     //
     // SignedXml support for SHA-2 hashing The .NET Framework 4.6.2 adds support
     // to the SignedXml class for RSA-SHA256, RSA-SHA384, and RSA-SHA512 PKCS#1
     // signature methods, and SHA256, SHA384, and SHA512 reference digest algorithms.
     signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA256Url; //"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"

     // Create a reference to be signed. Pass "" to specify that
     // all of the current XML document should be signed.
     Reference reference = new Reference(string.Empty);

     reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
     reference.AddTransform(new XmlDsigC14NTransform());
     reference.DigestMethod = SignedXml.XmlDsigSHA256Url; //""http://www.w3.org/2001/04/xmlenc#sha256"

     // 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(certificate));

     // 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));

     if (xmlDoc.FirstChild is XmlDeclaration)
        xmlDoc.RemoveChild(xmlDoc.FirstChild);
  }

In EFD-Reinf the only difference is that the Reference.URI element must contain the event ID, with the character # ahead (thing you are already doing), whereas in eSocial this element must be empty. So for EFD-Reinf the line that creates the object Reference, in that role that I gave you, it should be changed to:

     Reference reference = new Reference("#" + idEvento);

Here is an example of Reinf batch that was successfully shipped:

http://suporte.quarta.com.br/eSocial/arquivos/R1000_EnvioLote.xml

Browser other questions tagged

You are not signed in. Login or sign up in order to post.