Ниже приведен полный пример, включая все необходимое:
Необработанный XML-файл состоит из элементов Header и Body, и (по требованию) подпись должна быть выполнена на этих двух.
Код Python:
Код: Выделить всё
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)
Код: Выделить всё
Test
12345
Код: Выделить всё
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
Код: Выделить всё
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
примечание: для проверки я использую объект xml, а не записанный файл.
Записанный файл:
Код: Выделить всё
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.
Подробнее здесь: https://stackoverflow.com/questions/798 ... ec-example
Мобильная версия