MoinMoin Logo
  • Comments
  • Immutable Page
  • Menu
    • Navigation
    • RecentChanges
    • FindPage
    • Local Site Map
    • Help
    • HelpContents
    • HelpOnMoinWikiSyntax
    • Display
    • Attachments
    • Info
    • Raw Text
    • Print View
    • Edit
    • Load
    • Save
  • Login

Navigation

  • Start
  • Sitemap

Upload page content

You can upload content for the page named below. If you change the page name, you can also upload content for another page. If the page name is empty, we derive the page name from the file name.

File to load page content from
Page name
Comment

  • Python
  • xmlsign

xmlsign

  • https://pypi.org/project/signxml/

  • https://www.w3.org/TR/xmldsig-core/xmldsig-core-schema.xsd

Format XML

   1 sudo apt install libxml2-utils # install in debian
   2 xmllint --format payload.xml  # format XML
   3 

Example

main.py

   1 '''
   2 pip install signxml lxml
   3 # generate the x509 cert and private key
   4 openssl req -new -x509 -days 3650 -nodes -out cert.pem -keyout privkey.pem
   5 
   6 apt install libxml2-utils
   7 
   8 xmllint --schema ./test.xsd ./test_signed.xml 
   9 xmllint --schema ./test.xsd ./test.xml 
  10 
  11 '''
  12 
  13 from signxml import XMLVerifier, XMLSigner, methods, XMLSignatureProcessor
  14 from lxml import etree
  15 
  16 XML_SIG_NS = ns = {"ds":"http://www.w3.org/2000/09/xmldsig#"}
  17 X509_CERT = "//ds:X509Certificate"
  18 PUB_KEY = "cert.pem"
  19 PRIV_KEY = "privkey.pem"
  20 
  21 def get_x509_cert(xml_signed_root):
  22     assert(type(xml_signed_root) is str)
  23     extracted_x509_cert = etree.fromstring(xml_signed_root).xpath(X509_CERT, namespaces=XML_SIG_NS)[0].text
  24     return extracted_x509_cert
  25 
  26 def sign_payload1():
  27     print "\n payload1"
  28     payload = open("payload1.xml").read()
  29     cert = open(PUB_KEY).read()
  30     key = open(PRIV_KEY).read()
  31     root = etree.fromstring(payload)
  32     signed_root = XMLSigner().sign(root, key=key, cert=cert)
  33     xml_signed_root = etree.tostring(signed_root)
  34     open("payload1_signed.xml", "wb").write(xml_signed_root)
  35     extracted_x509_cert = get_x509_cert(xml_signed_root)
  36     verified_data = XMLVerifier().verify(xml_signed_root, x509_cert=extracted_x509_cert).signed_xml
  37 
  38 def sign_payload2():
  39     print "\n payload2"
  40     payload = open("payload2.xml").read()
  41     cert = open(PUB_KEY).read()
  42     key = open(PRIV_KEY).read()
  43     root = etree.fromstring(payload)
  44     signer = XMLSigner(method=methods.enveloped, signature_algorithm="rsa-sha256",
  45         digest_algorithm="sha256", c14n_algorithm=XMLSignatureProcessor.default_c14n_algorithm)
  46     signed_root = signer.sign(root, key=key, cert=cert, reference_uri="#tosign", id_attribute="id")
  47     xml_signed_root = etree.tostring(signed_root)
  48     xml_signed_root = xml_signed_root.replace("7676767", "1111111")  # introduce change in data not signed
  49     open("payload2_signed.xml", "wb").write(xml_signed_root)
  50     extracted_x509_cert = get_x509_cert(xml_signed_root)
  51     verified_data = XMLVerifier().verify(xml_signed_root, x509_cert=extracted_x509_cert).signed_xml
  52 
  53 def sign_payload2_detached_nocert_insignature():
  54     print "\n payload2 detached no cert in signature"
  55     payload = open("payload2.xml").read()
  56     cert = open(PUB_KEY).read()
  57     key = open(PRIV_KEY).read()
  58     root = etree.fromstring(payload)
  59     signer = XMLSigner(method=methods.detached, signature_algorithm="rsa-sha256",
  60         digest_algorithm="sha256", c14n_algorithm=XMLSignatureProcessor.default_c14n_algorithm)
  61     signature = signer.sign(root, key=key, cert=None, reference_uri="#tosign", id_attribute="id")
  62     root.insert(0, signature)  # insert as first child of the XML node
  63     xml_signed_root = etree.tostring(root)
  64     xml_signed_root = xml_signed_root.replace("7676767", "1111111")  # introduce change in data not signed
  65     open("payload2_signed_nocert.xml", "wb").write(xml_signed_root)
  66     verified_data = XMLVerifier().verify(xml_signed_root, x509_cert=cert).signed_xml
  67 
  68 def sign_payload2_detached_cert_insignature():
  69     print "\n payload2 detached"
  70     payload = open("payload2.xml").read()
  71     cert = open(PUB_KEY).read()
  72     key = open(PRIV_KEY).read()
  73     root = etree.fromstring(payload)
  74     signer = XMLSigner(method=methods.detached, signature_algorithm="rsa-sha256",
  75         digest_algorithm="sha256", c14n_algorithm=XMLSignatureProcessor.default_c14n_algorithm)
  76     signature = signer.sign(root, key=key, cert=cert, reference_uri="#tosign", id_attribute="id")
  77     root.insert(0, signature)  # insert as first child of the root XML node
  78     xml_signed_root = etree.tostring(root)
  79     xml_signed_root = xml_signed_root.replace("7676767", "1111111")  # introduce change in data not signed
  80     open("payload2_signed_cert.xml", "wb").write(xml_signed_root)
  81     extracted_x509_cert = get_x509_cert(xml_signed_root)
  82     verified_data = XMLVerifier().verify(xml_signed_root, x509_cert=extracted_x509_cert).signed_xml
  83 
  84 def sign_test_detached_cert_insignature():
  85     print "\n test detached"
  86     payload = open("test.xml").read()
  87     cert = open(PUB_KEY).read()
  88     key = open(PRIV_KEY).read()
  89     root = etree.fromstring(payload)
  90     signer = XMLSigner(method=methods.detached, signature_algorithm="rsa-sha256",
  91         digest_algorithm="sha256", c14n_algorithm=XMLSignatureProcessor.default_c14n_algorithm)
  92     signature = signer.sign(root, key=key, cert=cert, reference_uri="#tosign", id_attribute="Id")
  93     nrelems = len(root.getchildren())
  94     root.insert(nrelems, signature)  # insert as the last child of the root XML node
  95     xml_signed_root = etree.tostring(root)
  96     open("test_signed.xml", "wb").write(xml_signed_root)
  97     extracted_x509_cert = get_x509_cert(xml_signed_root)
  98     verified_data = XMLVerifier().verify(xml_signed_root, x509_cert=extracted_x509_cert).signed_xml
  99 
 100 if __name__ == '__main__':
 101     sign_payload1()
 102     sign_payload2()
 103     sign_payload2_detached_nocert_insignature()
 104     sign_payload2_detached_cert_insignature()
 105     sign_test_detached_cert_insignature()

