You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
57 lines
2.0 KiB
57 lines
2.0 KiB
# -*- coding: utf-8 -*-
|
|
# © 2016 Danimar Ribeiro, Trustcode
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
|
|
import signxml
|
|
import os
|
|
from lxml import etree
|
|
from signxml import XMLSigner
|
|
|
|
|
|
class Assinatura(object):
|
|
def __init__(self, cert_pem, private_key, password):
|
|
self.cert_pem = cert_pem
|
|
self.private_key = private_key
|
|
self.password = password
|
|
|
|
def _checar_certificado(self):
|
|
if not os.path.isfile(self.private_key):
|
|
raise Exception("Caminho do certificado não existe.")
|
|
|
|
def assina_xml(self, xml_element, reference, getchildren=False):
|
|
self._checar_certificado()
|
|
cert = self.cert_pem
|
|
key = self.password
|
|
|
|
for element in xml_element.iter("*"):
|
|
if element.text is not None and not element.text.strip():
|
|
element.text = None
|
|
|
|
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 = {}
|
|
ns[None] = signer.namespaces["ds"]
|
|
signer.namespaces = ns
|
|
|
|
ref_uri = ("#%s" % reference) if reference else None
|
|
signed_root = signer.sign(
|
|
xml_element, key=key.encode(), cert=cert.encode(), reference_uri=ref_uri
|
|
)
|
|
if reference:
|
|
element_signed = signed_root.find(".//*[@Id='%s']" % reference)
|
|
signature = signed_root.find(
|
|
".//{http://www.w3.org/2000/09/xmldsig#}Signature"
|
|
)
|
|
|
|
if getchildren and element_signed is not None and signature is not None:
|
|
child = element_signed.getchildren()
|
|
child.append(signature)
|
|
elif element_signed is not None and signature is not None:
|
|
parent = element_signed.getparent()
|
|
parent.append(signature)
|
|
return etree.tostring(signed_root, encoding=str)
|