Repository: xmlsec/python-xmlsec (language: python)

Issue:
test_sign_case5 fails with xmlsec 1.2.36
* xmlsec: 1.2.36
* libxmlsec1: 1.2.36
* libxml2: 2.10.3
* pkg-config --cflags xmlsec1: `-DXMLSEC_CRYPTO_DYNAMIC_LOADING=1 -D__XMLSEC_FUNCTION__=__func__ -DXMLSEC_NO_SIZE_T -DXMLSEC_NO_MD5=1 -DXMLSEC_NO_GOST=1 -DXMLSEC_NO_GOST2012=1 -DXMLSEC_DL_LIBLTDL=1 -I/usr/include/xmlsec1 -I/usr/include/libxml2`

```
self = <tests.test_ds.TestSignContext testMethod=test_sign_case5>

    def test_sign_case5(self):
        """Should sign a file using a dynamicaly created template, key from PEM file and an X509 certificate."""
        root = self.load_xml("sign5-in.xml")
        sign = xmlsec.template.create(root, consts.TransformExclC14N, consts.TransformRsaSha1)
        self.assertIsNotNone(sign)
        root.append(sign)
        ref = xmlsec.template.add_reference(sign, consts.TransformSha1)
        xmlsec.template.add_transform(ref, consts.TransformEnveloped)
    
        ki = xmlsec.template.ensure_key_info(sign)
        x509 = xmlsec.template.add_x509_data(ki)
        xmlsec.template.x509_data_add_subject_name(x509)
        xmlsec.template.x509_data_add_certificate(x509)
        xmlsec.template.x509_data_add_ski(x509)
        x509_issuer_serial = xmlsec.template.x509_data_add_issuer_serial(x509)
        xmlsec.template.x509_issuer_serial_add_issuer_name(x509_issuer_serial, 'Test Issuer')
        xmlsec.template.x509_issuer_serial_add_serial_number(x509_issuer_serial, '1')
    
        ctx = xmlsec.SignatureContext()
        ctx.key = xmlsec.Key.from_file(self.path("rsakey.pem"), format=consts.KeyDataFormatPem)
        self.assertIsNotNone(ctx.key)
        ctx.key.load_cert_from_file(self.path('rsacert.pem'), consts.KeyDataFormatPem)
        ctx.key.name = 'rsakey.pem'
        self.assertEqual("rsakey.pem", ctx.key.name)
    
        ctx.sign(sign)
>       self.assertEqual(self.load_xml("sign5-out.xml"), root)

tests/test_ds.py:186: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/base.py:128: in assertXmlEqual
    self.assertXmlEqual(c1, c2)
tests/base.py:128: in assertXmlEqual
    self.assertXmlEqual(c1, c2)
tests/base.py:128: in assertXmlEqual
    self.assertXmlEqual(c1, c2)
tests/base.py:128: in assertXmlEqual
    self.assertXmlEqual(c1, c2)
tests/base.py:118: in assertXmlEqual
    self.fail('text: {!r} != {!r}. {}'.format(first.text, second.text, msg))
E   AssertionError: text: 'JIQs8tRZIGKLLlyGkKOqMLonGpw=' != None.
```


