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

4

Good afternoon, has anyone managed to sign the EFD-Reinf event using C #?

I am sending the signed event and it 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());

Has anyone ever been in this situation?

    
asked by anonymous 22.12.2017 / 17:57

1 answer

3

Muriel, I've been through this situation and today I can sign the events successfully. I'm working with eSocial, but, the code is basically the same and I even tried to send an R-1000 to EFD-Reinf, also successfully.

Some basic tips to follow to successfully sign up:

  • You must use only the event XML to generate the signature, and then the signed event XML is embedded in the batch XML. The batch XML must never be signed, only the events are individually signed.
  • The event root tag, Reinf , should not contain the xmlns: xsi and xmlns: xsd elements, by the serializer.
  • Once signed, the event XML should not be no change, otherwise the signature becomes invalid. I've seen people who changed things manually in XML after signed, and it happened to me that the XML of the event was written to disk using an encoding and writing the batch XML, 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:

  

link

But, briefly, the code I am 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 should contain the event ID, with the # character at the front (which you are already doing), whereas in eSocial this element must be empty. So for EFD-Reinf the line that creates the reference object, in this function I passed you, should be changed to:

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

Here is an example of a successful reinf batch:

  

link

    
20.02.2018 / 05:42