|
|
@ -61,16 +61,30 @@ class AssinaturaA1(Assinatura): |
|
|
"""Classe abstrata responsavel por efetuar a assinatura do certificado |
|
|
"""Classe abstrata responsavel por efetuar a assinatura do certificado |
|
|
digital no XML informado.""" |
|
|
digital no XML informado.""" |
|
|
|
|
|
|
|
|
def assinar_arquivo(self, caminho_arquivo): |
|
|
|
|
|
|
|
|
def assinar_arquivo(self, caminho_arquivo, salva=True): |
|
|
# Carrega o XML do arquivo |
|
|
# Carrega o XML do arquivo |
|
|
raiz = etree.parse(caminho_arquivo) |
|
|
raiz = etree.parse(caminho_arquivo) |
|
|
return self.assinar_etree(raiz) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Efetua a assinatura |
|
|
|
|
|
xml = self.assinar_etree(raiz, retorna_xml=True) |
|
|
|
|
|
|
|
|
|
|
|
raise Exception(xml) |
|
|
|
|
|
|
|
|
|
|
|
# Grava XML assinado no arquivo |
|
|
|
|
|
if salva: |
|
|
|
|
|
fp = file(caminho_arquivo, 'w') |
|
|
|
|
|
fp.write(xml) |
|
|
|
|
|
fp.close() |
|
|
|
|
|
|
|
|
|
|
|
return xml |
|
|
|
|
|
|
|
|
def assinar_xml(self, xml): |
|
|
def assinar_xml(self, xml): |
|
|
raiz = etree.parse(StringIO(xml)) |
|
|
raiz = etree.parse(StringIO(xml)) |
|
|
return self.assinar_etree(raiz) |
|
|
|
|
|
|
|
|
|
|
|
def assinar_etree(self, raiz): |
|
|
|
|
|
|
|
|
# Efetua a assinatura |
|
|
|
|
|
return self.assinar_etree(raiz, retorna_xml=True) |
|
|
|
|
|
|
|
|
|
|
|
def assinar_etree(self, raiz, retorna_xml=False): |
|
|
# Extrai a tag do elemento raiz |
|
|
# Extrai a tag do elemento raiz |
|
|
tipo = extrair_tag(raiz.getroot()) |
|
|
tipo = extrair_tag(raiz.getroot()) |
|
|
|
|
|
|
|
|
@ -91,6 +105,24 @@ class AssinaturaA1(Assinatura): |
|
|
URI=raiz.getroot().getchildren()[0].attrib['Id'], |
|
|
URI=raiz.getroot().getchildren()[0].attrib['Id'], |
|
|
nsmap={'sig': NAMESPACE_SIG}, |
|
|
nsmap={'sig': NAMESPACE_SIG}, |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
signed_info = etree.SubElement(signature, '{%s}SignedInfo'%NAMESPACE_SIG) |
|
|
|
|
|
etree.SubElement(signed_info, 'CanonicalizationMethod', Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315") |
|
|
|
|
|
etree.SubElement(signed_info, 'SignatureMethod', Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1") |
|
|
|
|
|
|
|
|
|
|
|
reference = etree.SubElement(signed_info, '{%s}Reference'%NAMESPACE_SIG, URI=raiz.getroot().getchildren()[0].attrib['Id']) |
|
|
|
|
|
transforms = etree.SubElement(reference, 'Transforms', URI=raiz.getroot().getchildren()[0].attrib['Id']) |
|
|
|
|
|
etree.SubElement(transforms, 'Transform', Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature") |
|
|
|
|
|
etree.SubElement(transforms, 'Transform', Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315") |
|
|
|
|
|
etree.SubElement(reference, '{%s}DigestMethod'%NAMESPACE_SIG, Algorithm="http://www.w3.org/2000/09/xmldsig#sha1") |
|
|
|
|
|
digest_value = etree.SubElement(reference, '{%s}DigestValue'%NAMESPACE_SIG) |
|
|
|
|
|
|
|
|
|
|
|
signature_value = etree.SubElement(signature, '{%s}SignatureValue'%NAMESPACE_SIG) |
|
|
|
|
|
|
|
|
|
|
|
key_info = etree.SubElement(signature, '{%s}KeyInfo'%NAMESPACE_SIG) |
|
|
|
|
|
x509_data = etree.SubElement(key_info, '{%s}X509Data'%NAMESPACE_SIG) |
|
|
|
|
|
x509_certificate = etree.SubElement(x509_data, '{%s}X509Certificate'%NAMESPACE_SIG) |
|
|
|
|
|
|
|
|
raiz.getroot().insert(0, signature) |
|
|
raiz.getroot().insert(0, signature) |
|
|
|
|
|
|
|
|
# Acrescenta a tag de doctype (como o lxml nao suporta alteracao do doctype, |
|
|
# Acrescenta a tag de doctype (como o lxml nao suporta alteracao do doctype, |
|
|
@ -108,21 +140,27 @@ class AssinaturaA1(Assinatura): |
|
|
assinador.sign(noh_assinatura) |
|
|
assinador.sign(noh_assinatura) |
|
|
|
|
|
|
|
|
# Coloca na instância Signature os valores calculados |
|
|
# Coloca na instância Signature os valores calculados |
|
|
doc.Signature.DigestValue = ctxt.xpathEval(u'//sig:DigestValue')[0].content.replace(u'\n', u'') |
|
|
|
|
|
doc.Signature.SignatureValue = ctxt.xpathEval(u'//sig:SignatureValue')[0].content.replace(u'\n', u'') |
|
|
|
|
|
|
|
|
digest_value.text = ctxt.xpathEval(u'//sig:DigestValue')[0].content.replace(u'\n', u'') |
|
|
|
|
|
signature_value.text = ctxt.xpathEval(u'//sig:SignatureValue')[0].content.replace(u'\n', u'') |
|
|
|
|
|
|
|
|
# Provavelmente retornarão vários certificados, já que o xmlsec inclui a cadeia inteira |
|
|
# Provavelmente retornarão vários certificados, já que o xmlsec inclui a cadeia inteira |
|
|
certificados = ctxt.xpathEval(u'//sig:X509Data/sig:X509Certificate') |
|
|
certificados = ctxt.xpathEval(u'//sig:X509Data/sig:X509Certificate') |
|
|
doc.Signature.X509Certificate = certificados[len(certificados)-1].content.replace(u'\n', u'') |
|
|
|
|
|
|
|
|
x509_certificate.text = certificados[len(certificados)-1].content.replace(u'\n', u'') |
|
|
|
|
|
|
|
|
resultado = assinador.status == xmlsec.DSigStatusSucceeded |
|
|
resultado = assinador.status == xmlsec.DSigStatusSucceeded |
|
|
|
|
|
|
|
|
# Limpa objetos da memoria e desativa funções criptográficas |
|
|
# Limpa objetos da memoria e desativa funções criptográficas |
|
|
self._depois_de_assinar_ou_verificar(doc_xml, ctxt, assinador) |
|
|
self._depois_de_assinar_ou_verificar(doc_xml, ctxt, assinador) |
|
|
|
|
|
|
|
|
#print etree.tostring(raiz, pretty_print=True, xml_declaration=True, encoding='utf-8') |
|
|
|
|
|
|
|
|
# Gera o XML para retornar |
|
|
|
|
|
raise Exception(dir(doc_xml)) |
|
|
|
|
|
xml = doc_xml.serialize() |
|
|
|
|
|
|
|
|
return resultado |
|
|
|
|
|
|
|
|
if retorna_xml: |
|
|
|
|
|
raise Exception(xml) |
|
|
|
|
|
return xml |
|
|
|
|
|
else: |
|
|
|
|
|
return etree.parse(StringIO(xml)) |
|
|
|
|
|
|
|
|
def _ativar_funcoes_criptograficas(self): |
|
|
def _ativar_funcoes_criptograficas(self): |
|
|
# FIXME: descobrir forma de evitar o uso do libxml2 neste processo |
|
|
# FIXME: descobrir forma de evitar o uso do libxml2 neste processo |
|
|
@ -175,7 +213,6 @@ class AssinaturaA1(Assinatura): |
|
|
return resultado |
|
|
return resultado |
|
|
|
|
|
|
|
|
def _antes_de_assinar_ou_verificar(self, raiz): |
|
|
def _antes_de_assinar_ou_verificar(self, raiz): |
|
|
raise Exception(dir(raiz)) |
|
|
|
|
|
# Converte etree para string |
|
|
# Converte etree para string |
|
|
xml = etree.tostring(raiz, xml_declaration=True, encoding='utf-8') |
|
|
xml = etree.tostring(raiz, xml_declaration=True, encoding='utf-8') |
|
|
|
|
|
|
|
|
|