Discussion / hints:
More precisely, `xmlsec.template.x509_data_add_ski(x509)` does not fill `<X509SKI>`:
```
<Envelope xmlns="urn:envelope">
  <Data>
	Hello, World!
  </Data>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference>
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>HjY8ilZAIEM2tBbPn5mYO1ieIX4=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>SIaj/6KY3C1SmDXU2++Gm31U1xTadFp04WhBgfsJFbxrL+q7GKSKN9kfQ+UpN9+i
D5fWmuavXEHe4Gw6RMaMEkq2URQo7F68+d5J/ajq8/l4n+xE6/reGScVwT6L4dEP
XXVJcAi2ZnQ3O7GTNvNGCPibL9mUcyCWBFZ92Uemtc/vJFCQ7ZyKMdMfACgxOwyN
T/9971oog241/2doudhonc0I/3mgPYWkZdX6yvr62mEjnG+oUZkhWYJ4ewZJ4hM4
JjbFqZO+OEzDRSbw3DkmuBA/mtlx+3t13SESfEub5hqoMdVmtth/eTb64dsPdl9r
3k1ACVX9f8aHfQQdJOmLFQ==</SignatureValue>
<KeyInfo>
<X509Data>
<X509IssuerSerial>
<X509IssuerName>Test Issuer</X509IssuerName>
<X509SerialNumber>1</X509SerialNumber>
</X509IssuerSerial>
<X509SubjectName/>
<X509Certificate>MIIE3zCCBEigAwIBAgIBBTANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCVVMx
EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tMB4X
DTAzMDMzMTA0MDIyMloXDTEzMDMyODA0MDIyMlowgb8xCzAJBgNVBAYTAlVTMRMw
EQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFy
eSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94bWxzZWMpMSEwHwYDVQQLExhFeGFt
cGxlcyBSU0EgQ2VydGlmaWNhdGUxFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAf
BgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAJe4/rQ/gzV4FokE7CthjL/EXwCBSkXm2c3p4jyXO0Wt
quaNC3dxBwFPfPl94hmq3ZFZ9PHPPbp4RpYRnLZbRjlzVSOq954AXOXpSew7nD+E
mTqQrd9+ZIbGJnLOMQh5fhMVuOW/1lYCjWAhTCcYZPv7VXD2M70vVXDVXn6ZrqTg
qkVHE6gw1aCKncwg7OSOUclUxX8+Zi10v6N6+PPslFc5tKwAdWJhVLTQ4FKG+F53
7FBDnNK6p4xiWryy/vPMYn4jYGvHUUk3eH4lFTCr+rSuJY8i/KNIf/IKim7g/o3w
Ae3GM8xrof2mgO8GjK/2QDqOQhQgYRIf4/wFsQXVZcMCAwEAAaOCAVcwggFTMAkG
A1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp
ZmljYXRlMB0GA1UdDgQWBBQkhCzy1FkgYosuXIaQo6owuicanDCB+AYDVR0jBIHw
MIHtgBS0ue+a5pcOaGUemM76VQ2JBttMfKGB0aSBzjCByzELMAkGA1UEBhMCVVMx
EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tggEA
MA0GCSqGSIb3DQEBBAUAA4GBALU/mzIxSv8vhDuomxFcplzwdlLZbvSQrfoNkMGY
1UoS3YJrN+jZLWKSyWE3mIaPpElqXiXQGGkwD5iPQ1iJMbI7BeLvx6ZxX/f+c8Wn
ss0uc1NxfahMaBoyG15IL4+beqO182fosaKJTrJNG3mc//ANGU9OsQM9mfBEt4oL
NJ2D
</X509Certificate>
<X509SKI/>
</X509Data>
</KeyInfo>
</Signature></Envelope>
```

Compiled with PYXMLSEC_ENABLE_DEBUG=1 and there *is* something odd logged right on the test:
```
tests/test_ds.py ......FE[./src/ds.c:61 PyXmlSec_SignatureContext__del__] 0x7fe9f9fca6d0: delete sign context   [ 58%]
tests/test_enc.py ........................                                                                                                             [ 67%]
```

