Inquiridor
Assinatura RPS

Pergunta
-
Pessoal, estou tentando fazer a assinatura digital da RPS,para enviar para prefeitura de São Paulo,Estou usando o seguinte codigo em C#.
private static XmlDocument Gera_Assinatura_RPS(XmlDocument Xml, string uri, X509Certificate2 X509Cert)
{
try
{
XmlDocument docXML = new XmlDocument();
docXML.PreserveWhitespace = true;
// Carrega o documento XML
docXML = Xml;
// Cria o objeto XML assinado
SignedXml signedXml = new SignedXml(docXML);
// Assina com a chave privada
signedXml.SigningKey = X509Cert.PrivateKey;
// Atribui o método de canonização
signedXml.SignedInfo.CanonicalizationMethod = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
// Atribui o método para assinatura
signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
// Cria a referencia
Reference reference = new Reference();
// Pega a URI para ser assinada
XmlAttributeCollection _Uri = docXML.GetElementsByTagName(uri).Item(0).Attributes;
foreach (XmlAttribute _atributo in _Uri)
{
if (_atributo.Name == "xmlns")
reference.Uri = "#" + _atributo.InnerText;
}
// Adiciona o envelope à referência
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
// Atribui o método do Hash
reference.DigestMethod = "http://www.w3.org/2000/09/xmldsig#sha1";
// Adiciona a referencia ao XML assinado
signedXml.AddReference(reference);
// Cria o objeto keyInfo
KeyInfo keyInfo = new KeyInfo();
// Carrega a informação da KeyInfo
KeyInfoClause rsaKeyVal = new RSAKeyValue((System.Security.Cryptography.RSA)X509Cert.PrivateKey);
KeyInfoX509Data x509Data = new KeyInfoX509Data(X509Cert);
x509Data.AddSubjectName(X509Cert.SubjectName.Name.ToString());
keyInfo.AddClause(x509Data);
keyInfo.AddClause(rsaKeyVal);
// Adiciona a KeyInfo
signedXml.KeyInfo = keyInfo;
// Atribui uma ID à assinatura
///signedXml.Signature.Id = "Assigned" + uri;
signedXml.Signature.Id = signedXml.Signature.Id + uri;
// Efetiva a assinatura
signedXml.ComputeSignature();
// Obtem o XML assinado
XmlElement xmlDigitalSignature = signedXml.GetXml();
// Adiciona o elemento assinado ao XML
docXML.DocumentElement.AppendChild(docXML.ImportNode(xmlDigitalSignature, true));
// Retorna o XML
return docXML;
}
catch (Exception erro) { throw erro; }
}so que quando vou efetuar a assinatura no comando signedXml.ComputeSignature(); ele me traz o erro Elemento de referência mal formado., sera que alguem sabe o que esta acontecendo.
Obrigado.
Todas as Respostas
-
Veja esta dica da microsoft: http://msdn.microsoft.com/en-us/library/x8xwex4b.aspx
Just Be Humble Malange! -
-
Malange nesse exemplo pelo que entendi ele esta assinando o arquivo inteiro, no meu caso preciso assinar uma RPS separadamente e depois adicionar essa RPS a um lote e assinar o lote tambem?
E ai alguem poderia me ajudar com a assinatura da rps de são paulo, ja consigo assinar o lote mas não estou conseguindo assinar individualmente cada rps.Obrigado
-
Estou com o mesmo problema do rafael achei esse código em c# (http://nf-eletronica.com/blog/?p=47) que assina todo o xml
mais preciso que ele assine tbm após cada tag infrps.
-
Estou com o mesmo problema do rafael achei esse código em c# (http://nf-eletronica.com/blog/?p=47) que assina todo o xml
mais preciso que ele assine tbm após cada tag infrps.
Ricardo da uma olhada nesse link, e ve se te ajuda.
-
Rafael, no meu caso eh BH, mais mesmo assim não tinha nada mostrando como assiner a RPS.
vc conseguiu assinar as RPS? Anota meus contatos ai ricardodavidss@gtalk.com, fox_3_d@hotmail.com
-
Rafael, no meu caso eh BH, mais mesmo assim não tinha nada mostrando como assiner a RPS.
vc conseguiu assinar as RPS? Anota meus contatos ai ricardodavidss@gtalk.com, fox_3_d@hotmail.com
-
Rafael, no meu caso eh BH, mais mesmo assim não tinha nada mostrando como assiner a RPS.
vc conseguiu assinar as RPS? Anota meus contatos ai ricardodavidss@gtalk.com, fox_3_d@hotmail.com
Alguém conseguiu resolver isso? -
Rafael, no meu caso eh BH, mais mesmo assim não tinha nada mostrando como assiner a RPS.
vc conseguiu assinar as RPS? Anota meus contatos ai ricardodavidss@gtalk.com, fox_3_d@hotmail.com
Alguém conseguiu resolver isso?Boa tarde, vocês conseguiram resolver este problema?
Estou com a mesma dúvida, principalmente em relação a São Paulo, pois não sei se funciona da forma que o Rafael falou,
de assinar cada rps e em seguida assinar o lote?
Ajuda aí pessoal!
-
-
Rodrigo bom dia, estou com o mesmo problema em São Paulo... você conseguiu resolver ?
Infelizmente não meu amigo, mas na verdade estou conseguindo assinar, porém da forma incorreta, pelo menos é o retorno que estou tendo do webservice:
<Codigo>1206</Codigo>
<Descricao>Assinatura Digital do RPS incorreta.</Descricao>Mandei um e-mail para prefeitura de SP, com o arquivo em anexo para ver se eles me auxiliam, qualquer novidade posto por aqui, peço a todos que façam o mesmo para nos ajudarmos.
Abraço!
- Sugerido como Resposta Rodrigo Valença segunda-feira, 1 de agosto de 2011 20:35
-
-
Rodrigo bom dia, estou com o mesmo problema em São Paulo... você conseguiu resolver ?
Consegui resolver...
No meu caso o problema era na assinatura adicional que corresponde aquela assinatura da cadeia de caracteres que devemos montar. Eu estava montando essa string com o valor de serviços e deduções sem utilizar os zeros dos centavos, por exemplo:
250,00 (Valor dos serviços)
000000000000250 (Valor que eu estava montando, errado!)
000000000025000 (Valor correto a ser montado)
Portanto AdemirLuiz, verifica se você está montando direitinho essa string que devemos assinar para cada RPS.
Obrigado a Rafa Alves e aos demais colegas!
-
Ola Rafa e demais colegas...
Meu problema agora é outro, estou tentando utilizar o método de consulta de lote RPS, e não estou entendendo muito quanto a mensagem xml. Lembrando que isso é referente a São Paulo, estou com dúvidas na parte "Signature", elemento exigido na estrutura da msg a ser enviada pela consulta. Gostaria de saber se neste elemento "Signature", vou apenas copiar o conteúdo existente no mesmo elemento("Signature") encontrado no lote já enviado, ou se devo montar essa estrutura, ex: Cabecalho, NumerodoLote ,etc, em um arquivo xml e gerar uma nova assinatura específica deste xml.
Obrigado, aguardo uma resposta.
-
Rodrigo eu estou com o mesmo problema. Já conferi item por item da cadeia de caracteres e está tudo rigorosamente dentro do padrão do manual. Mas ainda assim eu continuo recebendo o mesmo erro. Estou assinando da seguinte forma:
AssinarRPS(X509Certificate2 cert, String sAssinatura) { ASCIIEncoding enc = new ASCIIEncoding(); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); rsa = cert.PrivateKey as RSACryptoServiceProvider; byte[] sAssinaturaByte = enc.GetBytes(sAssinatura); byte[] hash = sha1.ComputeHash(sAssinaturaByte); sAssinaturaByte = rsa.SignHash(hash, "SHA1"); string convertido = Convert.ToBase64String(sAssinaturaByte); return convertido; }
Alguma dica? -
Rodrigo eu estou com o mesmo problema. Já conferi item por item da cadeia de caracteres e está tudo rigorosamente dentro do padrão do manual. Mas ainda assim eu continuo recebendo o mesmo erro. Estou assinando da seguinte forma:
AssinarRPS(X509Certificate2 cert, String sAssinatura) { ASCIIEncoding enc = new ASCIIEncoding(); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); rsa = cert.PrivateKey as RSACryptoServiceProvider; byte[] sAssinaturaByte = enc.GetBytes(sAssinatura); byte[] hash = sha1.ComputeHash(sAssinaturaByte); sAssinaturaByte = rsa.SignHash(hash, "SHA1"); string convertido = Convert.ToBase64String(sAssinaturaByte); return convertido; }
Alguma dica?Abaixo segue meu código em C#, aparentemente o teu tá correto, mas mesmo assim analisa direitinho. Outra dica: vai debugando o projeto e no final quando a string estiver montada, você confere mesmo se está correta, após isso você deixa o método assiná-la para ver se dar certo. Analisa bem, pois no começo eu estava achando que eu estava fazendo correto, mas por uma bobagem já não é validado. Boa sorte!public static string AssinaturaAdicional(string texto){X509Certificate2 cert = new X509Certificate2();Certificado certificado = new Certificado();cert = certificado.BuscaNroSerie(util.ParametroConfig("NoSerieCertificado", "xxx"), false, false);try{System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();RSA = (RSACryptoServiceProvider)cert.PrivateKey;byte[] sAssinaturaByte = enc.GetBytes(texto);RSAPKCS1SignatureFormatter rsaf = new RSAPKCS1SignatureFormatter(RSA);SHA1CryptoServiceProvider SHA1 = new SHA1CryptoServiceProvider();byte[] hash = null;hash = SHA1.ComputeHash(sAssinaturaByte);rsaf.SetHashAlgorithm("SHA1");sAssinaturaByte = rsaf.CreateSignature(hash);string convertido = null;convertido = Convert.ToBase64String(sAssinaturaByte);return convertido;} -
Prezados Amigos,
Depois de muito procurar por todos os fóruns e nunca encontrar a solução para resolver o problema da assinatura adicional do RPS que sempre retornava o erro 1206 <Descricao>Assinatura Digital do RPS incorreta.</Descricao>, com a ajuda do Rodrigo e do meu amigo George consegui a validação do PedidoEnvioLoteRPS.
Tudo não passa de uma grande falta de atenção:
O problema na maioria das vezes não está no Hash que geramos com sha1 e nem na assinatura com RSA-SHA1. A maioria dos códigos que encontramos por aí pelos fóruns explicando como fazer esta assinatura estão corretos. O grande problema na maioria dos casos, acredito eu, está na concatenação dos campos para formar a string de 86 posições.
Se está recebendo o erro 1206 e está utilizando o método abaixo para a assinatura adicional e seu RPS é da cidade de são paulo, então meu amigo é muito provável que seu erro esteja na concatenação da string, mais precisamente nos campos ValorServicos e ValorDeducoes.
O que ocorre é que na maioria das vezes quando as pessoas descobrem o erro, se calam, mas todos procuram ajuda. NÃO VOU ME CALAR!!! RS
Seguindo a boa vontade do Rodrigo Valença que descobriu e postou a solução reforçarei o comentário dele concordando com o que disse que mesmo após eu ler achei que não houvesse erros na minha string.
Veja abaixo:
R$ 20.500,00 (Valor dos serviços)
R$ 5.000,00 (Valor das Deduções)
De acordo com o exemplo do manual, o valor de R$ 20.500,00 fica assim no xml <ValorServicos>20500</ValorServicos>
Repare que no xml foi ocultado as casas decimais.
Naturalmente acabamos montando desta forma o nosso xml e na hora de montar a string apenas pegamos este valor e acrescentamos os zeros à esquerda ficando assim: 000000000020500 (ESTÁ ERRADOOO!!!)
Precisamos exibir as duas casas decimais, mesmo sendo Zero.
Forma correta do ValorServicos na string é 000000002050000
Tendo esta atenção para estes dois campos possivelmente você conseguirá ver o tão esperado true nas tags <Sucesso>true</Sucesso> do retorno.
O método para assinar segue abaixo:
AssinarRPS(X509Certificate2 cert, String sAssinatura) { ASCIIEncoding enc = new ASCIIEncoding(); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); rsa = cert.PrivateKey as RSACryptoServiceProvider; byte[] sAssinaturaByte = enc.GetBytes(sAssinatura); byte[] hash = sha1.ComputeHash(sAssinaturaByte); sAssinaturaByte = rsa.SignHash(hash, "SHA1"); string convertido = Convert.ToBase64String(sAssinaturaByte); return convertido; }
Um grande abraço para todos e muitíssimo obrigado pela ajuda Rodrigo!!!
- Sugerido como Resposta HugoFernandes_ quinta-feira, 13 de setembro de 2012 15:49
-
-
Ola Rafa e demais colegas...
Meu problema agora é outro, estou tentando utilizar o método de consulta de lote RPS, e não estou entendendo muito quanto a mensagem xml. Lembrando que isso é referente a São Paulo, estou com dúvidas na parte "Signature", elemento exigido na estrutura da msg a ser enviada pela consulta. Gostaria de saber se neste elemento "Signature", vou apenas copiar o conteúdo existente no mesmo elemento("Signature") encontrado no lote já enviado, ou se devo montar essa estrutura, ex: Cabecalho, NumerodoLote ,etc, em um arquivo xml e gerar uma nova assinatura específica deste xml.
Obrigado, aguardo uma resposta.
Pessoal, quanto a esta minha dúvida, falando com o suporte de SP, me explicaram que cada uma das mensagens a serem enviadas, precisam de assinaturas. Portanto, cada mensagem obrigatoriamente precisa de sua própria assinatura.
Desculpem pela dúvida boba, mas na dúvida melhor perguntar. :P
Abraço!
-
-
public class Assinador { public string Ass(string xmlMensagem, string uri) { // // le o arquivo xml // string _uri; string _stringXml; _stringXml = xmlMensagem; _uri = uri; // // realiza assinatura // AssinaturaDigital AD = new AssinaturaDigital(); // // cria cert // X509Certificate2 cert = new X509Certificate2(); // // seleciona certificado do repositório MY do windows // Certificado certificado = new Certificado(); cert = certificado.BuscaNomeCert2("CN=NFe - Associacao NF-e:99999090910270, C=BR, L=PORTO ALEGRE, O=Teste Projeto NFe RS, OU=Teste Projeto NFe RS, S=RS"); //int resultado = AD.Assinar(_stringXml, _uri, cert); string result = string.Empty; try { XmlDocument xmlDoc = AD.AplicaAssinatura(_stringXml, _uri, cert); result = xmlDoc.OuterXml; } catch (Exception ex) { throw new Exception(ex.Message); } return result; } } public class AssinaturaDigital { public XmlDocument AplicaAssinatura(string xml, string uri, X509Certificate2 cert) { try { // Obtem o certificado X509Certificate2 X509Cert = cert; // Cria um documento XML para carregar o XML XmlDocument docXML = new XmlDocument(); docXML.PreserveWhitespace = true; // Carrega o documento XML docXML.LoadXml(xml); // Cria o objeto XML assinado SignedXml signedXml = new SignedXml(docXML); // Assina com a chave privada signedXml.SigningKey = X509Cert.PrivateKey; // Atribui o método de canonização signedXml.SignedInfo.CanonicalizationMethod = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"; // Atribui o método para assinatura signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; // Cria a referencia Reference reference = new Reference(""); // Pega a URI para ser assinada XmlAttributeCollection _Uri = docXML.GetElementsByTagName(uri).Item(0).Attributes; foreach (XmlAttribute _atributo in _Uri) { if (_atributo.Name == "Id") reference.Uri = "#" + _atributo.InnerText; } // Adiciona o envelope à referência XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform(); reference.AddTransform(env); // Atribui o método do Hash reference.DigestMethod = "http://www.w3.org/2000/09/xmldsig#sha1"; // Adiciona a referencia ao XML assinado signedXml.AddReference(reference); // Cria o objeto keyInfo KeyInfo keyInfo = new KeyInfo(); // Carrega a informação da KeyInfo KeyInfoClause rsaKeyVal = new RSAKeyValue((RSA)X509Cert.PrivateKey); KeyInfoX509Data x509Data = new KeyInfoX509Data(X509Cert); x509Data.AddSubjectName(X509Cert.SubjectName.Name.ToString()); keyInfo.AddClause(x509Data); keyInfo.AddClause(rsaKeyVal); // Adiciona a KeyInfo signedXml.KeyInfo = keyInfo; // Atribui uma ID à assinatura signedXml.Signature.Id = "#" + uri; // Efetiva a assinatura signedXml.ComputeSignature(); bool signed = signedXml.CheckSignature(cert, true); // Obtem o XML assinado XmlElement xmlDigitalSignature = signedXml.GetXml(); // Adiciona o elemento assinado ao XML docXML.DocumentElement.AppendChild(docXML.ImportNode(xmlDigitalSignature, true)); // Retorna o XML return docXML; } catch (Exception erro) { throw erro; } } } public class Certificado { public X509Certificate2 BuscaNomeCert2(string nome) { X509Store store = new X509Store(StoreLocation.CurrentUser); store.Open(OpenFlags.ReadWrite); X509Certificate2Collection certCollection = store.Certificates; X509Certificate2 cert = null; // Loop through each certificate and find the certificate // with the appropriate name. foreach (X509Certificate2 c in certCollection) { if (c.Subject == nome) { cert = c; break; } } store.Close(); return cert; }
Deu certo pra mim assim... Normalmente no trecho onde tem Reference reference = new Reference(""), as pessoas esquecem de colocar as aspas pra dizer que não é uma transformação envelopada... Se funcionar, por favor, marcar como resposta... ;)
Igo Soares Ventura (17)
igo1-2@hotmail.com
igo.scitus@hotmail.com
SCITUS Informática - Excelência na Qualidade
- Editado Igo Soares Ventura quarta-feira, 10 de setembro de 2014 19:57