parent
b478a7d826
commit
99072e3f7b
69
invoice.py
69
invoice.py
|
@ -452,19 +452,17 @@ class Invoice(metaclass=PoolMeta):
|
||||||
cert_file.close()
|
cert_file.close()
|
||||||
|
|
||||||
def _sign_file(cert, password, request):
|
def _sign_file(cert, password, request):
|
||||||
|
# get key and certificates from PCK12 file
|
||||||
(
|
(
|
||||||
private_key,
|
private_key,
|
||||||
certificate,
|
certificate,
|
||||||
additional_certificates,
|
additional_certificates,
|
||||||
) = pkcs12.load_key_and_certificates(cert, password)
|
) = pkcs12.load_key_and_certificates(cert, password)
|
||||||
# key = private_key.private_bytes(
|
|
||||||
# encoding=serialization.Encoding.PEM,
|
|
||||||
# format=serialization.PrivateFormat.PKCS8,
|
|
||||||
# encryption_algorithm=serialization.NoEncryption(),
|
|
||||||
# )
|
|
||||||
# DER is an ASN.1 encoding type
|
# DER is an ASN.1 encoding type
|
||||||
crt = certificate.public_bytes(serialization.Encoding.DER)
|
crt = certificate.public_bytes(serialization.Encoding.DER)
|
||||||
|
|
||||||
|
# Set variables values
|
||||||
rand_min = 1
|
rand_min = 1
|
||||||
rand_max = 99999
|
rand_max = 99999
|
||||||
signature_id = "Signature%05d" % random.randint(rand_min, rand_max)
|
signature_id = "Signature%05d" % random.randint(rand_min, rand_max)
|
||||||
|
@ -483,18 +481,32 @@ class Invoice(metaclass=PoolMeta):
|
||||||
".pdf"
|
".pdf"
|
||||||
)
|
)
|
||||||
sig_policy_hash_value = "Ohixl6upD6av8N7pEvDABhEL6hM="
|
sig_policy_hash_value = "Ohixl6upD6av8N7pEvDABhEL6hM="
|
||||||
|
|
||||||
|
# Get XML file to edit
|
||||||
root = etree.fromstring(request)
|
root = etree.fromstring(request)
|
||||||
|
|
||||||
|
# Create a signature template for RSA-SHA1 enveloped signature.
|
||||||
sign = xmlsig.template.create(
|
sign = xmlsig.template.create(
|
||||||
c14n_method=xmlsig.constants.TransformInclC14N,
|
c14n_method=xmlsig.constants.TransformInclC14N,
|
||||||
sign_method=xmlsig.constants.TransformRsaSha1,
|
sign_method=xmlsig.constants.TransformRsaSha1,
|
||||||
name=signature_id,
|
name=signature_id,
|
||||||
ns="ds",
|
ns="ds",
|
||||||
)
|
)
|
||||||
key_info = xmlsig.template.ensure_key_info(sign, name=key_info_id)
|
assert sign is not None
|
||||||
x509_data = xmlsig.template.add_x509_data(key_info)
|
|
||||||
xmlsig.template.x509_data_add_certificate(x509_data)
|
|
||||||
xmlsig.template.add_key_value(key_info)
|
|
||||||
|
|
||||||
|
# Add the <ds:Signature/> node to the document.
|
||||||
|
root.append(sign)
|
||||||
|
|
||||||
|
# Add the <ds:Reference/> node to the signature template.
|
||||||
|
ref = xmlsig.template.add_reference(
|
||||||
|
sign, xmlsig.constants.TransformSha1, name=reference_id, uri=""
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the enveloped transform descriptor.
|
||||||
|
xmlsig.template.add_transform(ref,
|
||||||
|
xmlsig.constants.TransformEnveloped)
|
||||||
|
|
||||||
|
# Add 2 new <ds:Reference/> node to the signature template.
|
||||||
xmlsig.template.add_reference(
|
xmlsig.template.add_reference(
|
||||||
sign,
|
sign,
|
||||||
xmlsig.constants.TransformSha1,
|
xmlsig.constants.TransformSha1,
|
||||||
|
@ -504,11 +516,20 @@ class Invoice(metaclass=PoolMeta):
|
||||||
xmlsig.template.add_reference(
|
xmlsig.template.add_reference(
|
||||||
sign, xmlsig.constants.TransformSha1, uri="#" + key_info_id
|
sign, xmlsig.constants.TransformSha1, uri="#" + key_info_id
|
||||||
)
|
)
|
||||||
ref = xmlsig.template.add_reference(
|
|
||||||
sign, xmlsig.constants.TransformSha1, name=reference_id, uri=""
|
# Add the <ds:KeyInfo/> and <ds:KeyName/> nodes.
|
||||||
)
|
key_info = xmlsig.template.ensure_key_info(sign, name=key_info_id)
|
||||||
xmlsig.template.add_transform(ref,
|
x509_data = xmlsig.template.add_x509_data(key_info)
|
||||||
xmlsig.constants.TransformEnveloped)
|
xmlsig.template.x509_data_add_certificate(x509_data)
|
||||||
|
|
||||||
|
# Set the certificate values
|
||||||
|
ctx = xmlsig.SignatureContext()
|
||||||
|
ctx.private_key = private_key
|
||||||
|
ctx.x509 = certificate
|
||||||
|
ctx.ca_certificates = additional_certificates
|
||||||
|
ctx.public_key = certificate.public_key()
|
||||||
|
|
||||||
|
# Set the footer validation
|
||||||
object_node = etree.SubElement(
|
object_node = etree.SubElement(
|
||||||
sign,
|
sign,
|
||||||
etree.QName(xmlsig.constants.DSigNs, "Object"),
|
etree.QName(xmlsig.constants.DSigNs, "Object"),
|
||||||
|
@ -618,15 +639,25 @@ class Invoice(metaclass=PoolMeta):
|
||||||
etree.SubElement(
|
etree.SubElement(
|
||||||
data_object_format, etree.QName(etsi, "Description")
|
data_object_format, etree.QName(etsi, "Description")
|
||||||
).text = "Factura"
|
).text = "Factura"
|
||||||
|
data_object_format_identifier = etree.SubElement(
|
||||||
|
data_object_format, etree.QName(etsi, "ObjectIdentifier")
|
||||||
|
)
|
||||||
|
etree.SubElement(
|
||||||
|
data_object_format_identifier,
|
||||||
|
etree.QName(etsi, "Identifier"),
|
||||||
|
attrib={"Qualifier": "OIDAsURN"}
|
||||||
|
).text = "urn:oid:1.2.840.10003.5.109.10"
|
||||||
|
etree.SubElement(
|
||||||
|
data_object_format_identifier, etree.QName(etsi, "Description")
|
||||||
|
)
|
||||||
etree.SubElement(
|
etree.SubElement(
|
||||||
data_object_format, etree.QName(etsi, "MimeType")
|
data_object_format, etree.QName(etsi, "MimeType")
|
||||||
).text = "text/xml"
|
).text = "text/xml"
|
||||||
ctx = xmlsig.SignatureContext()
|
|
||||||
ctx.x509 = certificate
|
# Sign the file and verify the sign.
|
||||||
ctx.public_key = certificate.public_key()
|
|
||||||
ctx.private_key = private_key
|
|
||||||
root.append(sign)
|
|
||||||
ctx.sign(sign)
|
ctx.sign(sign)
|
||||||
|
ctx.verify(sign)
|
||||||
|
|
||||||
return etree.tostring(root, xml_declaration=True, encoding="UTF-8")
|
return etree.tostring(root, xml_declaration=True, encoding="UTF-8")
|
||||||
|
|
||||||
signed_file_content = _sign_file(
|
signed_file_content = _sign_file(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% from "template_facturae_macros.xml" import administrative_center, address, contact %}<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
{% from "template_facturae_macros.xml" import administrative_center, address, contact %}<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||||
<namespace:Facturae xmlns:namespace2="http://uri.etsi.org/01903/v1.2.2#" xmlns:namespace3="http://www.w3.org/2000/09/xmldsig#" xmlns:namespace="http://www.facturae.es/Facturae/2014/v3.2.1/Facturae">
|
<namespace:Facturae xmlns:namespace="http://www.facturae.es/Facturae/2014/v3.2.1/Facturae" xmlns:namespace2="http://uri.etsi.org/01903/v1.2.2#" xmlns:namespace3="http://www.w3.org/2000/09/xmldsig#">
|
||||||
<FileHeader>
|
<FileHeader>
|
||||||
<SchemaVersion>3.2.1</SchemaVersion>
|
<SchemaVersion>3.2.1</SchemaVersion>
|
||||||
<Modality>I</Modality>
|
<Modality>I</Modality>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
<!-- Schema for XML Signatures
|
<!-- Schema for XML Signatures
|
||||||
http://www.w3.org/2000/09/xmldsig#
|
http://www.w3.org/2000/09/xmldsig#
|
||||||
$Revision: 1.1 $ on $Date: 2002/02/08 20:32:26 $ by $Author: reagle $
|
$Revision: 1.2 $ on $Date: 2013-04-16 12:48:49 $ by $Author: denis $
|
||||||
|
|
||||||
Copyright 2001 The Internet Society and W3C (Massachusetts Institute
|
Copyright 2001 The Internet Society and W3C (Massachusetts Institute
|
||||||
of Technology, Institut National de Recherche en Informatique et en
|
of Technology, Institut National de Recherche en Informatique et en
|
||||||
|
|
Loading…
Reference in New Issue