Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-signxml for openSUSE:Factory checked in at 2026-03-04 21:08:25 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-signxml (Old) and /work/SRC/openSUSE:Factory/.python-signxml.new.561 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-signxml" Wed Mar 4 21:08:25 2026 rev:3 rq:1336215 version:4.4.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-signxml/python-signxml.changes 2026-02-17 16:47:35.864057753 +0100 +++ /work/SRC/openSUSE:Factory/.python-signxml.new.561/python-signxml.changes 2026-03-04 21:09:02.709938301 +0100 @@ -1,0 +2,8 @@ +Tue Mar 3 20:50:27 UTC 2026 - Dirk Müller <[email protected]> + +- update to 4.4.0: + * Forbid DTD declarations in XML input + * Avoid deprecated method importlib.resources.open_text + * Fix comparison logic for ECDSA public keys + +------------------------------------------------------------------- Old: ---- signxml-4.3.0.tar.gz New: ---- signxml-4.4.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-signxml.spec ++++++ --- /var/tmp/diff_new_pack.47TVsl/_old 2026-03-04 21:09:04.698020466 +0100 +++ /var/tmp/diff_new_pack.47TVsl/_new 2026-03-04 21:09:04.702020632 +0100 @@ -17,7 +17,7 @@ Name: python-signxml -Version: 4.3.0 +Version: 4.4.0 Release: 0 Summary: Python XML Signature and XAdES library License: Apache-2.0 ++++++ signxml-4.3.0.tar.gz -> signxml-4.4.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/signxml-4.3.0/Changes.rst new/signxml-4.4.0/Changes.rst --- old/signxml-4.3.0/Changes.rst 2020-02-02 01:00:00.000000000 +0100 +++ new/signxml-4.4.0/Changes.rst 2020-02-02 01:00:00.000000000 +0100 @@ -1,3 +1,15 @@ +Changes for v4.4.0 (2026-03-01) +=============================== + +- Forbid DTD declarations in XML input + +- Avoid deprecated method importlib.resources.open_text + +Changes for v4.3.1 (2026-02-17) +=============================== + +- Fix comparison logic for ECDSA public keys (#290) + Changes for v4.3.0 (2026-02-14) =============================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/signxml-4.3.0/PKG-INFO new/signxml-4.4.0/PKG-INFO --- old/signxml-4.3.0/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 +++ new/signxml-4.4.0/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: signxml -Version: 4.3.0 +Version: 4.4.0 Summary: Python XML Signature and XAdES library Project-URL: Homepage, https://github.com/XML-Security/signxml Project-URL: Documentation, https://xml-security.github.io/signxml/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/signxml-4.3.0/signxml/processor.py new/signxml-4.4.0/signxml/processor.py --- old/signxml-4.3.0/signxml/processor.py 2020-02-02 01:00:00.000000000 +0100 +++ new/signxml-4.4.0/signxml/processor.py 2020-02-02 01:00:00.000000000 +0100 @@ -19,7 +19,9 @@ @lru_cache def get_schema(schema_file: str) -> etree.XMLSchema: pkg_name = "signxml.xades.schemas" if schema_file.startswith("XAdES") else "signxml.schemas" - with importlib.resources.open_text(pkg_name, schema_file) as schema_fh: + + pkg_resources = importlib.resources.files(pkg_name) + with pkg_resources.joinpath(schema_file).open("r") as schema_fh: return etree.XMLSchema(etree.parse(schema_fh)) @@ -46,6 +48,9 @@ def _fromstring(self, xml_string, **kwargs): xml_node = etree.fromstring(xml_string, parser=self.parser, **kwargs) + docinfo = etree.ElementTree(xml_node).docinfo + if docinfo.internalDTD is not None or docinfo.externalDTD is not None: + raise InvalidInput("DTD declarations are not supported in XML input") for entity in xml_node.iter(etree.Entity): raise InvalidInput("Entities are not supported in XML input") return xml_node diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/signxml-4.3.0/signxml/verifier.py new/signxml-4.4.0/signxml/verifier.py --- old/signxml-4.3.0/signxml/verifier.py 2020-02-02 01:00:00.000000000 +0100 +++ new/signxml-4.4.0/signxml/verifier.py 2020-02-02 01:00:00.000000000 +0100 @@ -608,7 +608,7 @@ pubk_x = public_key.public_numbers().x pubk_y = public_key.public_numbers().y - return curve_class == pubk_curve and x == pubk_x and y == pubk_y + return isinstance(pubk_curve, curve_class) and x == pubk_x and y == pubk_y elif signature_alg.name.startswith("DSA_") and isinstance(public_key, dsa.DSAPublicKey): dsa_key_value = self._find(key_value, "DSAKeyValue") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/signxml-4.3.0/test/example_ecdsa.key new/signxml-4.4.0/test/example_ecdsa.key --- old/signxml-4.3.0/test/example_ecdsa.key 1970-01-01 01:00:00.000000000 +0100 +++ new/signxml-4.4.0/test/example_ecdsa.key 2020-02-02 01:00:00.000000000 +0100 @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDBY6FeFQmM2GbPnlVzZqhKdY4M77y8oQiF7lpI837SY8t0KEvO/qTy7 +KtFvawNG3uigBwYFK4EEACKhZANiAASuGz3ikMmN6M9rJiA+xgSce0Ax2+dm5sXI +nwSU52PnPecZHFx/GtpYNVJwKqJwMdXYlH/0tn9OtDXajxy0hY2aM0wVgaNsH9aP +K4pj8Ayl/MYJY3VK//+ei/L206px7cg= +-----END EC PRIVATE KEY----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/signxml-4.3.0/test/example_ecdsa.pem new/signxml-4.4.0/test/example_ecdsa.pem --- old/signxml-4.3.0/test/example_ecdsa.pem 1970-01-01 01:00:00.000000000 +0100 +++ new/signxml-4.4.0/test/example_ecdsa.pem 2020-02-02 01:00:00.000000000 +0100 @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBuzCCAUKgAwIBAgIUehXk0nzJ2sctfSmR9j5MNb7M3NIwCgYIKoZIzj0EAwMw +FTETMBEGA1UEAwwKRUNEU0EgdGVzdDAeFw0yNjAyMTgwMDIyMDBaFw0zNjAyMTYw +MDIyMDBaMBUxEzARBgNVBAMMCkVDRFNBIHRlc3QwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAASuGz3ikMmN6M9rJiA+xgSce0Ax2+dm5sXInwSU52PnPecZHFx/GtpYNVJw +KqJwMdXYlH/0tn9OtDXajxy0hY2aM0wVgaNsH9aPK4pj8Ayl/MYJY3VK//+ei/L2 +06px7cijUzBRMB0GA1UdDgQWBBR4PRv1xxITznx4G7kQaTISLUkeZDAfBgNVHSME +GDAWgBR4PRv1xxITznx4G7kQaTISLUkeZDAPBgNVHRMBAf8EBTADAQH/MAoGCCqG +SM49BAMDA2cAMGQCMBQ0OrujEmk+6faCzG01aXg69619rJcDIJpDaIEU8Wyi69Lc +gx1IDQR7GqqTUhl9yAIwUujG00FtgMZ8bfNtz5qRenS4YL1lZDtuAFF2rqfIh1j8 +IeFHdpTkFJPO41N4Dpwe +-----END CERTIFICATE----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/signxml-4.3.0/test/test.py new/signxml-4.4.0/test/test.py --- old/signxml-4.3.0/test/test.py 2020-02-02 01:00:00.000000000 +0100 +++ new/signxml-4.4.0/test/test.py 2020-02-02 01:00:00.000000000 +0100 @@ -99,6 +99,13 @@ key = fh.read() return crt, key + def load_example_ecdsa_keys(self): + with open(os.path.join(os.path.dirname(__file__), "example_ecdsa.pem"), "rb") as fh: + crt = fh.read() + with open(os.path.join(os.path.dirname(__file__), "example_ecdsa.key"), "rb") as fh: + key = fh.read() + return crt, key + class TestVerifyXML(unittest.TestCase, LoadExampleKeys): def test_example_multi(self): @@ -648,6 +655,31 @@ def test_excision_of_untrusted_comments(self): pass # TODO: test comments excision + def test_doctype_rejection(self): + doc = """<!DOCTYPE samlp:Response [<!ATTLIST saml:Assertion xmlns:saml CDATA "urn:oasis:names:tc:SAML:2.0:assertion">]><samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:Assertion"><saml:Assertion Version="2.0" ID="_test"> + <saml:Subject><saml:NameID>[email protected]</saml:NameID></saml:Subject> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><ds:Reference URI="#_test"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>qMAYPT7tK9U5s0OuDLgiY7t3uXBgXxmM8doM849sH2g=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>VfrFy9IakkV48zDp0NJxdueUPG8Ec9II0I9InWHDaQzIlNm+F8fwdvYU6JEoXoIKHv3Bj8beE9qcNh03xzL/l7DVtKV31YQc0+cylp/5YvkZBZHza643tKKPIXag3tR6Zo/wR+X+e1YuDlbb1oAOcl85Ob9ZPmW7wnVqu27kGratcYbU2vHh4jbYua3ZkPyUajwbw8O5R/LLIg3uko1oWdQxWnmNM9zoxLT3V5O7rYPp/gwvebhYTX6tnxkKrHK7CsslEINRbEDCXbpc0gT9TuADSP/aHrQmFN8eLXahpyBygYnNIdbil4usKfdcf2L13x03OkWiLdhvqMbOQZOV0g==</ ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIC/zCCAeegAwIBAgIUZd6NULqQQPpHUImmpZ5d8KO0meYwDQYJKoZIhvcNAQEL + BQAwDzENMAsGA1UEAwwEdGVzdDAeFw0yNjAzMDExNzExNTlaFw0yNjAzMDIxNzEx + NTlaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK + AoIBAQDAyHLFxknSg8igmRlNJwSnZ1HzRtaqmLb6THv2cyNdGspvce6LmfOE/0dz + KEqh7XVhvK3pMfsDi0NEjddyENA+IRZIcjQinBaG6d1+k/LmJybO+SBtopKbOMi2 + EsjlTbcOj/TzvEkdSJukHvZWd/AfUJcl7YWHTYCeevtad/ko454AfS6fGSWg4HXd + 7s6SI/RlcDW3VAzY19C6bIX8GPVW5aZZg0Dihe2QW1ghN5n/6Etp9No2zooBdV1f + zq79xvECUdTSwGEvEZz92sxjFnOJKVFZetDuE+BylpYxnc7akiPQZbhHCeiTheiL + yiDE2BVp6q2zxXuhNjbkXvVLI0qtAgMBAAGjUzBRMB0GA1UdDgQWBBQcgXR3Y2y/ + jjlgm1DyvNLu/+NN4TAfBgNVHSMEGDAWgBQcgXR3Y2y/jjlgm1DyvNLu/+NN4TAP + BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQATqMPgzLiUaxJBBvKa + +TyUTiH/ZFjGY3eYEWxbjzaBvRll8r09rd8roORdPr299EKKfDMn4N9l9X+nYvAY + //sJ+NO54yO6uiWW6ScOqq9igj5Q6bnNgvuz/5PBai/i/sb8cFKHzY+TEIRnRMBb + 8LAynzKgh9IXyTvjeBCiIT06C0nP4tKIygIoXcESBzzLjOO9rxG9nLqznZYfUKMT + 4h8Lh2DO5VeLsZawPsR9VU99MjrYsMrcHPXdW42KUTY7IpjBcd69xI6lhwTOqOV0 + TStby5C4JWMZtMpJPwBJjczYSBsxx91OTDzMhQuEqH4WiCOcrBtqLjT7DSj6kAHx + ea+x + </ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></saml:Assertion></samlp:Response>""" + + with self.assertRaises(InvalidInput): + XMLVerifier().verify(doc) + def test_mismatched_key_value_with_x509_data(self): crt, key = self.load_example_keys() data = etree.parse(os.path.join(os.path.dirname(__file__), "example.xml")).getroot() @@ -668,6 +700,39 @@ XMLVerifier().verify(signed_xml, x509_cert=crt, ignore_ambiguous_key_info=True) + def test_mismatched_ecdsa_key_value_with_x509_data(self): + crt, key = self.load_example_ecdsa_keys() + data = etree.parse(os.path.join(os.path.dirname(__file__), "example.xml")).getroot() + signer = XMLSigner( + signature_algorithm=SignatureMethod.ECDSA_SHA384, + ) + signed = signer.sign(data, key=key, cert=crt, always_add_key_value=True) + key_info = signed.find(".//ds:KeyInfo", namespaces=namespaces) + key_value = key_info.find("ds:KeyValue", namespaces=namespaces) + key_info.remove(key_value) + mismatched_key = ec.generate_private_key(curve=ec.SECP384R1()) + signer._serialize_key_value(mismatched_key, key_info) + signed_xml = etree.tostring(signed) + + with self.assertRaisesRegex( + InvalidInput, + "Both X509Data and KeyValue found and they represent different public keys", + ): + XMLVerifier().verify(signed_xml, x509_cert=crt) + + XMLVerifier().verify(signed_xml, x509_cert=crt, ignore_ambiguous_key_info=True) + + def test_matched_ecdsa_key_value_with_x509_data(self): + crt, key = self.load_example_ecdsa_keys() + data = etree.parse(os.path.join(os.path.dirname(__file__), "example.xml")).getroot() + signer = XMLSigner( + signature_algorithm=SignatureMethod.ECDSA_SHA384, + ) + signed = signer.sign(data, key=key, cert=crt, always_add_key_value=True) + signed_xml = etree.tostring(signed) + + XMLVerifier().verify(signed_xml, x509_cert=crt, ignore_ambiguous_key_info=False) + def test_ws_security(self): wsse_dir = os.path.join(interop_dir, "ws-security", "ws.js") with open(os.path.join(wsse_dir, "examples", "server_public.pem"), "rb") as fh:
