Assine o HASH utilizando RSA-SHA1

galera, estou fazendo o envio de nota fiscal pra Recife, depois de muita luta, e muita pesquisa, conseguí assinar o XML,
mas com aprendi tentando solucionar isso, percebí que estava fazendo a assinatura do RPS de forma errada.
me deparei com os dois passos da documentação:

“3º - Gere o HASH (array de bytes) utilizando SHA1.
4º - Assine o HASH (array de bytes) utilizando RSA-SHA1.
ATENÇÃO! Na maioria das linguagens de programação, os passos 3 e 4 são feitos através de uma
única função. Verifique a documentação de sua linguagem para evitar assinar um hash de um hash.”

esse HASH são dados do própido RPS, isso já está funcionando, eu já procurei muito, e ninguem sabe me dizer como eu faço esses 2 passos que na documentação parece ser a coisa mais simples do mundo…

pesquisei em alguns cantos e cheguei a isso

		try {

			Signature dsa = Signature.getInstance("SHA1withRSA");
			/* Initializing the object with a private key */
			dsa.initSign(privateKey);

			/* Update and sign the data */
			dsa.update(hashSHA);
			byte[] sig = dsa.sign();
			sig = Base64.encodeBase64(sig);
			result = new String(sig);
		} catch (Exception e) {
			e.printStackTrace();
		}

mas isso me retorna algo parecido com isso : A46erP1KpX0j60GjJLq++xb/VqK3A2qNBMyMohB5mjVF/VPM+512Ta00cfSgr9iy9jUWN6AzW0Q3pFWdxpeDqGN+GqT4V0WYf/e6d1jK+Uf+KHY08GIB4XA8CcJOWTNwSG5bqdTRKgBnoz2Q/kI/dS2Bte9yWFS7TaJwL6yslgI=

que eu acho que venha a ser o SignatureValue, mas na verdade eu não precisaria da assinatura completa ?
algo mais ou menos assim?

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
	<SignedInfo>
		<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
		<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
		<Reference URI="">
			<Transforms>
				<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
			</Transforms>
			<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
			<DigestValue>IOeFFhL/u2ReYKoPigqprk7dTL4=</DigestValue>
		</Reference>
	</SignedInfo>	
	<SignatureValue>JF1LdpxewsPQ7T0mMpmE6iwTHPD5qSvSfPIzAQi26aGh7AfI/KAklyqdKfc/gdxR5xk9kgrJNBusHrCa9eImO86PWOogUm3/1D0nb+smcN1HMhUKQzxft0b/ketR1Zp8VZSgv2Aifzj60ZURN/hKSB3vB0uupbHuNQp3yRQ7UoY=</SignatureValue>
	<KeyInfo>
		<X509Data>
			<X509SubjectName>// DADOS DO CERTIFICADO</X509SubjectName>
			<X509Certificate>// DADOS DO CERTIFICADO</X509Certificate>
		</X509Data>
	</KeyInfo>
</Signature>

Sandro,

Eu uso a JSR 105 (XML Digital Signature APIs) para fazer isso.

  private synchronized Document gerarAssinatura(Document xml, String referencia) throws AssinaturaException {
        try {
            String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");

            XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM", (Provider) Class.forName(providerName).newInstance());

            logger.fine("Referência = " + referencia);

            ArrayList transformList = new ArrayList();

            Transform tr1 = fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null);
            Transform tr2 = fac.newTransform(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null);
            transformList.add(tr1);
            transformList.add(tr2);

            Reference ref = fac.newReference(new String("#" + referenciaNFE),
                    fac.newDigestMethod(DigestMethod.SHA1, null),
                    transformList,
                    null, null);

            // Informações da Assinatura
            SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
                    (C14NMethodParameterSpec) null), fac.newSignatureMethod(
                    SignatureMethod.RSA_SHA1, null), Collections.singletonList(ref));

            KeyInfoFactory kif = fac.getKeyInfoFactory();
            X509Data x509 = kif.newX509Data(Collections.singletonList(certificadoX509));
            KeyInfo ki = kif.newKeyInfo(Collections.singletonList(x509));

            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);



            DOMSignContext dsc = new DOMSignContext(chavePrivada, xml.getDocumentElement());

            // Assina o documento
            logger.fine("Assinando...");
            XMLSignature signature = fac.newXMLSignature(si, ki);
            signature.sign(dsc);

            // Resultado
            StringWriter fos = new StringWriter();
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer trans = tf.newTransformer();
            if (isOmitirDeclaracao()) {
                trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            } else {
                trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "false");
            }
            trans.setOutputProperty(OutputKeys.STANDALONE, "yes");
            trans.transform(new DOMSource(xml), new StreamResult(fos));
            logger.fine("Documento assinado = " + fos.toString());


            return xml;
        } catch (Exception e) {
            throw new AssinaturaException(e.getMessage());
        }
    }