payload1.xml

   1 <a>
   2         <b>7676767</b>
   3 </a>

payload2.xml

   1 <a>
   2         <b>7676767</b>
   3         <c id="tosign">klfljsdfjlsdkfksflfk</c>
   4 </a>

test.xsd

   1 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
   2         xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
   3 
   4         <xs:import namespace="http://www.w3.org/2000/09/xmldsig#"
   5                 schemaLocation="./xmldsig-core-schema.xsd" />
   6 
   7         <xs:element name="a" type="AType" />
   8         <xs:complexType name="AType" mixed="true">
   9                 <xs:sequence>                   
  10                         <xs:element name="b" type="CType" />
  11                         <xs:element ref="ds:Signature" minOccurs="0" />
  12                 </xs:sequence>
  13         </xs:complexType>
  14 
  15         <xs:complexType name="CType" mixed="true">
  16                 <xs:sequence>
  17                         <xs:element name="c" type="xs:string" />
  18                 </xs:sequence>
  19                 <xs:attribute name="Id" type="xs:ID" use="optional" />
  20         </xs:complexType>
  21 </xs:schema>

test.xml

   1 <a>
   2         <b Id="tosign">
   3                 <c>test</c>
   4         </b>
   5 </a>

Check signed XML

   1 # check_signed_xml.py
   2 from signxml import XMLVerifier
   3 from lxml import etree
   4 import sys
   5 
   6 XML_SIG_NS = ns = {"ds":"http://www.w3.org/2000/09/xmldsig#"}
   7 X509_CERT = "//ds:X509Certificate"
   8 
   9 if __name__ == '__main__':
  10     print("Checking file %s" % (sys.argv[1]))
  11     xml_data = open(sys.argv[1]).read()
  12     try:
  13         extracted_x509_cert = etree.fromstring(xml_data).xpath(X509_CERT, namespaces=XML_SIG_NS)
  14         if len(extracted_x509_cert) > 0:
  15             verified_data = XMLVerifier().verify(xml_data, x509_cert=extracted_x509_cert[0].text).signed_xml
  16             print "Trusted data\n"+etree.tostring(verified_data)
  17         else:
  18             verified_data = XMLVerifier().verify(xml_data, require_x509=False).signed_xml
  19             print "Trusted data\n"+etree.tostring(verified_data)
  20         print("OK")
  21     except Exception as ex:
  22         print("Exception: %s" % (str(ex)))
  23         print("Has error")
  • MoinMoin Powered
  • Python Powered
  • GPL licensed
  • Valid HTML 4.01