Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assinatura do XML #3

Open
rodrigorodriguescosta opened this issue Dec 22, 2020 · 24 comments
Open

Assinatura do XML #3

rodrigorodriguescosta opened this issue Dec 22, 2020 · 24 comments

Comments

@rodrigorodriguescosta
Copy link

Olá, de uma olhada no seu código e não vi se tinha como assinar um XML usando o certificado, vi que vc ler o certificado, tem alguma função para assinatura do XML?

@frones
Copy link
Owner

frones commented Dec 29, 2020

Olá, Rodrigo! Na verdade eu só comecei esse projeto, minha necessidade imediata eram as consultas de situação da NFe e de cadastro. O restante (incluindo geração, assinatura e transmissão dos XMLs) ficou pra depois e eu acabei entrando em outro projeto que está bastante distante da NFe.
Ainda pretendo finalizar os recursos inicialmente pretendidos, mas a essa altura não espere muita agilidade.
Se você tiver flexibilidade de linguagem, recomendo dar uma olhada no ACBr e no UniNFe. São dois projetos bacanas e bem completos para NFe.

@rodrigorodriguescosta
Copy link
Author

obrigado pelo retorno, eu ja tenho sistema que emite Nfe e assinatura feito em Python, estava migrando pra Go e queria emitir a partir de um servidor na nuvem em um programa Go, cheguei a testar esse russellhaering/goxmldsig#65 e conseguir fazer gerar uma assinatura válida, porém, ele tem um bug que so assinsa se o Id tiver na raiz do XML.

eu conheço o Acbr, tentei o AcbrLib com comunicação via C para ser usada em Go mas nao conseguir funcionar. https://acbr.sourceforge.io/ACBrLib/CdeclouStdCallqualusar.html

novamente, obrigado pelo retorno

@alexrosabr
Copy link

@rodrigorodriguescosta você ainda tem interesse em assinar e enviar?

@rodrigorodriguescosta
Copy link
Author

@alexrosabr eu conseguir assinar o XML em Go usando essa lib acima que falei

@alexrosabr
Copy link

alexrosabr commented May 4, 2022

@alexrosabr eu conseguir assinar o XML em Go usando essa lib acima que falei

@rodrigorodriguescosta Você precisou mexer na https://github.com/russellhaering/goxmldsig ou conseguiu fazer funcionar de outra forma? Tenho interesse em dar continuidade, pode ser aqui nesse projeto ou em algum fork.

@RhuanPrado
Copy link

@alexrosabr eu conseguir assinar o XML em Go usando essa lib acima que falei

Interessante poderia apresentar um exemplo da assinatura utilizando essa Lib?
Eu tentei e não consegui uma assinatura válida.

@alexrosabr
Copy link

@alexrosabr eu conseguir assinar o XML em Go usando essa lib acima que falei

Interessante poderia apresentar um exemplo da assinatura utilizando essa Lib? Eu tentei e não consegui uma assinatura válida.

Não fui eu, foi o @rodrigorodriguescosta que conseguiu.

@rodrigorodriguescosta
Copy link
Author

fala galera, segue a fucnao que fiz funcionar, precisa adaptar

		keyPair, _ := tls.X509KeyPair(certBytes, keBytes)
		keyStore := dsig.TLSCertKeyStore(keyPair)
		
		ctx := dsig.NewDefaultSigningContext(keyStore)
		ctx.Hash = crypto.SHA1
		ctx.IdAttribute = "Id"
		ctx.Canonicalizer = dsig.MakeC14N10RecCanonicalizer()
		ctx.Prefix = ""
		doc := etree.NewDocument()

               //procura pele elemento que precisa de assinatura
		elementToSign := doc.FindElement(fmt.Sprintf("//%s", tagAssinatura))
		if elementToSign == nil {
			err = fmt.Errorf("nao foi possivel achar a tag de referencia '%s' para assinatura ", tagAssinatura)
			return
		}
		// so assina corretamente se tiver o xmlns dentro da tag que precisa assinar, entao caso nao exista, adicione
		// para poder efetuar a assinatura corretamente
		if elementToSign.SelectAttr("xmlns") == nil {
			if strings.Contains(xml, "http://www.portalfiscal.inf.br/mdfe") {
				elementToSign.CreateAttr("xmlns", "http://www.portalfiscal.inf.br/mdfe")
			} else {
				elementToSign.CreateAttr("xmlns", "http://www.portalfiscal.inf.br/nfe")
			}
		}

		// realiza a assinatura
		signedElement, err2 := ctx.SignEnveloped(elementToSign)