Boa cara, muito obrigado, vou fazer os teste aqui pra assinar os RPS dentro do meu xml do envio de lote, mas eu só não entendi uma coisa nesse código, oque é esse parametro “referencia” ? e tem outra váriavel chamada referenciaNFE que não está declarada no código… voce pode me passar oque é ela ?

Sandro,

Na verdade o campo referenciaNFE é a referencia passado como parâmetro para o método.

Que é composto pela literal NFe + chaveDeAcesso

Eu tinha renomeado para facilitar o entendimento mas esqueci de renomear no método.

Abraço

cristiano , eu não entendi muito bem cara, veja se está certo oque eu fiz, eu gerei o XML assinado, com os RPS, e salvei o Hash no SignatureValue e agora eu vou mandar ele assinar o signature value, dessa maneira ??


	Document doc = dbf.newDocumentBuilder().parse(
					new FileInputStream(fileName));
			gerarAssinaturaRPS(doc, "#" + "SignatureValue");

oque eu não entendo é aonde estou dizendo no código que ele tem que assinar o HASH de Rps X…

mais uma vez agradeço cara, estou a mais de uma semana apanhando pra esse negócio… ;/

Então você não precisa se preocupar com o hash e em assinar o xml… Você só precisa passar a referencia. Que foi a String que você usou para gerar seu Hash.

Essa parte do código faz todo processo de assinatura. Aplica a função de Hash em cima da referencia e faz a assinatura.

      XMLSignature signature = fac.newXMLSignature(si, ki);
      signature.sign(dsc);

então cristiano, é que cada RPS é assinado, além do própio arquivo…

eu devo salvar a string dentro da tag do RPS , e dps mandar ele assinar pela referencia?
eu (ainda) não entendi como o método vai saber assinar dentro da tag do RPS X só pela String que eu gerei

O que seria RPS?

RPS é como se estivece enviando um lote de nota fiscal, e o RPS seria cada nota.

no exemplo que a prefeitura disponibiliza é assim ,

