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
Revision 2 as of 2019-10-18 21:56:58
  • Python
  • xmlsign

xmlsign

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

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>
  • MoinMoin Powered
  • Python Powered
  • GPL licensed
  • Valid HTML 4.01