Im Folgenden finden Sie ein vollständiges Beispiel, einschließlich aller benötigten Dinge:
Das Roh-XML besteht aus den Elementen Header und Body und (als Voraussetzung) muss die Signatur auf diesen beiden ausgeführt werden.
Der Python-Code lautet:
Code: Select all
import lxml.etree as ET
import xmlsec
import textwrap
xmlsec.enable_debug_trace(True)
################
### SIGN ###
################
# ====================================================================================
# 1) load XML
# ====================================================================================
xml = ET.parse("raw.xml")
root = xml.getroot()
# ====================================================================================
# 2) Signature-Template
# ====================================================================================
signature_node = xmlsec.template.create(
root,
c14n_method=xmlsec.Transform.C14N, # Canonicalization
sign_method=xmlsec.Transform.RSA_SHA256, # Signature-Method
ns="ns3"
)
# ====================================================================================
# 3) Reference + Transform (XML Signature Filter 2)
# ====================================================================================
ref = xmlsec.template.add_reference(
signature_node,
digest_method=xmlsec.Transform.SHA256,
uri=""
)
# Add FILTER2 transform
tr = xmlsec.template.add_transform(ref, xmlsec.Transform.XPATH2)
# XPath
xpath_node = ET.SubElement(
tr,
"{http://www.w3.org/2002/06/xmldsig-filter2}XPath"
)
xpath_node.set("Filter", "intersect")
xpath_node.text = "//*[local-name()='Header' or local-name()='Body']"
# ====================================================================================
# 4) KeyInfo + X509-Data
# ====================================================================================
key_info = xmlsec.template.ensure_key_info(signature_node)
xmlsec.template.add_x509_data(key_info)
# ====================================================================================
# 5) Signature-context
# ====================================================================================
ctx = xmlsec.SignatureContext()
ctx.key = xmlsec.Key.from_file("myprivatekey.pem", xmlsec.KeyFormat.PEM)
ctx.key.load_cert_from_file("test.crt", xmlsec.KeyFormat.CERT_PEM)
# ====================================================================================
# 6) Sign
# ====================================================================================
ctx.sign(signature_node)
# Signature at the end
root.append(signature_node)
xml.write("raw_signed.xml", encoding="UTF-8", xml_declaration=True, pretty_print=False)
################
#### VERIFY ####
################
def b64_to_pem(b64):
b64 = "".join(b64.split()) # removes all whitespace
return (
"-----BEGIN CERTIFICATE-----\n"
+ textwrap.fill(b64, 64)
+ "\n-----END CERTIFICATE-----\n"
)
def verify_signed_xml(xml):
root = xml.getroot()
signature_node = xmlsec.tree.find_node(root, xmlsec.Node.SIGNATURE)
if signature_node is None:
raise Exception("Keine im XML gefunden!")
ctx = xmlsec.SignatureContext()
crtttext = signature_node.find(".//{http://www.w3.org/2000/09/xmldsig#}X509Certificate").text
print("cert")
print(crtttext)
pem = b64_to_pem(crtttext)
print("pem")
print(pem)
key = xmlsec.Key.from_memory(
pem,
xmlsec.KeyFormat.CERT_PEM,
None
)
ctx.key = key
# 5. verify
try:
ctx.verify(signature_node)
print("✔ Signature is valid")
return True
except xmlsec.VerificationError as e:
print("✘ Signature invalid:", e)
return False
verify_signed_xml(xml)
Code: Select all
Test
12345
Code: Select all
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
Code: Select all
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
Hinweis – zur Überprüfung verwende ich das XML-Objekt – nicht die geschriebene Datei.
Die geschriebene Datei ist:
Code: Select all
Test
12345
//*[local-name()='Header' or local-name()='Body']
JrMAhSgrvTYKjSaE9kPS37xJ3WtAGMKZrjdbuYsLVYw=
lDxYDNhqvQsKt7asNpgI1S26HIHxaqPfHh2pLD1IftWHtRkn25KbX9NJmH2DRYG8
eHUtFVnRBeAKaBkMld1D4NvLSyy2tuXCzCjqz7ZKYSC...
MIIFOzCCAyOgAwIBAgIIfWPNuRppL...
> func=xmlSecOpenSSLEvpSignatureVerify:file=..\src\openssl\signatures.c:line=1074:obj=rsa-sha256:subj=unknown:error=18:data
> do not match:details=Signature verification failed ✘ Signature
> invalid: Signature is invalid.
Mobile version