<EnviarLoteRpsEnvio xmlns="http://www.abrasf.org.br/ABRASF/arquivos/nfse.xsd">
  <LoteRps Id="L1">
    <NumeroLote>1</NumeroLote>
    <Cnpj>04642554000143</Cnpj>
    <InscricaoMunicipal>1570790</InscricaoMunicipal>
    <QuantidadeRps>2</QuantidadeRps>
    <ListaRps>
      <Rps>
        <InfRps Id="R1">
          <IdentificacaoRps>
            <Numero>1</Numero>
            <Serie>ABC</Serie>
            <Tipo>1</Tipo>
          </IdentificacaoRps>
          <DataEmissao>2009-11-16T21:00:00</DataEmissao>
          <NaturezaOperacao>1</NaturezaOperacao>
          <RegimeEspecialTributacao>6</RegimeEspecialTributacao>
          <OptanteSimplesNacional>2</OptanteSimplesNacional>
          <IncentivadorCultural>2</IncentivadorCultural>
          <Status>1</Status>
          <Servico>
            <Valores>
              <ValorServicos>1000.00</ValorServicos>
              <ValorDeducoes>0</ValorDeducoes>
              <ValorPis>10.00</ValorPis>
              <ValorCofins>10.00</ValorCofins>
              <ValorInss>10.00</ValorInss>
              <ValorIr>10.00</ValorIr>
              <ValorCsll>10.00</ValorCsll>
              <IssRetido>2</IssRetido>
              <ValorIss>10.00</ValorIss>
              <OutrasRetencoes>10.00</OutrasRetencoes>
              <Aliquota>0.05</Aliquota>
              <DescontoIncondicionado>10.00</DescontoIncondicionado>
              <DescontoCondicionado>10.00</DescontoCondicionado>
            </Valores>
            <ItemListaServico>1</ItemListaServico>
            <CodigoCnae>4520001</CodigoCnae>
            <CodigoTributacaoMunicipio>522310000
						</CodigoTributacaoMunicipio>
            <Discriminacao>Teste</Discriminacao>
            <CodigoMunicipio>3106200</CodigoMunicipio>
          </Servico>
          <Prestador>
            <Cnpj>04642554000143</Cnpj>
            <InscricaoMunicipal>1570790</InscricaoMunicipal>
          </Prestador>
          <Tomador>
            <IdentificacaoTomador>
              <CpfCnpj>
                <Cnpj>99999999000191</Cnpj>
              </CpfCnpj>
            </IdentificacaoTomador>
            <RazaoSocial>INSCRICAO DE TESTE SIATU - D'AGUA -PAULINO'S
						</RazaoSocial>
            <Endereco>
              <Endereco>DA BAHIA</Endereco>
              <Numero>200</Numero>
              <Complemento>ANDAR 14</Complemento>
              <Bairro>CENTRO</Bairro>
              <CodigoMunicipio>3106200</CodigoMunicipio>
              <Uf>MG</Uf>
              <Cep>30160010</Cep>
            </Endereco>
          </Tomador>
          <IntermediarioServico>
            <RazaoSocial>INSCRICAO DE TESTE SIATU - D'AGUA -PAULINO'S
						</RazaoSocial>
            <CpfCnpj>
              <Cnpj>05499994000156</Cnpj>
            </CpfCnpj>
            <InscricaoMunicipal>8041700010</InscricaoMunicipal>
          </IntermediarioServico>
          <ConstrucaoCivil>
            <CodigoObra>1234</CodigoObra>
            <Art>1234</Art>
          </ConstrucaoCivil>
        </InfRps>
        <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="#R1">
              <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>pyuIXFAqQ0hwr+3cH2taKy0CGjk=</DigestValue>
            </Reference>
          </SignedInfo>
          <SignatureValue>iHkS2259HxU7nFnJr1qnRA1YFuDPFH94k/TbqcXxOCISFL5vTeBY5AaV0fuUwY78/O1rczSv0pc+dNUTV2LexsSmplyyvlyDboXhPpR29Cvd2UWasAUAl4um1BLzKH322ustSNpKePbmhsMpkAIhZC3MVaCpUt4netvToveHrVA=</SignatureValue>
          <KeyInfo>
            <X509Data>         <X509Certificate>MIIGvzCCBaegAwIBAgIQH/nrIzJAHhhy3nmQ3HfPTANBgkqhkiG9w0BAQUFADB4MQswCQYDVQQGEwJCUjETMBEGA</X509Certificate>
            </X509Data>
          </KeyInfo>
        </Signature>
      </Rps>
      <Rps>
        <InfRps Id="R2">
          <IdentificacaoRps>
            <Numero>2</Numero>
            <Serie>ABC</Serie>
            <Tipo>1</Tipo>
          </IdentificacaoRps>
          <DataEmissao>2009-11-16T21:00:00</DataEmissao>
          <NaturezaOperacao>1</NaturezaOperacao>
          <RegimeEspecialTributacao>6</RegimeEspecialTributacao>
          <OptanteSimplesNacional>2</OptanteSimplesNacional>
          <IncentivadorCultural>2</IncentivadorCultural>
          <Status>1</Status>
          <Servico>
            <Valores>
              <ValorServicos>1000.00</ValorServicos>
              <ValorDeducoes>0</ValorDeducoes>
              <ValorPis>10.00</ValorPis>
              <ValorCofins>10.00</ValorCofins>
              <ValorInss>10.00</ValorInss>
              <ValorIr>10.00</ValorIr>
              <ValorCsll>10.00</ValorCsll>
              <IssRetido>2</IssRetido>
              <ValorIss>10.00</ValorIss>
              <OutrasRetencoes>10.00</OutrasRetencoes>
              <Aliquota>0.05</Aliquota>
              <DescontoIncondicionado>10.00</DescontoIncondicionado>
              <DescontoCondicionado>10.00</DescontoCondicionado>
            </Valores>
            <ItemListaServico>1</ItemListaServico>
            <CodigoCnae>4520001</CodigoCnae>
            <CodigoTributacaoMunicipio>522310000
						</CodigoTributacaoMunicipio>
            <Discriminacao>Teste.</Discriminacao>
            <CodigoMunicipio>3106200</CodigoMunicipio>
          </Servico>
          <Prestador>
            <Cnpj>04642554000143</Cnpj>
            <InscricaoMunicipal>1570790</InscricaoMunicipal>
          </Prestador>
          <Tomador>
            <IdentificacaoTomador>
              <CpfCnpj>
                <Cnpj>99999999000191</Cnpj>
              </CpfCnpj>
            </IdentificacaoTomador>
            <RazaoSocial>INSCRICAO DE TESTE SIATU - D'AGUA -PAULINO'S
						</RazaoSocial>
            <Endereco>
              <Endereco>DA BAHIA</Endereco>
              <Numero>200</Numero>
              <Complemento>ANDAR 14</Complemento>
              <Bairro>CENTRO</Bairro>
              <CodigoMunicipio>3106200</CodigoMunicipio>
              <Uf>MG</Uf>
              <Cep>30160010</Cep>
            </Endereco>
          </Tomador>
          <IntermediarioServico>
            <RazaoSocial>INSCRICAO DE TESTE SIATU - D'AGUA -PAULINO'S
						</RazaoSocial>
            <CpfCnpj>
              <Cnpj>05499994000156</Cnpj>
            </CpfCnpj>
            <InscricaoMunicipal>8041700010</InscricaoMunicipal>
          </IntermediarioServico>
          <ConstrucaoCivil>
            <CodigoObra>1234</CodigoObra>
            <Art>1234</Art>
          </ConstrucaoCivil>
        </InfRps>
        <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="#R2">
              <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>SNNbP4MTcqVZZIwb30KWhA+rVy8=</DigestValue>
            </Reference>
          </SignedInfo>
          <SignatureValue>CZL9pJrdVBiO46FIAw97puzdyfeLDMj3p/BMKvbXgDD/Vn7fnG2Bfqlf5jbujFbhElkB6f/3ODre8s05bI/tFl/AiYT27Z/KE6mUgP54YBkv+UQmlD799PnX5zqU0uvxEr8j5YiUT5Lh6OszTIlNRfTG6Fedur4ll7BTgse4BZ0=</SignatureValue>
          <KeyInfo>
            <X509Data>
              <X509Certificate>MIIGvzCCBaegAwIBAgIQH/nrIzJAHhhy3nmQ3HfPTANBgkqhkiG9w0BAQUFADB4MQsw</X509Certificate>
            </X509Data>
          </KeyInfo>
        </Signature>
      </Rps>
    </ListaRps>
  </LoteRps>
  <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="#L1">
        <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>+jSJxAuTpHtKZA8vcO7zMqD5V9o=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>A46erP1KpX0j60GjJLq++xb/VqK3A2qNBMyMohB5mjVF/VPM+512Ta00cfSgr9iy9jUWN6AzW0Q3pFWdxpeDqGN+GqT4V0WYf/e6d1jK+Uf+KHY08GIB4XA8CcJOWTNwSG5bqdTRKgBnoz2Q/kI/dS2Bte9yWFS7TaJwL6yslgI=</SignatureValue>
    <KeyInfo>
      <X509Data>
        <X509Certificate>fdsafsdfsdfdsfsdfsdfsdf</X509Certificate>
      </X509Data>
    </KeyInfo>
  </Signature>
