C# EFD-REINF 1.03.02 - Invalid event signature. Invalid XML document Digital signature

Asked

Viewed 739 times

1

all good?

I’m trying to make the reference to the digital signature of EFD-REINF (The latest version 1.03.02) event XML (in this case I am testing with R1000) with .Net C#, but framework 4.0.

I don’t really know if I’m doing something wrong but I’ve tried several things to try to subscribe to the event xml and I can’t, I’m always getting the MS0017 - Invalid event signature. Invalid XML document Digital signature.

Look below, it’s the code I’m using to sign the event block.

public static System.Xml.XmlElement XmlAssinado(object reinf, string cpfCnpj, string id)
{
    var certificate = GetCertificado(cpfCnpj);
    var xml = reinf.ToXmlString();
    var xmlDoc = new XmlDocument();

    xmlDoc.LoadXml(xml);

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

    //if (xmlDoc.FirstChild.Attributes["xmlns:xsi"] != null)
    //    xmlDoc.FirstChild.Attributes.Remove(xmlDoc.FirstChild.Attributes["xmlns:xsi"]);

    //if (xmlDoc.FirstChild.Attributes["xmlns:xsd"] != null)
    //    xmlDoc.FirstChild.Attributes.Remove(xmlDoc.FirstChild.Attributes["xmlns:xsd"]);

    Reference reference = new Reference($"#{id}");

    // 1 - Transformação exigida - Envelop
    XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
    reference.AddTransform(env);

    // 2 - Transformação exigida - C14N
    XmlDsigC14NTransform c14 = new XmlDsigC14NTransform();
    reference.AddTransform(c14);

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

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

    //XmlDocument documentoUTF8 = ReconstruirComoUTF8(xmlDoc);

    // Instancia a classe de criptografia
    //var signedXml = new SignedXml(documentoUTF8);
    var signedXml = new SignedXml(xmlDoc);
    // Define as propriedades da assinatura
    // Adiciona a chave ao documento assinado

    RSACryptoServiceProvider key = new RSACryptoServiceProvider();
    key.FromXmlString(certificate.PrivateKey.ToXmlString(true));

    signedXml.SigningKey = key; //.GetRSAPrivateKey();http://www.w3.org/2000/09/xmldsig#rsa-sha1

    // Adiciona a referência ao documento assinado
    signedXml.AddReference(reference);
    signedXml.KeyInfo = keyInfo;
    signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

    // Gera a assinatura
    signedXml.ComputeSignature();

    // Obtém a representação em XML da assinatura e salva em um objeto XmlElement
    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);

    return xmlDoc.DocumentElement;
}

That one Object is the structure of the Object.

Below is the output xml of how XML is getting:

<Reinf xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.reinf.esocial.gov.br/schemas/envioLoteEventos/v1_03_02">
<loteEventos>
    <evento id="ID1111111110000002017102714215100001">
        <Reinf xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.reinf.esocial.gov.br/schemas/evtInfoContribuinte/v1_03_02">
            <evtInfoContri id="ID1111111110000002017102714215100001">
                <ideEvento>
                    <tpAmb>2</tpAmb>
                    <procEmi>1</procEmi>
                    <verProc>SAP ECC 6.0</verProc>
                </ideEvento>
                <ideContri>
                    <tpInsc>1</tpInsc>
                    <nrInsc>15622088000150</nrInsc>
                </ideContri>
                <infoContri>
                    <inclusao>
                        <idePeriodo>
                            <iniValid>2018-01</iniValid>
                        </idePeriodo>
                        <infoCadastro>
                            <classTrib>99</classTrib>
                            <indEscrituracao>1</indEscrituracao>
                            <indDesoneracao>0</indDesoneracao>
                            <indAcordoIsenMulta>0</indAcordoIsenMulta>
                            <contato>
                                <nmCtt>xxxxxxxxxxx</nmCtt>
                                <cpfCtt>111111111</cpfCtt>
                                <foneFixo>11111111111</foneFixo>
                                <email>[email protected]</email>
                            </contato>
                        </infoCadastro>
                    </inclusao>
                </infoContri>
            </evtInfoContri>
            <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/2001/04/xmldsig-more#rsa-sha256" />
                    <Reference URI="#ID1111111110000002017102714215100001">
                        <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>yBmhSIzReZE0+WLAqgxjoSqq2tZZEThdZIHx5uRiffI=</DigestValue>
                    </Reference>
                </SignedInfo>
                <SignatureValue>gF/YxdCbbPM8dd0qdBdcnALwk0zvMRWSxLqqdda/qbeYFDQ30/1m38oO80EXeZgab1e79SxLYDwOQleWknUKFxa5r+u+3mmCdy2Bgq0YJxdZ16PSEQnVTwDJDguXMyaWY76OoqIQdcqm35m11hmPRJZtkuKatgBce/pksWDZqI/2GdEUrWFPx+FB6Luto9IFt3RRxon6gQN6M3jsmd8c3BMu34TCD53JfgyTm1WqQBNtGj+fLYbC/eyItG2DI+8x3mb4WtKS3KqDUSqzZvOKj9GKTtg92+TsJurJrVsq3CZVGgClvcTCOsmP0ByES1ninFDaMEeFPKOzz8Mirz2Xsw==</SignatureValue>
                <KeyInfo>
                    <X509Data>
                        <X509Certificate>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</X509Certificate>
                    </X509Data>
                </KeyInfo>
            </Signature>
        </Reinf>
    </evento>
</loteEventos>

If anyone can help me, I really appreciate it! Very grateful from now on.

  • this message is the server that is receiving the xml, which returns you? or is it an error that occurs at runtime?

  • that id <evtInfoContri id="ID1111111110000002017102714215100001"> is generated based on some criterion?

  • @Rodrigok. B, this message is the server of the recipe that is returning me yes. And the ID, IN THIS CASE, was generated in the hand, even, respecting only the character limit.

  • I had a similar problem with another Ws recipe service. I resolved to add the id character at the beginning of the id. In other words, the id would look like this "_ID2332887733398878900000098822".

2 answers

1


good afternoon! I managed to solve my problem, I rewrote the signature function, as it looks like Framework 4.0 the form is a little more complex to sign the same, follows below the function, if someone runs into the same problem:

Concerning the parameters:

  • Puri: It is the name of the main XML node that will be signed, in which case it is always the "Reinf"
  • noPrincipal: It is the name of the event node, it is necessary because the signature comes just after that node. Example: in the case of the R1000 event, the event node is the "evtInfoContri"
  • objToTransform: It is the object of the event that will be signed

I am using an extended class for the serialization/de-accomplishment of XML objects

.

    public static XmlElement AssinarXml(string pUri,string noPrincipal, object objToTransform)
    {
        XmlDocument documento = new XmlDocument();
        documento.LoadXml(objToTransform.ToXmlString());

        if (documento.FirstChild is XmlDeclaration)
            documento.RemoveChild(documento.FirstChild);

        if (documento.FirstChild.Attributes["xmlns:xsi"] != null)
            documento.FirstChild.Attributes.Remove(documento.FirstChild.Attributes["xmlns:xsi"]);

        if (documento.FirstChild.Attributes["xmlns:xsd"] != null)
            documento.FirstChild.Attributes.Remove(documento.FirstChild.Attributes["xmlns:xsd"]);

        string subject = String.Empty;

        X509Certificate2 pCertificado = null;
        System.Security.Cryptography.AsymmetricAlgorithm pKey = null;

        if (pCertificado != null)
            subject = pCertificado.Subject.ToString();

        // parametros de retorno
        string XMLAssinado = String.Empty;

        try
        {
            try
            {
                int qtdeRefUri = documento.GetElementsByTagName(pUri).Count;

                if (qtdeRefUri == 0)
                    throw new Exception(string.Format("A tag de assinatura {0} não existe.", pUri.Trim()));
                else
                {
                    try
                    {
                        for (int i = 0; i < qtdeRefUri; i++)
                        {
                            SignedXml docXML = new SignedXml(documento);

                            Reference reference = new Reference();
                            XmlAttributeCollection uri = documento.GetElementsByTagName(pUri).Item(i).Attributes;
                            var nrInscr = documento.GetElementsByTagName("nrInsc")[0].FirstChild.Value;

                            pCertificado = GetCertificado(nrInscr);
                            pKey = pCertificado.PrivateKey;

                            foreach (XmlAttribute atributo in uri)
                            {
                                if (atributo.Name == "id" || atributo.Name == "Id" || atributo.Name == "ID")
                                    reference.Uri = "#" + atributo.InnerText;
                            }

                            // adicionando EnvelopedSignatureTransform a referencia
                            XmlDsigEnvelopedSignatureTransform envelopedSigntature = new XmlDsigEnvelopedSignatureTransform();
                            reference.AddTransform(envelopedSigntature);

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

                            docXML.AddReference(reference);

                            // carrega o certificado em KeyInfoX509Data para adicionar a KeyInfo
                            KeyInfo keyInfo = new KeyInfo();
                            keyInfo.AddClause(new KeyInfoX509Data(pCertificado));
                            docXML.KeyInfo = keyInfo;

                            // SHA256
                            var exportedKeyMaterial = pCertificado.PrivateKey.ToXmlString(/* includePrivateParameters = */ true);
                            var key = new RSACryptoServiceProvider(new CspParameters(24 /* PROV_RSA_AES */));
                            key.PersistKeyInCsp = false;
                            key.FromXmlString(exportedKeyMaterial);

                            docXML.SigningKey = key;
                            // -----------------
                            docXML.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
                            docXML.ComputeSignature();

                            // recuperando a representacao do XML assinado
                            XmlElement xmlDigitalSignature = docXML.GetXml();

                            documento.GetElementsByTagName(noPrincipal).Item(i).AppendChild(documento.ImportNode(xmlDigitalSignature, true));
                            //documento.GetElementsByTagName(noPrincipal).Item(1).AppendChild(documento.ImportNode(xmlDigitalSignature, true));

                            // teste Charset                                
                            Encoding iso = Encoding.GetEncoding("ISO-8859-1");
                            Encoding utf8 = Encoding.UTF8;
                            byte[] utfBytes = utf8.GetBytes(documento.OuterXml);
                            byte[] isoBytes = Encoding.Convert(utf8, iso, utfBytes);
                            XMLAssinado = iso.GetString(isoBytes);

                            //XMLAssinado = documento.OuterXml;
                        }
                    }
                    catch (CryptographicException ex)
                    {
                        throw new Exception(string.Format("Erro ao assinar o documento - {0}", ex.Message));
                    }
                    catch (Exception caught)
                    {
                        throw new Exception(string.Format("Erro ao assinar o documento - {0}", caught.Message));
                    }
                }
            }
            catch (Exception caught)
            {
                throw new Exception(string.Format("XML mal formado - {0}", caught.Message));
            }
        }
        catch (Exception caught)
        {
            throw new Exception(string.Format("Problema ao acessar o certificado digital - {0}", caught.Message));
        }

        XmlDocument any = new XmlDocument();
        any.LoadXml(XMLAssinado);

        return any.DocumentElement;
    }

