signxml-references-modified 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- signxml/__init__.py +13 -0
- signxml/__pyinstaller/__init__.py +10 -0
- signxml/__pyinstaller/hook-signxml.py +5 -0
- signxml/algorithms.py +201 -0
- signxml/exceptions.py +35 -0
- signxml/processor.py +160 -0
- signxml/py.typed +0 -0
- signxml/schemas/__init__.py +0 -0
- signxml/schemas/xmldsig-core-schema.xsd +318 -0
- signxml/schemas/xmldsig1-schema.xsd +27 -0
- signxml/schemas/xmldsig11-schema.xsd +144 -0
- signxml/signer.py +470 -0
- signxml/util/__init__.py +297 -0
- signxml/verifier.py +628 -0
- signxml/xades/__init__.py +34 -0
- signxml/xades/schemas/XAdES.xsd +466 -0
- signxml/xades/schemas/XAdES01903v132-201506.xsd +537 -0
- signxml/xades/schemas/XAdES01903v132-201601.xsd +532 -0
- signxml/xades/schemas/XAdES01903v141-201506.xsd +53 -0
- signxml/xades/schemas/XAdES01903v141-201601.xsd +63 -0
- signxml/xades/schemas/XAdESv141.xsd +15 -0
- signxml/xades/schemas/__init__.py +0 -0
- signxml/xades/xades.py +378 -0
- signxml_references_modified-1.0.0.dist-info/LICENSE +201 -0
- signxml_references_modified-1.0.0.dist-info/METADATA +296 -0
- signxml_references_modified-1.0.0.dist-info/NOTICE +5 -0
- signxml_references_modified-1.0.0.dist-info/RECORD +30 -0
- signxml_references_modified-1.0.0.dist-info/WHEEL +5 -0
- signxml_references_modified-1.0.0.dist-info/entry_points.txt +3 -0
- signxml_references_modified-1.0.0.dist-info/top_level.txt +1 -0
signxml/__init__.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Use :class:`signxml.XMLSigner` and :class:`signxml.XMLVerifier` to sign and verify XML Signatures, respectively.
|
|
3
|
+
See `SignXML documentation <#synopsis>`_ for examples.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .signer import XMLSigner, SignatureReference
|
|
7
|
+
from .verifier import XMLVerifier, VerifyResult, SignatureConfiguration
|
|
8
|
+
from .algorithms import DigestAlgorithm, SignatureMethod, CanonicalizationMethod, SignatureConstructionMethod
|
|
9
|
+
from .exceptions import InvalidCertificate, InvalidDigest, InvalidInput, InvalidSignature
|
|
10
|
+
from .processor import XMLSignatureProcessor
|
|
11
|
+
from .util import namespaces
|
|
12
|
+
|
|
13
|
+
methods = SignatureConstructionMethod
|
signxml/algorithms.py
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Callable, Dict, Type, Union
|
|
3
|
+
|
|
4
|
+
from cryptography.hazmat.primitives import hashes
|
|
5
|
+
|
|
6
|
+
from .exceptions import InvalidInput
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SignatureConstructionMethod(Enum):
|
|
10
|
+
"""
|
|
11
|
+
An enumeration of signature construction methods supported by SignXML, used to specify the method when signing.
|
|
12
|
+
See the list of signature types under `XML Signature Syntax and Processing Version 2.0, Definitions
|
|
13
|
+
<http://www.w3.org/TR/xmldsig-core2/#sec-Definitions>`_.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
enveloped = "http://www.w3.org/2000/09/xmldsig#enveloped-signature"
|
|
17
|
+
"""
|
|
18
|
+
The signature is over the XML content that contains the signature as an element. The content provides the root
|
|
19
|
+
XML document element. This is the most common XML signature type in modern applications.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
enveloping = "enveloping-signature"
|
|
23
|
+
"""
|
|
24
|
+
The signature is over content found within an Object element of the signature itself. The Object (or its
|
|
25
|
+
content) is identified via a Reference (via a URI fragment identifier or transform).
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
detached = "detached-signature"
|
|
29
|
+
"""
|
|
30
|
+
The signature is over content external to the Signature element, and can be identified via a URI or
|
|
31
|
+
transform. Consequently, the signature is "detached" from the content it signs. This definition typically applies to
|
|
32
|
+
separate data objects, but it also includes the instance where the Signature and data object reside within the same
|
|
33
|
+
XML document but are sibling elements.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class FragmentLookupMixin:
|
|
38
|
+
@classmethod
|
|
39
|
+
def from_fragment(cls, fragment):
|
|
40
|
+
for i in cls: # type: ignore[attr-defined]
|
|
41
|
+
if i.value.endswith("#" + fragment):
|
|
42
|
+
return i
|
|
43
|
+
else:
|
|
44
|
+
raise InvalidInput(f"Unrecognized {cls.__name__} identifier fragment: {fragment}")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class InvalidInputErrorMixin:
|
|
48
|
+
@classmethod
|
|
49
|
+
def _missing_(cls, value):
|
|
50
|
+
raise InvalidInput(f"Unrecognized {cls.__name__}: {value}")
|
|
51
|
+
|
|
52
|
+
def __repr__(self):
|
|
53
|
+
return f"{self.__class__.__name__}.{self.name}" # type: ignore[attr-defined]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class DigestAlgorithm(FragmentLookupMixin, InvalidInputErrorMixin, Enum):
|
|
57
|
+
"""
|
|
58
|
+
An enumeration of digest algorithms supported by SignXML. See the
|
|
59
|
+
`Algorithm Identifiers and Implementation Requirements <http://www.w3.org/TR/xmldsig-core1/#sec-AlgID>`_ section of
|
|
60
|
+
the XML Signature 1.1 standard for details.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
SHA224 = "http://www.w3.org/2001/04/xmldsig-more#sha224"
|
|
64
|
+
SHA384 = "http://www.w3.org/2001/04/xmldsig-more#sha384"
|
|
65
|
+
SHA256 = "http://www.w3.org/2001/04/xmlenc#sha256"
|
|
66
|
+
SHA512 = "http://www.w3.org/2001/04/xmlenc#sha512"
|
|
67
|
+
SHA3_224 = "http://www.w3.org/2007/05/xmldsig-more#sha3-224"
|
|
68
|
+
SHA3_256 = "http://www.w3.org/2007/05/xmldsig-more#sha3-256"
|
|
69
|
+
SHA3_384 = "http://www.w3.org/2007/05/xmldsig-more#sha3-384"
|
|
70
|
+
SHA3_512 = "http://www.w3.org/2007/05/xmldsig-more#sha3-512"
|
|
71
|
+
|
|
72
|
+
SHA1 = "http://www.w3.org/2000/09/xmldsig#sha1"
|
|
73
|
+
"See `SHA1 deprecation`_."
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def implementation(self) -> Callable:
|
|
77
|
+
"""
|
|
78
|
+
The cryptography callable that implements the specified algorithm.
|
|
79
|
+
"""
|
|
80
|
+
return digest_algorithm_implementations[self]
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# TODO: check if padding errors are fixed by using padding=MGF1
|
|
84
|
+
class SignatureMethod(FragmentLookupMixin, InvalidInputErrorMixin, Enum):
|
|
85
|
+
"""
|
|
86
|
+
An enumeration of signature methods (also referred to as signature algorithms) supported by SignXML. See the
|
|
87
|
+
`Algorithm Identifiers and Implementation Requirements <http://www.w3.org/TR/xmldsig-core1/#sec-AlgID>`_ section of
|
|
88
|
+
the XML Signature 1.1 standard for details.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
|
|
92
|
+
"""
|
|
93
|
+
The RSASSA-PKCS1-v1_5 algorithm described in RFC 3447. This is the default, most widely supported signature method.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
RSA_SHA224 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha224"
|
|
97
|
+
RSA_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"
|
|
98
|
+
RSA_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"
|
|
99
|
+
ECDSA_SHA224 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha224"
|
|
100
|
+
ECDSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"
|
|
101
|
+
ECDSA_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384"
|
|
102
|
+
ECDSA_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"
|
|
103
|
+
ECDSA_SHA3_224 = "http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-224"
|
|
104
|
+
ECDSA_SHA3_256 = "http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-256"
|
|
105
|
+
ECDSA_SHA3_384 = "http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-384"
|
|
106
|
+
ECDSA_SHA3_512 = "http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-512"
|
|
107
|
+
DSA_SHA256 = "http://www.w3.org/2009/xmldsig11#dsa-sha256"
|
|
108
|
+
HMAC_SHA224 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha224"
|
|
109
|
+
HMAC_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256"
|
|
110
|
+
HMAC_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384"
|
|
111
|
+
HMAC_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha512"
|
|
112
|
+
SHA3_224_RSA_MGF1 = "http://www.w3.org/2007/05/xmldsig-more#sha3-224-rsa-MGF1"
|
|
113
|
+
SHA3_256_RSA_MGF1 = "http://www.w3.org/2007/05/xmldsig-more#sha3-256-rsa-MGF1"
|
|
114
|
+
SHA3_384_RSA_MGF1 = "http://www.w3.org/2007/05/xmldsig-more#sha3-384-rsa-MGF1"
|
|
115
|
+
SHA3_512_RSA_MGF1 = "http://www.w3.org/2007/05/xmldsig-more#sha3-512-rsa-MGF1"
|
|
116
|
+
SHA224_RSA_MGF1 = "http://www.w3.org/2007/05/xmldsig-more#sha224-rsa-MGF1"
|
|
117
|
+
SHA256_RSA_MGF1 = "http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1"
|
|
118
|
+
SHA384_RSA_MGF1 = "http://www.w3.org/2007/05/xmldsig-more#sha384-rsa-MGF1"
|
|
119
|
+
SHA512_RSA_MGF1 = "http://www.w3.org/2007/05/xmldsig-more#sha512-rsa-MGF1"
|
|
120
|
+
|
|
121
|
+
DSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#dsa-sha1"
|
|
122
|
+
"""
|
|
123
|
+
_`SHA1 deprecation`: SHA1 based algorithms are not secure for use in digital signatures. They are included for
|
|
124
|
+
legacy compatibility only and disabled by default. To verify SHA1 based signatures, use::
|
|
125
|
+
|
|
126
|
+
XMLVerifier().verify(
|
|
127
|
+
expect_config=SignatureConfiguration(
|
|
128
|
+
signature_methods=...,
|
|
129
|
+
digest_algorithms=...
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
"""
|
|
133
|
+
HMAC_SHA1 = "http://www.w3.org/2000/09/xmldsig#hmac-sha1"
|
|
134
|
+
"See `SHA1 deprecation`_."
|
|
135
|
+
RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
|
|
136
|
+
"See `SHA1 deprecation`_."
|
|
137
|
+
ECDSA_SHA1 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"
|
|
138
|
+
"See `SHA1 deprecation`_."
|
|
139
|
+
SHA1_RSA_MGF1 = "http://www.w3.org/2007/05/xmldsig-more#sha1-rsa-MGF1"
|
|
140
|
+
"See `SHA1 deprecation`_."
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class CanonicalizationMethod(InvalidInputErrorMixin, Enum):
|
|
144
|
+
"""
|
|
145
|
+
An enumeration of XML canonicalization methods (also referred to as canonicalization algorithms) supported by
|
|
146
|
+
SignXML. See the `Algorithm Identifiers and Implementation Requirements
|
|
147
|
+
<http://www.w3.org/TR/xmldsig-core1/#sec-AlgID>`_ section of the XML Signature 1.1 standard for details.
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
CANONICAL_XML_1_0 = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
|
|
151
|
+
CANONICAL_XML_1_0_WITH_COMMENTS = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"
|
|
152
|
+
CANONICAL_XML_1_1 = "http://www.w3.org/2006/12/xml-c14n11"
|
|
153
|
+
CANONICAL_XML_1_1_WITH_COMMENTS = "http://www.w3.org/2006/12/xml-c14n11#WithComments"
|
|
154
|
+
EXCLUSIVE_XML_CANONICALIZATION_1_0 = "http://www.w3.org/2001/10/xml-exc-c14n#"
|
|
155
|
+
EXCLUSIVE_XML_CANONICALIZATION_1_0_WITH_COMMENTS = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments"
|
|
156
|
+
|
|
157
|
+
# The identifier for Canonical XML 2.0 is "http://www.w3.org/2010/xml-c14n2", but it is not a W3C standard.
|
|
158
|
+
# While it is supported by lxml, it's not in general use and not supported by SignXML
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
digest_algorithm_implementations: Dict[Union[DigestAlgorithm, SignatureMethod], Type[hashes.HashAlgorithm]] = {
|
|
162
|
+
DigestAlgorithm.SHA1: hashes.SHA1,
|
|
163
|
+
DigestAlgorithm.SHA224: hashes.SHA224,
|
|
164
|
+
DigestAlgorithm.SHA384: hashes.SHA384,
|
|
165
|
+
DigestAlgorithm.SHA256: hashes.SHA256,
|
|
166
|
+
DigestAlgorithm.SHA512: hashes.SHA512,
|
|
167
|
+
DigestAlgorithm.SHA3_224: hashes.SHA3_224,
|
|
168
|
+
DigestAlgorithm.SHA3_256: hashes.SHA3_256,
|
|
169
|
+
DigestAlgorithm.SHA3_384: hashes.SHA3_384,
|
|
170
|
+
DigestAlgorithm.SHA3_512: hashes.SHA3_512,
|
|
171
|
+
SignatureMethod.DSA_SHA1: hashes.SHA1,
|
|
172
|
+
SignatureMethod.HMAC_SHA1: hashes.SHA1,
|
|
173
|
+
SignatureMethod.RSA_SHA1: hashes.SHA1,
|
|
174
|
+
SignatureMethod.ECDSA_SHA1: hashes.SHA1,
|
|
175
|
+
SignatureMethod.ECDSA_SHA224: hashes.SHA224,
|
|
176
|
+
SignatureMethod.ECDSA_SHA256: hashes.SHA256,
|
|
177
|
+
SignatureMethod.ECDSA_SHA384: hashes.SHA384,
|
|
178
|
+
SignatureMethod.ECDSA_SHA512: hashes.SHA512,
|
|
179
|
+
SignatureMethod.HMAC_SHA224: hashes.SHA224,
|
|
180
|
+
SignatureMethod.HMAC_SHA256: hashes.SHA256,
|
|
181
|
+
SignatureMethod.HMAC_SHA384: hashes.SHA384,
|
|
182
|
+
SignatureMethod.HMAC_SHA512: hashes.SHA512,
|
|
183
|
+
SignatureMethod.RSA_SHA224: hashes.SHA224,
|
|
184
|
+
SignatureMethod.RSA_SHA256: hashes.SHA256,
|
|
185
|
+
SignatureMethod.RSA_SHA384: hashes.SHA384,
|
|
186
|
+
SignatureMethod.RSA_SHA512: hashes.SHA512,
|
|
187
|
+
SignatureMethod.DSA_SHA256: hashes.SHA256,
|
|
188
|
+
SignatureMethod.ECDSA_SHA3_224: hashes.SHA3_224,
|
|
189
|
+
SignatureMethod.ECDSA_SHA3_256: hashes.SHA3_256,
|
|
190
|
+
SignatureMethod.ECDSA_SHA3_384: hashes.SHA3_384,
|
|
191
|
+
SignatureMethod.ECDSA_SHA3_512: hashes.SHA3_512,
|
|
192
|
+
SignatureMethod.SHA3_224_RSA_MGF1: hashes.SHA3_224,
|
|
193
|
+
SignatureMethod.SHA3_256_RSA_MGF1: hashes.SHA3_256,
|
|
194
|
+
SignatureMethod.SHA3_384_RSA_MGF1: hashes.SHA3_384,
|
|
195
|
+
SignatureMethod.SHA3_512_RSA_MGF1: hashes.SHA3_512,
|
|
196
|
+
SignatureMethod.SHA224_RSA_MGF1: hashes.SHA224,
|
|
197
|
+
SignatureMethod.SHA256_RSA_MGF1: hashes.SHA256,
|
|
198
|
+
SignatureMethod.SHA384_RSA_MGF1: hashes.SHA384,
|
|
199
|
+
SignatureMethod.SHA512_RSA_MGF1: hashes.SHA512,
|
|
200
|
+
SignatureMethod.SHA1_RSA_MGF1: hashes.SHA1,
|
|
201
|
+
}
|
signxml/exceptions.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SignXML exception types.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import cryptography.exceptions
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SignXMLException(Exception):
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class InvalidSignature(cryptography.exceptions.InvalidSignature, SignXMLException):
|
|
13
|
+
"""
|
|
14
|
+
Raised when signature validation fails.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class InvalidDigest(InvalidSignature):
|
|
19
|
+
"""
|
|
20
|
+
Raised when digest validation fails (causing the signature to be untrusted).
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class InvalidCertificate(InvalidSignature):
|
|
25
|
+
"""
|
|
26
|
+
Raised when certificate validation fails.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class InvalidInput(ValueError, SignXMLException):
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class RedundantCert(SignXMLException):
|
|
35
|
+
pass
|
signxml/processor.py
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
from typing import Any, List, Tuple
|
|
4
|
+
from xml.etree import ElementTree as stdlibElementTree
|
|
5
|
+
|
|
6
|
+
from cryptography.hazmat.primitives.asymmetric import ec
|
|
7
|
+
from cryptography.hazmat.primitives.hashes import Hash
|
|
8
|
+
from lxml import etree
|
|
9
|
+
|
|
10
|
+
from .algorithms import CanonicalizationMethod, DigestAlgorithm, digest_algorithm_implementations
|
|
11
|
+
from .exceptions import InvalidInput
|
|
12
|
+
from .util import namespaces
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class XMLProcessor:
|
|
18
|
+
_schemas: List[Any] = []
|
|
19
|
+
schema_files: List[Any] = []
|
|
20
|
+
_default_parser, _parser = None, None
|
|
21
|
+
_schema_dir = os.path.normpath(os.path.join(os.path.dirname(__file__), "schemas"))
|
|
22
|
+
|
|
23
|
+
@classmethod
|
|
24
|
+
def schemas(cls):
|
|
25
|
+
if len(cls._schemas) == 0:
|
|
26
|
+
for schema_file in cls.schema_files:
|
|
27
|
+
schema_path = os.path.join(cls._schema_dir, schema_file)
|
|
28
|
+
cls._schemas.append(etree.XMLSchema(etree.parse(schema_path)))
|
|
29
|
+
return cls._schemas
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def parser(self):
|
|
33
|
+
if self._parser is None:
|
|
34
|
+
if self._default_parser is None:
|
|
35
|
+
self._default_parser = etree.XMLParser(resolve_entities=False)
|
|
36
|
+
return self._default_parser
|
|
37
|
+
return self._parser
|
|
38
|
+
|
|
39
|
+
def _fromstring(self, xml_string, **kwargs):
|
|
40
|
+
xml_node = etree.fromstring(xml_string, parser=self.parser, **kwargs)
|
|
41
|
+
for entity in xml_node.iter(etree.Entity):
|
|
42
|
+
raise InvalidInput("Entities are not supported in XML input")
|
|
43
|
+
return xml_node
|
|
44
|
+
|
|
45
|
+
def _tostring(self, xml_node, **kwargs):
|
|
46
|
+
return etree.tostring(xml_node, **kwargs)
|
|
47
|
+
|
|
48
|
+
def get_root(self, data):
|
|
49
|
+
if isinstance(data, (str, bytes)):
|
|
50
|
+
return self._fromstring(data)
|
|
51
|
+
elif isinstance(data, stdlibElementTree.Element):
|
|
52
|
+
# TODO: add debug level logging statement re: performance impact here
|
|
53
|
+
return self._fromstring(stdlibElementTree.tostring(data, encoding="utf-8"))
|
|
54
|
+
else:
|
|
55
|
+
# Create a separate copy of the node so we can modify the tree and avoid any c14n inconsistencies from
|
|
56
|
+
# namespaces propagating from parent nodes. The lxml docs recommend using copy.deepcopy for this, but it
|
|
57
|
+
# doesn't seem to preserve namespaces. It would be nice to find a less heavy-handed way of doing this.
|
|
58
|
+
return self._fromstring(self._tostring(data))
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class XMLSignatureProcessor(XMLProcessor):
|
|
62
|
+
schema_files = ["xmldsig1-schema.xsd"]
|
|
63
|
+
|
|
64
|
+
# See https://tools.ietf.org/html/rfc5656
|
|
65
|
+
known_ecdsa_curves = {
|
|
66
|
+
"urn:oid:1.2.840.10045.3.1.7": ec.SECP256R1,
|
|
67
|
+
"urn:oid:1.3.132.0.34": ec.SECP384R1,
|
|
68
|
+
"urn:oid:1.3.132.0.35": ec.SECP521R1,
|
|
69
|
+
"urn:oid:1.3.132.0.1": ec.SECT163K1,
|
|
70
|
+
"urn:oid:1.2.840.10045.3.1.1": ec.SECP192R1,
|
|
71
|
+
"urn:oid:1.3.132.0.33": ec.SECP224R1,
|
|
72
|
+
"urn:oid:1.3.132.0.26": ec.SECT233K1,
|
|
73
|
+
"urn:oid:1.3.132.0.27": ec.SECT233R1,
|
|
74
|
+
"urn:oid:1.3.132.0.16": ec.SECT283R1,
|
|
75
|
+
"urn:oid:1.3.132.0.36": ec.SECT409K1,
|
|
76
|
+
"urn:oid:1.3.132.0.37": ec.SECT409R1,
|
|
77
|
+
"urn:oid:1.3.132.0.38": ec.SECT571K1,
|
|
78
|
+
}
|
|
79
|
+
known_ecdsa_curve_oids = {ec().name: oid for oid, ec in known_ecdsa_curves.items()} # type: ignore[abstract]
|
|
80
|
+
|
|
81
|
+
excise_empty_xmlns_declarations = False
|
|
82
|
+
|
|
83
|
+
id_attributes: Tuple[str, ...] = ("Id", "ID", "id", "xml:id")
|
|
84
|
+
|
|
85
|
+
def _get_digest(self, data, algorithm: DigestAlgorithm):
|
|
86
|
+
algorithm_implementation = digest_algorithm_implementations[algorithm]()
|
|
87
|
+
hasher = Hash(algorithm=algorithm_implementation)
|
|
88
|
+
hasher.update(data)
|
|
89
|
+
return hasher.finalize()
|
|
90
|
+
|
|
91
|
+
def _find(self, element, query, require=True, xpath=""):
|
|
92
|
+
namespace = "ds"
|
|
93
|
+
if ":" in query:
|
|
94
|
+
namespace, _, query = query.partition(":")
|
|
95
|
+
result = element.find(f"{xpath}{namespace}:{query}", namespaces=namespaces)
|
|
96
|
+
|
|
97
|
+
if require and result is None:
|
|
98
|
+
raise InvalidInput(f"Expected to find XML element {query} in {element.tag}")
|
|
99
|
+
return result
|
|
100
|
+
|
|
101
|
+
def _findall(self, element, query, xpath=""):
|
|
102
|
+
namespace = "ds"
|
|
103
|
+
if ":" in query:
|
|
104
|
+
namespace, _, query = query.partition(":")
|
|
105
|
+
return element.findall(f"{xpath}{namespace}:{query}", namespaces=namespaces)
|
|
106
|
+
|
|
107
|
+
def _c14n(self, nodes, algorithm: CanonicalizationMethod, inclusive_ns_prefixes=None):
|
|
108
|
+
exclusive, with_comments = False, False
|
|
109
|
+
|
|
110
|
+
if algorithm.value.startswith("http://www.w3.org/2001/10/xml-exc-c14n#"):
|
|
111
|
+
exclusive = True
|
|
112
|
+
if algorithm.value.endswith("#WithComments"):
|
|
113
|
+
with_comments = True
|
|
114
|
+
|
|
115
|
+
if not isinstance(nodes, list):
|
|
116
|
+
nodes = [nodes]
|
|
117
|
+
|
|
118
|
+
c14n = b""
|
|
119
|
+
for node in nodes:
|
|
120
|
+
c14n += etree.tostring(
|
|
121
|
+
node,
|
|
122
|
+
method="c14n",
|
|
123
|
+
exclusive=exclusive,
|
|
124
|
+
with_comments=with_comments,
|
|
125
|
+
inclusive_ns_prefixes=inclusive_ns_prefixes,
|
|
126
|
+
)
|
|
127
|
+
if exclusive is False and self.excise_empty_xmlns_declarations is True:
|
|
128
|
+
# Incorrect legacy behavior. See also:
|
|
129
|
+
# - https://github.com/XML-Security/signxml/issues/193
|
|
130
|
+
# - http://www.w3.org/TR/xml-c14n, "namespace axis"
|
|
131
|
+
# - http://www.w3.org/TR/xml-c14n2/#sec-Namespace-Processing
|
|
132
|
+
c14n = c14n.replace(b' xmlns=""', b"")
|
|
133
|
+
logger.debug("Canonicalized string (exclusive=%s, with_comments=%s): %s", exclusive, with_comments, c14n)
|
|
134
|
+
return c14n
|
|
135
|
+
|
|
136
|
+
def _resolve_reference(self, doc_root, reference, uri_resolver=None):
|
|
137
|
+
uri = reference.get("URI")
|
|
138
|
+
if uri is None:
|
|
139
|
+
raise InvalidInput("References without URIs are not supported")
|
|
140
|
+
elif uri == "":
|
|
141
|
+
return doc_root
|
|
142
|
+
elif uri.startswith("#xpointer("):
|
|
143
|
+
raise InvalidInput("XPointer references are not supported")
|
|
144
|
+
# doc_root.xpath(uri.lstrip("#"))[0]
|
|
145
|
+
elif uri.startswith("#"):
|
|
146
|
+
for id_attribute in self.id_attributes:
|
|
147
|
+
xpath_query = f"//*[@*[local-name() = '{id_attribute}']=$uri]"
|
|
148
|
+
results = doc_root.xpath(xpath_query, uri=uri.lstrip("#"))
|
|
149
|
+
if len(results) > 1:
|
|
150
|
+
raise InvalidInput(f"Ambiguous reference URI {uri} resolved to {len(results)} nodes")
|
|
151
|
+
elif len(results) == 1:
|
|
152
|
+
return results[0]
|
|
153
|
+
raise InvalidInput(f"Unable to resolve reference URI: {uri}")
|
|
154
|
+
else:
|
|
155
|
+
if uri_resolver is None:
|
|
156
|
+
raise InvalidInput(f"External URI dereferencing is not configured: {uri}")
|
|
157
|
+
result = uri_resolver(uri)
|
|
158
|
+
if result is None:
|
|
159
|
+
raise InvalidInput(f"Unable to resolve reference URI: {uri}")
|
|
160
|
+
return result
|
signxml/py.typed
ADDED
|
File without changes
|
|
File without changes
|