</EnviarLoteRpsEnvio>

eu consegui (eu acho) fazer ele assinar o rps pela referencia, mas ele ficou do lado de fora da Tag logo dps da primeira assinatura, como se fosce mais uma assinatura do XML e não dentro da tag como no exemplo…

cara consegui!! FINALMENTE !

vou explicar aqui porque pode servir para alguem
oque tava faltando em relação à como o código vai saber em qual RPS assinar eu fiz assim

tinha de ser gerado uma String com vários campos do RPS, eu fiz isso, e coloquei no ID da tag do Rps.

    <InfRps Id="NFe0000000001254550001000000000000190020100528FNN00000000173913600000000000000000000100227437215000120">

sendo InfRps filha da tag
e no código, esse elemento é achado nesse assim

		Reference ref = fac.newReference(new String("#" + referencia), fac
					.newDigestMethod(DigestMethod.SHA1, null), transformList,
					null, null);

o atributo referencia é o que contem o valor de NFe0000000001254550001000000000000190020100528FNN00000000173913600000000000000000000100227437215000120

agora respondendo a minha outra dúvida, como assinar dentro desta tag do RPS?

eu mudei seu código para isso :

DOMSignContext dsc = new DOMSignContext(privateKey, xml .getDocumentElement().getElementsByTagName("RPS").item(0));

este código está retornando apenas o primeiro valor, ainda vou fazer pra assinar todos, mas acho que basta fazer um for

for (int i = 0; i < doc.getDocumentElement().getElementsByTagName("RPS").getLength(); i++) 

e chamar o método de assinatura e trocar esse “0” pelo “i”. deve funcionar,
qualquer coisa posto aqui se esse for não der certo, a solução.

vlw cristiano, voce me ajudou 200%!!
to te devendo uma cerveja;

olá sandro
estou iniciando o desenvolvimento da nota fiscal eletronica no java
pode me ajudar ?
esse métido x509, do que se trata ?
obrigado

cristiano.andrade MUITO OBRIGADO PELO SEU EXEMPLO!
Salvou a vida!!!

Desculpem estar upando o topico, mas estou com o mesmo problema e não consegui resolver utilizando o exemplo ai citado.
O layout deve ter mudado em relação ao q o sandroalm.silva implementou pois hoje não existe mais a tag onde ele coloca o ID como referencia. Sendo assim não consegui passar um id com referencia. Tentei criar a tag com o valor sem a criptografia e passar este valor como referencia, não deu certo.

Alguem conseguiu implementar isto em java ?

Obrigado.

alguem conseguiu ja ?