Base64 string signature

6

In my project, I have a rule that I need to sign the string of an XML that I have that is in base64 with the user's CPF ...

I have been searching, but I have not been able to understand how this signature works with .NET classes.

Well, I found this link here that subscribes to a string of an XML of NF-e. But I could not quite understand how that works, and how to adapt that code to my scenario.

What I have so far: I generate XML , I write to the file and I can generate the hash base64 of this string in>, but what I'm missing now is to sign this string with the person's CPF .

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 you 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's 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 XML that is created follows:

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

Until that time I can generate the base64 hash .

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

    
asked by anonymous 12.06.2015 / 14:30

1 answer

6

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.

This for fiscal documents, but I have not checked the idea should be the same.

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

<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>
    
16.06.2015 / 20:44