让我们看看如何签署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())
如果我们执行它,而没有修改文件,并且在对内容进行了任何修改后,我们可以观察到差异。
您可以看到,事情很简单吗?