@rodrigorodriguescosta
Copy link
Author

rodrigorodriguescosta commented Sep 6, 2022

ou seja, a lib em si nao precisou de ajuste, precisou de ajuste na funcao para assinar o XML da nota

@RhuanPrado
Copy link

@alexrosabr eu conseguir assinar o XML em Go usando essa lib acima que falei

@rodrigorodriguescosta Você precisou mexer na https://github.com/russellhaering/goxmldsig ou conseguiu fazer funcionar de outra forma? Tenho interesse em dar continuidade, pode ser aqui nesse projeto ou em algum fork.

Obteve algum sucesso na assinatura?

@RhuanPrado
Copy link

Ao enivar para a Sefaz eu recebo:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Body><nfeResultMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NFeAutorizacao4"><retEnviNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00"> <tpAmb>2</tpAmb> <verAplic>14.4.80-OR3</verAplic> <cStat>104</cStat> <xMotivo>Lote processado</xMotivo> <cUF>31</cUF> <dhRecbto>2022-09-06T10:35:31-03:00</dhRecbto> <protNFe versao="4.00"> <infProt> <tpAmb>2</tpAmb> <verAplic>14.4.80-OR3</verAplic> <chNFe>31220705749654000136550010000104901220730125</chNFe> <dhRecbto>2022-09-06T10:35:31-03:00</dhRecbto> <digVal>nNJuzqGxxkYkiFZqdtfbEtftgx8=</digVal> <cStat>297</cStat> <xMotivo>Rejeicao: Assinatura difere do calculado</xMotivo> </infProt> </protNFe> </retEnviNFe></nfeResultMsg></soap:Body></soap:Envelope>

@rodrigorodriguescosta
Copy link
Author

preste atencao aos comentários no código

@RhuanPrado
Copy link

fala galera, segue a fucnao que fiz funcionar, precisa adaptar

		keyPair, _ := tls.X509KeyPair(certBytes, keBytes)
		keyStore := dsig.TLSCertKeyStore(keyPair)
		
		ctx := dsig.NewDefaultSigningContext(keyStore)
		ctx.Hash = crypto.SHA1
		ctx.IdAttribute = "Id"
		ctx.Canonicalizer = dsig.MakeC14N10RecCanonicalizer()
		ctx.Prefix = ""
		doc := etree.NewDocument()

               //procura pele elemento que precisa de assinatura
		elementToSign := doc.FindElement(fmt.Sprintf("//%s", tagAssinatura))
		if elementToSign == nil {
			err = fmt.Errorf("nao foi possivel achar a tag de referencia '%s' para assinatura ", tagAssinatura)
			return
		}
		// so assina corretamente se tiver o xmlns dentro da tag que precisa assinar, entao caso nao exista, adicione
		// para poder efetuar a assinatura corretamente
		if elementToSign.SelectAttr("xmlns") == nil {
			if strings.Contains(xml, "http://www.portalfiscal.inf.br/mdfe") {
				elementToSign.CreateAttr("xmlns", "http://www.portalfiscal.inf.br/mdfe")
			} else {
				elementToSign.CreateAttr("xmlns", "http://www.portalfiscal.inf.br/nfe")
			}
		}

		// realiza a assinatura
		signedElement, err2 := ctx.SignEnveloped(elementToSign)

Legal, eu estou faz algum tempo tentando realizar a assinatura!

@rodrigorodriguescosta
Copy link
Author

eu passei mais de mês até descobrir o porque, que no caso é esse código que mandei

@RhuanPrado
Copy link

eu passei mais de mês até descobrir o porque, que no caso é esse código que mandei

Como você faz a manipulação do xml?
utilizando https://pkg.go.dev/github.com/beevik/etree
ou https://pkg.go.dev/encoding/xml

@rodrigorodriguescosta
Copy link
Author

eu passei mais de mês até descobrir o porque, que no caso é esse código que mandei

Como você faz a manipulação do xml? utilizando https://pkg.go.dev/github.com/beevik/etree ou https://pkg.go.dev/encoding/xml

utilizando o etree, aqui está meu import

import (
	"comps/utils"
	"crypto"
	"crypto/tls"
	"encoding/xml"
	"fmt"
	"net/http"
	"strings"
	"time"

	"github.com/beevik/etree"
	dsig "github.com/russellhaering/goxmldsig"
)

@RhuanPrado
Copy link

fala galera, segue a fucnao que fiz funcionar, precisa adaptar

		keyPair, _ := tls.X509KeyPair(certBytes, keBytes)
		keyStore := dsig.TLSCertKeyStore(keyPair)
		
		ctx := dsig.NewDefaultSigningContext(keyStore)
		ctx.Hash = crypto.SHA1
		ctx.IdAttribute = "Id"
		ctx.Canonicalizer = dsig.MakeC14N10RecCanonicalizer()
		ctx.Prefix = ""
		doc := etree.NewDocument()

               //procura pele elemento que precisa de assinatura
		elementToSign := doc.FindElement(fmt.Sprintf("//%s", tagAssinatura))
		if elementToSign == nil {
			err = fmt.Errorf("nao foi possivel achar a tag de referencia '%s' para assinatura ", tagAssinatura)
			return
		}
		// so assina corretamente se tiver o xmlns dentro da tag que precisa assinar, entao caso nao exista, adicione
		// para poder efetuar a assinatura corretamente
		if elementToSign.SelectAttr("xmlns") == nil {
			if strings.Contains(xml, "http://www.portalfiscal.inf.br/mdfe") {
				elementToSign.CreateAttr("xmlns", "http://www.portalfiscal.inf.br/mdfe")
			} else {
				elementToSign.CreateAttr("xmlns", "http://www.portalfiscal.inf.br/nfe")
			}
		}

		// realiza a assinatura
		signedElement, err2 := ctx.SignEnveloped(elementToSign)

essas alterações estão no seu Fork?
https://github.com/rodrigorodriguescosta/goxmldsig

@rodrigorodriguescosta
Copy link
Author

rodrigorodriguescosta commented Sep 6, 2022

fala galera, segue a fucnao que fiz funcionar, precisa adaptar

		keyPair, _ := tls.X509KeyPair(certBytes, keBytes)
		keyStore := dsig.TLSCertKeyStore(keyPair)
		
		ctx := dsig.NewDefaultSigningContext(keyStore)
		ctx.Hash = crypto.SHA1
		ctx.IdAttribute = "Id"
		ctx.Canonicalizer = dsig.MakeC14N10RecCanonicalizer()
		ctx.Prefix = ""
		doc := etree.NewDocument()

               //procura pele elemento que precisa de assinatura
		elementToSign := doc.FindElement(fmt.Sprintf("//%s", tagAssinatura))
		if elementToSign == nil {
			err = fmt.Errorf("nao foi possivel achar a tag de referencia '%s' para assinatura ", tagAssinatura)
			return
		}
		// so assina corretamente se tiver o xmlns dentro da tag que precisa assinar, entao caso nao exista, adicione
		// para poder efetuar a assinatura corretamente
		if elementToSign.SelectAttr("xmlns") == nil {
			if strings.Contains(xml, "http://www.portalfiscal.inf.br/mdfe") {
				elementToSign.CreateAttr("xmlns", "http://www.portalfiscal.inf.br/mdfe")
			} else {
				elementToSign.CreateAttr("xmlns", "http://www.portalfiscal.inf.br/nfe")
			}
		}

		// realiza a assinatura
		signedElement, err2 := ctx.SignEnveloped(elementToSign)

essas alterações estão no seu Fork? https://github.com/rodrigorodriguescosta/goxmldsig

nao, eu nao dei seguimento ao projeto, essas alteracoes fazem parte do projeto erp que eu desenvolvi, eu copiei do código aqui essa parte de assinatura, eu nao alterei o projeto de assinatura, na verdade vou ate excluir esse fork pq acabei nao utilizando ele

