Browse Source

Nova forma de assinatura usando o signXML

tags/0.3.10
Leonardo 9 years ago
parent
commit
264ea14bed
  1. 3
      pynfe/entidades/certificado.py
  2. 50
      pynfe/processamento/assinatura.py
  3. 5
      pynfe/utils/__init__.py

3
pynfe/entidades/certificado.py

@ -33,7 +33,7 @@ class CertificadoA1(Certificado):
def separar_arquivo(self, senha, caminho=False):
"""Separa o arquivo de certificado em dois: de chave e de certificado,
e retorna a string. Se caminho for True grava na pasta temporaria e retorna
o caminho dos arquivos, apos o uso devem ser excluidos com o metodo excluir."""
o caminho dos arquivos, senao retorna o objeto. Apos o uso devem ser excluidos com o metodo excluir."""
# Carrega o arquivo .pfx, erro pode ocorrer se a senha estiver errada ou formato invalido.
pkcs12 = crypto.load_pkcs12(open(self.caminho_arquivo, "rb").read(), senha)
@ -69,4 +69,3 @@ class CertificadoA1(Certificado):
self.arquivos_temp.clear()
except:
pass

50
pynfe/processamento/assinatura.py

@ -1,7 +1,11 @@
# -*- coding: utf-8 -*-
from pynfe.utils import etree, remover_acentos
from pynfe.utils.flags import NAMESPACE_SIG
import subprocess
import signxml
from signxml import XMLSigner
from pynfe.entidades import CertificadoA1
class Assinatura(object):
@ -323,3 +327,49 @@ class AssinaturaA1(Assinatura):
return xml
except Exception as e:
raise e
class AssinaturaA1SignXML(Assinatura):
def __init__(self, certificado, senha):
self.key, self.cert = CertificadoA1(certificado).separar_arquivo(senha)
def assinar(self, xml, retorna_string=False):
if len(xml.nsmap.items()) == 0: # não tem namespace
reference = xml.find('infNFe').attrib['Id']
else:
ns = {'ns': 'http://www.portalfiscal.inf.br/nfe'}
reference = xml.find('ns:infNFe', namespaces=ns).attrib['Id']
# retira acentos
xml_str = remover_acentos(etree.tostring(xml, encoding="unicode", pretty_print=False))
xml = etree.fromstring(xml_str)
signer = XMLSigner(
method=signxml.methods.enveloped, signature_algorithm="rsa-sha1",
digest_algorithm='sha1',
c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
ns = {None: signer.namespaces['ds']}
signer.namespaces = ns
ref_uri = ('#%s' % reference) if reference else None
signed_root = signer.sign(
xml, key=self.key, cert=self.cert, reference_uri=ref_uri)
ns = {'ns': NAMESPACE_SIG}
if reference:
element_signed = signed_root.find(".//*[@Id='%s']" % reference)
signature = signed_root.find(".//ns:Signature", namespaces=ns)
if element_signed is not None and signature is not None:
parent = element_signed.getparent()
parent.append(signature)
# coloca o certificado na tag X509Data/X509Certificate
tagX509Data = signed_root.find('.//ns:X509Data', namespaces=ns)
etree.SubElement(tagX509Data, 'X509Certificate').text = self.cert
if retorna_string:
return etree.tostring(signed_root, encoding="unicode", pretty_print=False)
else:
return signed_root

5
pynfe/utils/__init__.py

@ -9,10 +9,7 @@ try:
except ImportError:
raise Exception('Falhou ao importar lxml/ElementTree')
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
from io import StringIO
try:
from . import flags

Loading…
Cancel
Save