String signature in Base64

Asked

Viewed 2,687 times

6

In my project, I have a rule that I need to sign the string of a XML that I have you on Base64 with the user’s CPF...

I’ve been doing some research, but I couldn’t quite understand how this signature works string with own classes .NET.

Well, I found this link here who signs a string of a XML of NF-e. But I couldn’t quite understand how it works, nor how to adapt this code of this size to my scenario.

What I have so far: Gero o XML, I write in the file and I can generate the hash Base64 of that string, but what I need now is to sign this string with the CPF of the person.

The codes I have are:

//Cria o xml com as tags e faz o encoding para base64
var sb = new StringBuilder();
var settings = new XmlWriterSettings();
string cpf = "000.001.000-00";

using (var writer = XmlWriter.Create(sb, settings))
{
    //Inicia o documetno xml
    writer.WriteStartDocument();

    //escreve o documento raiz
    writer.WriteStartElement("no1");

    //escreve os subelementos
    writer.WriteElementString("no2", "valor");

    //encerra o elemento raiz
    writer.WriteEndElement();

    //escreve o xml para o arquivo e encerra o objeto escritor
    writer.Close();
}

//encoding do xml para base64
string s = EncodeTo64(sb.ToString());

//arquivo que vai ser usado para gerar a string base64      
string caminho = parametros.Propriedades["ParPastaArquivoXML"].ToString();
caminho = caminho + "\\" + "arquivo.xml";

File.WriteAllText(caminho, s);

Here try to sign:

try
   {
       // Create a new CspParameters object to specify 
       // a key container.
       CspParameters cspParams = new CspParameters();
       cspParams.KeyContainerName = cpf;

       // Create a new RSA signing key and save it in the container. 
       RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

       // Create a new XML document.
       XmlDocument xmlDoc = new XmlDocument();

       // Load an XML file into the XmlDocument object.
       xmlDoc.PreserveWhitespace = false;
       xmlDoc.Load(caminho);

       // Sign the XML document. 
       SignXml(xmlDoc, rsaKey);

       Console.WriteLine("XML file signed.");

       // Save the document.
       xmlDoc.Save(caminhoAssinado);
   }
   catch (Exception e)
   {
       Console.WriteLine(e.Message);
   }

Here the method to sign:

// Sign an XML file.  
// This document cannot be verified unless the verifying  
// code has the key with which it was signed. 
public static void SignXml(XmlDocument xmlDoc, RSA Key)
{
    // Check arguments. 
    if (xmlDoc == null)
        throw new ArgumentException("xmlDoc");
    if (Key == null)
        throw new ArgumentException("Key");

    // Create a SignedXml object.
    SignedXml signedXml = new SignedXml(xmlDoc);

    // Add the key to the SignedXml document.
    signedXml.SigningKey = Key;

    // Create a reference to be signed.
    Reference reference = new Reference();
    reference.Uri = "";

    // Add an enveloped transformation to the reference.
    XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
    reference.AddTransform(env);

    // Add the reference to the SignedXml object.
    signedXml.AddReference(reference);

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

The example of XML which is created follows below:

<?xml version="1.0" encoding="utf-16"?>
<no1>
  <no2>021303</no2>
</no1>

Until that moment I can generate the hash Base64.

But now, how do I sign this hash with the CPF?

  • When you ask : "how do I sign this hash with the CPF," do you mean how to sign with a digital certificate from an individual? Type e-CPF A3 installed on user machine?

  • That’s right @Guilhermejsantos. With this certificate of Individual. He’s already installed on the machine, but I can’t get him to sign it for the webservice... And when sending the webservice returns me the error that is not reading the CPF in the file.

  • Erik, the example file seems to me correct, from the link you passed. Did you manage to run it? If so, did you get an error? For Nfe you need a specific legal entity certificate, see: http://www.nfe.fazenda.gov.br/portal/questionsFrequentes.aspx?tipConteudo=k/E5bakb80o=

  • As far as I know, for Nfe subscription you need a certificate for CNPJ (e-CNPJ) or Nfe (e-NFE).

  • I used the NF-e link as an example, but I’m not signing an NF-e, but an xml with a specific number for the webservice to reply to me with another xml populated with data so I can handle it on my internal system... I took the link more as example of same code.

1 answer

6


Dude, I’m developing solutions for NF-e, I have the following signature code, I don’t know if for the CPF can be the same pattern if yes, works like this:

var xml = new XmlDocument();   // <---- aqui declaro um novo xml
xml.LoadXml(sbXml.ToString()); // <-- carrego o xml que quero assinar, no meu caso, dependendo do xml a montar, uso um StringBuilder doc pequenos

var i = 0;
var docXML = new SignedXml(xml); // <-- instancia classe de criptografia

docXML.SigningKey = NFe_Rec.ClientCredentials.ClientCertificate.Certificate.PrivateKey; // <--adiciono o certificado digital, instanciado o serviço que vou usar no caso "NFe_Rec", que ira  para autenticar a operação e atribuindo a docXML.SigningKey.

var refer = new Reference(); // <-- Adicionando Reference

refer.Uri = "#ID" + (CASO O PADRÃO DO DOC FISCAL SEJA O MESMO, O CPF VEM AQUI); // <-- Essa é palavra chave
refer.AddTransform(new XmlDsigEnvelopedSignatureTransform());
refer.AddTransform(new XmlDsigC14NTransform());
docXML.AddReference(refer); 

var ki = new KeyInfo();
ki.AddClause(new KeyInfoX509Data(NFe_Rec.ClientCredentials.ClientCertificate.Certificate));
docXML.KeyInfo = ki; // <-- refente a algumas computações e tags especificas do padrão X509 que são adicionados.

docXML.ComputeSignature(); // <-- calcula e assinatura,com base no arquivo xml lá em cima e Uri que informamos;
i++;

xml.ChildNodes[1].ChildNodes[i].AppendChild(xml.ImportNode(docXML.GetXml(), true)); // <-- aqui adiciona dentro do node que quiser a assinatura, nas NF(s), ficam dentro da tag <NFe> depois de todos os outros childs do node.

That’s for tax documents, but I haven’t checked the idea anymore it should be the same.

Your doc would look like this, following the signature template I showed:

<CPF>
<infCPF Id="CPF00000000000">
//aqui ficaria as tags com informações que você gostaria de transmitir.
</infCPF> // Logo depois assinatura, essa assinatura
<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/2000/09/xmldsig#rsa-sha1" /><Reference URI="#CPF00000000000"><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/2000/09/xmldsig#sha1" /><DigestValue>cwWi6+IRhijWDsJxA1SgL0P9Dsk=</DigestValue></Reference></SignedInfo>q78y4IqMDFi070dX+foGJIABgd3/s7Du9glN2sZQh9JJfSFdwH1Evh1PtigN9dc7aSxNdha6/n8/7kWQFjv8=</X509Certificate></X509Data></KeyInfo></Signature></CPF>
  • Man, I don’t get this part here: refer.Uri = "#ID" + (CASO O PADRÃO DO DOC FISCAL SEJA O MESMO, O CPF VEM AQUI); <-- Essa é palavra chave. Could you explain to me ?

  • yes of course, the Uri serves with the key to encrypt the entire document, if it were a invoice would be the 44-character key, as your intention is to sign the document using the CPF will be the Cpf number.

  • Aaaaah ta! Our now became very clear... Thank you very much! Just another question... I would have to have a tag in XML for the CPF number ?

  • would have to have as attribute in a tag, I will trigger, an example of how your xml document would look.

  • Ohhh man, that would be great!

  • In the xml example we have, the root tag, CPF, dai we have the tag, infCPF that would go the other sets of nodes and Childs that would inform, in this same tag, has the id, which is the keyword(remembering that the certificate is required to sign a document), then Signature, the file signature.

  • 1

    If you use the same pattern used in a nfe, using A1 or A3 certificate to sign the doc, in your case it would work well.

  • I’m testing here to see if it works... @bp002

  • all right, showing more doubt just ask.

  • here: NFe_Rec, what would ? A certificate installed on the pc ?

  • No, it is a service that I need to instantiate the IRS, and to use it is required certificate.

  • Aaaah ta. I get it!

Show 7 more comments

Browser other questions tagged

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