Full test log: 
[test.log](https://github.com/xmlsec/python-xmlsec/files/10344622/test.log)

Could it be related to openssl 3.0 ?
Update: this test is expected to fail in debian bookworm, since libxmlsec1 in debian bookworm is also expecting this test to fail.
I ran into an issue with a signed document of this format, and it turns out the problem (at least in our case, and it might also be here), is that there is a spurious newline in the document at the end of the X509Certificate tag data (the close tag should be on the same line as the end of the data, not on the next line).  I have no idea what is triggering this change in generation, but if you remove the newline the document is properly handled.
> Could it be related to openssl 3.0 ?

I don't think so.

I've verified that the test passes if the extension is built against libxmlsec 1.2.34 or older, and fails with 1.2.36 and .37. I haven't been able to test 1.2.35 since it fails to build.

Fix patch:
diff --git a/.appveyor.yml b/.appveyor.yml
index de17f8ba..ce025819 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -16,6 +16,10 @@ environment:
     python_version: 3.10.6
   - python: 310-x64
     python_version: 3.10.6
+  - python: 311
+    python_version: 3.11.2
+  - python: 311-x64
+    python_version: 3.11.2
 
 install:
   - ps: |
diff --git a/.github/workflows/macosx.yml b/.github/workflows/macosx.yml
index 4db5e306..24fa6ddd 100644
--- a/.github/workflows/macosx.yml
+++ b/.github/workflows/macosx.yml
@@ -5,7 +5,7 @@ jobs:
     runs-on: macos-latest
     strategy:
       matrix:
-        python: [3.5, 3.6, 3.7, 3.8, 3.9, "3.10"]
+        python: [3.5, 3.6, 3.7, 3.8, 3.9, "3.10", "3.11"]
     steps:
       - uses: actions/checkout@v3
       - name: Setup Python
diff --git a/.github/workflows/manylinux.yml b/.github/workflows/manylinux.yml
index 867c17ba..520e5ba6 100644
--- a/.github/workflows/manylinux.yml
+++ b/.github/workflows/manylinux.yml
@@ -5,16 +5,16 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        python-abi: [cp36-cp36m, cp37-cp37m, cp38-cp38, cp39-cp39, cp310-cp310]
+        python-abi: [cp36-cp36m, cp37-cp37m, cp38-cp38, cp39-cp39, cp310-cp310, cp311-cp311]
         image:
           - manylinux2010_x86_64
           - manylinux_2_24_x86_64
           - musllinux_1_1_x86_64
         exclude:
           - image: manylinux2010_x86_64
-            python-abi: cp310-cp310
+            python-abi: cp311-cp311
           - image: manylinux2010_i686
-            python-abi: cp310-cp310
+            python-abi: cp311-cp311
     container: quay.io/pypa/${{ matrix.image }}
     steps:
       - uses: actions/checkout@v1
diff --git a/.github/workflows/opensuse-tumbleweed.yml b/.github/workflows/opensuse-tumbleweed.yml
index d8bb8113..273f7f7f 100644
--- a/.github/workflows/opensuse-tumbleweed.yml
+++ b/.github/workflows/opensuse-tumbleweed.yml
@@ -6,7 +6,7 @@ jobs:
     container: opensuse/tumbleweed
     strategy:
       matrix:
-        python-version: ["3.8", "3.9", "3.10"]
+        python-version: ["3.8", "3.9", "3.10", "3.11"]
     steps:
       - uses: actions/checkout@v1
       - name: Install build dependencies
diff --git a/.github/workflows/sdist.yml b/.github/workflows/sdist.yml
index fb13377a..d7959208 100644
--- a/.github/workflows/sdist.yml
+++ b/.github/workflows/sdist.yml
@@ -5,10 +5,10 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3
-      - name: Set up Python 3.10
+      - name: Set up Python 3.11
         uses: actions/setup-python@v4
         with:
-          python-version: "3.10"
+          python-version: "3.11"
       - name: Install build dependencies
         run: |
           pip install --upgrade pip setuptools wheel
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 0545b12f..6b8fdf67 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -31,7 +31,7 @@ repos:
         exclude: ^setup.py$
         additional_dependencies: [flake8-docstrings, flake8-bugbear, flake8-logging-format, flake8-builtins, flake8-eradicate, flake8-fixme, pep8-naming, flake8-pep3101, flake8-annotations-complexity,flake8-pyi]
 -   repo: https://github.com/PyCQA/isort
-    rev: 5.10.1
+    rev: 5.11.5
     hooks:
     -   id: isort
 -   repo: https://github.com/pre-commit/mirrors-mypy
diff --git a/.travis.yml b/.travis.yml
index 9106805a..9e6ca540 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,6 +16,9 @@ matrix:
   - python: 3.9
     dist: xenial
     sudo: required
+  - python: 3.11
+    dist: xenial
+    sudo: required
 env:
   global:
   - CFLAGS=-coverage
diff --git a/setup.py b/setup.py
index 9a3c9277..5c7e0da5 100644
--- a/setup.py
+++ b/setup.py
@@ -533,6 +533,7 @@ def prepare_static_build_linux(self):
         'Programming Language :: Python :: 3.7',
         'Programming Language :: Python :: 3.8',
         'Programming Language :: Python :: 3.9',
+        'Programming Language :: Python :: 3.11',
         'Topic :: Text Processing :: Markup :: XML',
         'Typing :: Typed',
     ],
diff --git a/src/main.c b/src/main.c
index ffcae14f..5773db3b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -119,6 +119,13 @@ static PyObject* PyXmlSec_PyShutdown(PyObject* self) {
     Py_RETURN_NONE;
 }
 
+static char PyXmlSec_GetLibXmlSecVersion__doc__[] = \
+    "get_libxmlsec_version() -> tuple\n"
+    "Returns Version tuple of wrapped libxml library.";
+static PyObject* PyXmlSec_GetLibXmlSecVersion() {
+    return Py_BuildValue("(iii)", XMLSEC_VERSION_MAJOR, XMLSEC_VERSION_MINOR, XMLSEC_VERSION_SUBMINOR);
+}
+
 static char PyXmlSec_PyEnableDebugOutput__doc__[] = \
     "enable_debug_trace(enabled) -> None\n"
     "Enables or disables calling LibXML2 callback from the default errors callback.\n\n"
@@ -386,6 +393,12 @@ static PyMethodDef PyXmlSec_MainMethods[] = {
         METH_NOARGS,
         PyXmlSec_PyShutdown__doc__
     },
+    {
+        "get_libxmlsec_version",
+        (PyCFunction)PyXmlSec_GetLibXmlSecVersion,
+        METH_NOARGS,
+        PyXmlSec_GetLibXmlSecVersion__doc__
+    },
     {
         "enable_debug_trace",
         (PyCFunction)PyXmlSec_PyEnableDebugOutput,


Test patch:
diff --git a/tests/data/sign5-out-xmlsec_1_2_36_to_37.xml b/tests/data/sign5-out-xmlsec_1_2_36_to_37.xml
new file mode 100644
index 00000000..f359b138
--- /dev/null
+++ b/tests/data/sign5-out-xmlsec_1_2_36_to_37.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: Signed XML doc file (sign5 example).
+-->
+<Envelope xmlns="urn:envelope">
+  <Data>
+	Hello, World!
+  </Data>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+<SignedInfo>
+<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+<Reference>
+<Transforms>
+<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+</Transforms>
+<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+<DigestValue>HjY8ilZAIEM2tBbPn5mYO1ieIX4=</DigestValue>
+</Reference>
+</SignedInfo>
+<SignatureValue>SIaj/6KY3C1SmDXU2++Gm31U1xTadFp04WhBgfsJFbxrL+q7GKSKN9kfQ+UpN9+i
+D5fWmuavXEHe4Gw6RMaMEkq2URQo7F68+d5J/ajq8/l4n+xE6/reGScVwT6L4dEP
+XXVJcAi2ZnQ3O7GTNvNGCPibL9mUcyCWBFZ92Uemtc/vJFCQ7ZyKMdMfACgxOwyN
+T/9971oog241/2doudhonc0I/3mgPYWkZdX6yvr62mEjnG+oUZkhWYJ4ewZJ4hM4
+JjbFqZO+OEzDRSbw3DkmuBA/mtlx+3t13SESfEub5hqoMdVmtth/eTb64dsPdl9r
+3k1ACVX9f8aHfQQdJOmLFQ==</SignatureValue>
+<KeyInfo>
+<X509Data>
+
+
+
+<X509IssuerSerial>
+<X509IssuerName>Test Issuer</X509IssuerName>
+<X509SerialNumber>1</X509SerialNumber>
+</X509IssuerSerial>
+<X509Certificate>MIIE3zCCBEigAwIBAgIBBTANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
+ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
+eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
+a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tMB4X
+DTAzMDMzMTA0MDIyMloXDTEzMDMyODA0MDIyMlowgb8xCzAJBgNVBAYTAlVTMRMw
+EQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFy
+eSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94bWxzZWMpMSEwHwYDVQQLExhFeGFt
+cGxlcyBSU0EgQ2VydGlmaWNhdGUxFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAf
+BgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAJe4/rQ/gzV4FokE7CthjL/EXwCBSkXm2c3p4jyXO0Wt
+quaNC3dxBwFPfPl94hmq3ZFZ9PHPPbp4RpYRnLZbRjlzVSOq954AXOXpSew7nD+E
+mTqQrd9+ZIbGJnLOMQh5fhMVuOW/1lYCjWAhTCcYZPv7VXD2M70vVXDVXn6ZrqTg
+qkVHE6gw1aCKncwg7OSOUclUxX8+Zi10v6N6+PPslFc5tKwAdWJhVLTQ4FKG+F53
+7FBDnNK6p4xiWryy/vPMYn4jYGvHUUk3eH4lFTCr+rSuJY8i/KNIf/IKim7g/o3w
+Ae3GM8xrof2mgO8GjK/2QDqOQhQgYRIf4/wFsQXVZcMCAwEAAaOCAVcwggFTMAkG
+A1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp
+ZmljYXRlMB0GA1UdDgQWBBQkhCzy1FkgYosuXIaQo6owuicanDCB+AYDVR0jBIHw
+MIHtgBS0ue+a5pcOaGUemM76VQ2JBttMfKGB0aSBzjCByzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
+ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
+eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
+a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tggEA
+MA0GCSqGSIb3DQEBBAUAA4GBALU/mzIxSv8vhDuomxFcplzwdlLZbvSQrfoNkMGY
+1UoS3YJrN+jZLWKSyWE3mIaPpElqXiXQGGkwD5iPQ1iJMbI7BeLvx6ZxX/f+c8Wn
+ss0uc1NxfahMaBoyG15IL4+beqO182fosaKJTrJNG3mc//ANGU9OsQM9mfBEt4oL
+NJ2D</X509Certificate>
+<X509SubjectName/>
+<X509SKI/>
+</X509Data>
+</KeyInfo>
+</Signature></Envelope>
diff --git a/tests/test_ds.py b/tests/test_ds.py
index 694ad431..38f0b25c 100644
--- a/tests/test_ds.py
+++ b/tests/test_ds.py
@@ -182,7 +182,11 @@ def test_sign_case5(self):
         self.assertEqual("rsakey.pem", ctx.key.name)
 
         ctx.sign(sign)
-        self.assertEqual(self.load_xml("sign5-out.xml"), root)
+        if (1, 2, 36) <= xmlsec.get_libxmlsec_version() <= (1, 2, 37):
+            expected_xml_file = 'sign5-out-xmlsec_1_2_36_to_37.xml'
+        else:
+            expected_xml_file = 'sign5-out.xml'
+        self.assertEqual(self.load_xml(expected_xml_file), root)
 
     def test_sign_binary_bad_args(self):
         ctx = xmlsec.SignatureContext()