Below is the extended class of de-realization/serialization

public static class XmlTools
{
    public static string ToXmlString<T>(this T input)
    {
        string _return = string.Empty;
        using (StringWriter stringwriter = new Utf8StringWriter())
        {
            System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(input.GetType());
            x.Serialize(stringwriter, input);
            _return = stringwriter.ToString();
        }

        return _return.ToString();
    }

    public static T ToObject<T>(this string objectToDeserialize)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        XmlReader reader = XmlReader.Create(new StringReader(objectToDeserialize.ToString()));

        return (T)serializer.Deserialize(reader);
    }

    public static I ToObject<T, I>(this T objectToDeserialize, I classePara)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(I));
        XmlReader reader = XmlReader.Create(new StringReader(objectToDeserialize.ToString()));

        return (I)serializer.Deserialize(reader);
    }
}

public class Utf8StringWriter : StringWriter
{
    // Use UTF8 encoding but write no BOM to the wire
    public override Encoding Encoding
    {
        get { return new UTF8Encoding(false); } // in real code I'll cache this encoding.
    }
}

1

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.

See these two answers here:

EFD-Reinf: Invalid signature - Failed to verify XML document signature
/a/277476/86952

XML signing error for EFD-Reinf
/a/283284/86952

  • opa Pedro, blz? I came to see these answers already, but I could not solve my problem. Know if this thing of attributes xmlns:xsi and xmlns:xsd even for version 1.03.02 keeps? I tried to remove tbm, but it didn’t work.

  • I believe it is true that eSocial also does not accept attributes. Some questions: 1) This object reinf that you pass to the function XmlAssinado, starts from the second node Reinf XML, right? 2) Then you add the function return XmlAssinado to batch XML? 3) How are you saving the final XML file? 4) The field id must contain the date the event was generated, and I noticed that its id has this value: "20171027", which would mean that the event was generated on 27/10/2017; for an event generated on 03/05/2018, for example, this excerpt should be "20180503".

  • Pedrão, I managed to rewrite the signature function, but follow the answers to his questions: 1) This, this object is only the block of the event, without the main node. I’m signing the events individually. 2) In fact, after signing the event, I add the signature node inside the same event node, but just below, respecting the xsd. 3) The final XML I recover with a function of serealization of objects, which transforms the objects into XML 4) The id field was sent only respecting the quantity, as it will be sent by another interface.

Browser other questions tagged

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