python y firma xml
#python #xml #x509 #firma

让我们看看如何签署XML文档,以及如何验证签名文档的内容是否保持不变,或者相反,已经遭受了任何修改。

否则,我们要做的第一件事就是创建一个新的虚拟环境并激活它。

mkdir firmaXML
cd firmaXML
python3 -m venv venv
source venv/bin/activate

现在我们安装了我们需要的库。

pip install pip --update
pip install lxml
pip install signxml

为了继续签署文档,我们必须拥有X509证书,尽管我们可以使用以下命令来创建一个自我确认:

openssl req -x509 -nodes \
        -subj "/CN=Certificado autofirmado" -days 365 \
        -newkey rsa \
        -keyout clave_privada.key \
        -out clave_publica.crt

我们已经处于创建如何签名XML的示例的处置。

from lxml import etree
from signxml import XMLSigner, XMLVerifier 
from signxml.exceptions import InvalidSignature

# Nuestro contenido XML
XML = """
<test>
   Contenido importante
</test>
"""

# Recuperamos nuestras claves de certificado.Para la firma, se necesitan tanto la
# clave pública como la privada. Para la validación, sólo se requiere la pública.
clave_publica = open("clave_publica.crt", "r").read()
clave_privada = open("clave_privada.key", "r").read()

# Construimos un objeto XNL a partir de string con el contenido
nodo_raiz = etree.fromstring(XML)

# Creamos objeto XML firmado
nodo_raiz_firmado = XMLSigner().sign( 
    data=nodo_raiz,
    key=clave_privada,
    cert=clave_publica 
)

# Convertimos objeto XML a formato string y lo guardamos en fichero para comprobar después
# que se produce un error si manipulamos su contenido
XML_firmado = etree.tostring(nodo_raiz_firmado, pretty_print=True).decode()
with open("XML_firmado.xml", "w") as f:
    f.write(XML_firmado)


# Validamos integridad del contenido XML
try:
    XML_validado = XMLVerifier().verify(
        data=etree.fromstring(XML_firmado),
        x509_cert=clave_publica
    ).signed_xml
except InvalidSignature as err:
    print("ERROR validando integridad XML")
    exit()

print("=== XML original =============================================================")
print(XML)

print("=== XML firmado ==============================================================")
print(XML_firmado)

print("=== XML validado =============================================================")
print(etree.tostring(XML_validado, pretty_print=True).decode())

我认为代码是自我解释的,并且不需要更大的解释。执行后,我们将拥有一个名为 xml_firmed.xml 的文件。因此,现在,我们可以继续验证文件的完整性。

from lxml import etree
from signxml import XMLSigner, XMLVerifier 
from signxml.exceptions import InvalidSignature

# Recuperamos contenido fichero XML
XML = open("XML_firmado.xml", "r").read()

# Para la validación, sólo se requiere la clave pública.
clave_publica = open("clave_publica.crt", "r").read()

# Construimos un objeto XNL a partir de string con el contenido
nodo_raiz = etree.fromstring(XML)

# Validamos integridad del contenido XML
try:
    XML_validado = XMLVerifier().verify(
        data=etree.fromstring(XML),
        x509_cert=clave_publica
    ).signed_xml
except InvalidSignature as err:
    print("ERROR validando integridad XML")
    exit()

print("=== XML original =============================================================")
print(XML)

print("=== XML validado =============================================================")
print(etree.tostring(XML_validado, pretty_print=True).decode())

如果我们执行它,而没有修改文件,并且在对内容进行了任何修改后,我们可以观察到差异。

您可以看到,事情很简单吗?