C # EFD-REINF 1.03.02 - Event signature invalid. Digital signature of XML document is invalid

1

All good?

I'm trying to make the EFD-REINF digital signature shell (the most recent version 1.03.02 ) of the event XML in this case I'm testing with the R1000) with .Net C # , but framework 4.0 .

I do not really know if I'm doing something wrong, but I've tried several things to try signing the event xml and I can not, I'm always getting the MS0017 - Invalid event signature. Digital signature of XML document is invalid .

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;
}

This object is the structure of the event in 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 someone can help me, I thank them immensely! Very grateful already.

    
asked by anonymous 30.04.2018 / 18:02

2 answers

1

Good afternoon! I was able to solve my problem, I rewritten the signature function, it seems that with Framework 4.0 the form is a bit more complex to sign the same, here is the below function if someone comes up with the same problem:

Regarding the parameters:

  • pUri : This is the name of the parent node of the XML that will be signed, in this case it is always " Reinf
  • noPrincipal : It is the name of the event node, it is necessary because the signature comes soon after that node. Example: In case of event R1000, the event node is " evtInfoContri "
  • objToTransform : Is the event object to be signed

I'm using an extended class for serializing / deserializing objects in XML

.

    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 deserialization / serialization class

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.
    }
}
    
04.05.2018 / 16:44
1

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.

See these two answers here:

  

EFD-Reinf: Invalid signature - Failed to verify XML document signature
link

p>      

XML signature error for EFD-Reinf
link

    
30.04.2018 / 18:26