Jean already listed most of the problems that normally cause this invalid signature error, but, as it is a very common problem, I will replicate here the answer I gave in other posts, which adds some points and gives an example of code in C#.
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, eSocial, 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);
}
If you have to also sign the EFD-Reinf events the only difference is that there the Reference.URI element must contain the event ID, with the character # ahead, whereas in eSocial that element must be empty. So for EFD-Reinf the line that creates the object Reference, in this function I have shown, should be changed to:
Reference reference = new Reference("#" + idEvento);
I have a page with some XML examples of eSocial that, although they are outdated (all the examples of the page are in the v2.2.02 layout, and the current one is v2.4.01), are interesting to see well what should be signed (only the XML of the event) and what should not be signed (the batch XML):
http://suporte.quarta.com.br/eSocial/ExemplosEventosXml.htm