@RhuanPrado
Copy link

fala galera, segue a fucnao que fiz funcionar, precisa adaptar

		keyPair, _ := tls.X509KeyPair(certBytes, keBytes)
		keyStore := dsig.TLSCertKeyStore(keyPair)
		
		ctx := dsig.NewDefaultSigningContext(keyStore)
		ctx.Hash = crypto.SHA1
		ctx.IdAttribute = "Id"
		ctx.Canonicalizer = dsig.MakeC14N10RecCanonicalizer()
		ctx.Prefix = ""
		doc := etree.NewDocument()

               //procura pele elemento que precisa de assinatura
		elementToSign := doc.FindElement(fmt.Sprintf("//%s", tagAssinatura))
		if elementToSign == nil {
			err = fmt.Errorf("nao foi possivel achar a tag de referencia '%s' para assinatura ", tagAssinatura)
			return
		}
		// so assina corretamente se tiver o xmlns dentro da tag que precisa assinar, entao caso nao exista, adicione
		// para poder efetuar a assinatura corretamente
		if elementToSign.SelectAttr("xmlns") == nil {
			if strings.Contains(xml, "http://www.portalfiscal.inf.br/mdfe") {
				elementToSign.CreateAttr("xmlns", "http://www.portalfiscal.inf.br/mdfe")
			} else {
				elementToSign.CreateAttr("xmlns", "http://www.portalfiscal.inf.br/nfe")
			}
		}

		// realiza a assinatura
		signedElement, err2 := ctx.SignEnveloped(elementToSign)

essas alterações estão no seu Fork? https://github.com/rodrigorodriguescosta/goxmldsig

nao, eu nao dei seguimento ao projeto, essas alteracoes fazem parte do projeto erp que eu desenvolvi, eu copiei do código aqui essa parte de assinatura

então vc não efetuou alterações na Lib

@RhuanPrado
Copy link

Obrigado pela resposta, precisando estou a disposição!

@RhuanPrado
Copy link

fala galera, segue a fucnao que fiz funcionar, precisa adaptar

		keyPair, _ := tls.X509KeyPair(certBytes, keBytes)
		keyStore := dsig.TLSCertKeyStore(keyPair)
		
		ctx := dsig.NewDefaultSigningContext(keyStore)
		ctx.Hash = crypto.SHA1
		ctx.IdAttribute = "Id"
		ctx.Canonicalizer = dsig.MakeC14N10RecCanonicalizer()
		ctx.Prefix = ""
		doc := etree.NewDocument()

               //procura pele elemento que precisa de assinatura
		elementToSign := doc.FindElement(fmt.Sprintf("//%s", tagAssinatura))
		if elementToSign == nil {
			err = fmt.Errorf("nao foi possivel achar a tag de referencia '%s' para assinatura ", tagAssinatura)
			return
		}
		// so assina corretamente se tiver o xmlns dentro da tag que precisa assinar, entao caso nao exista, adicione
		// para poder efetuar a assinatura corretamente
		if elementToSign.SelectAttr("xmlns") == nil {
			if strings.Contains(xml, "http://www.portalfiscal.inf.br/mdfe") {
				elementToSign.CreateAttr("xmlns", "http://www.portalfiscal.inf.br/mdfe")
			} else {
				elementToSign.CreateAttr("xmlns", "http://www.portalfiscal.inf.br/nfe")
			}
		}

		// realiza a assinatura
		signedElement, err2 := ctx.SignEnveloped(elementToSign)

na variavel doc você carrega o arquivo xml?
estou tendo problemas com o FindElement()

@rodrigorodriguescosta
Copy link
Author

sim, esqueci de colocar essa parte, carrego o xml na variavel doc

doc := etree.NewDocument()
err = doc.ReadFromString(xml)
if err != nil {
	return
}

@RhuanPrado
Copy link

@rodrigorodriguescosta A tag para assinatura você passa a infNFe ? ou a NFe?
por que quando eu passo a infNFe ele coloca dentro da Tag infNFe e não ao lado

@rodrigorodriguescosta
Copy link
Author

eu passo a infNFe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants