Skip to content

Commit a191049

Browse files
committed
Support inclusive_ns_prefixes when signing
1 parent 29966f8 commit a191049

File tree

1 file changed

+27
-8
lines changed

1 file changed

+27
-8
lines changed

signxml/__init__.py

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ def ds_tag(tag):
3636
def dsig11_tag(tag):
3737
return "{" + namespaces.dsig11 + "}" + tag
3838

39+
def ec_tag(tag):
40+
return "{" + namespaces.ec + "}" + tag
41+
3942
def _remove_sig(signature, idempotent=False):
4043
"""
4144
Remove the signature node from its parent, keeping any tail element.
@@ -281,7 +284,8 @@ def __init__(self, method=methods.enveloped, signature_algorithm="rsa-sha256", d
281284
self._parser = None
282285

283286
def sign(self, data, key=None, passphrase=None, cert=None, reference_uri=None, key_name=None, key_info=None,
284-
id_attribute=None, always_add_key_value=False):
287+
id_attribute=None, always_add_key_value=False, payload_inclusive_ns_prefixes=frozenset(),
288+
signature_inclusive_ns_prefixes=frozenset()):
285289
"""
286290
Sign the data and return the root element of the resulting XML tree.
287291
@@ -328,6 +332,14 @@ def sign(self, data, key=None, passphrase=None, cert=None, reference_uri=None, k
328332
KeyValue or make sure it matches what's in the certificate. This parameter is provided for compatibility
329333
purposes only.
330334
:type always_add_key_value: boolean
335+
:param payload_inclusive_ns_prefixes:
336+
Provide a list of XML namespace prefixes whose declarations should be preserved when canonicalizing the
337+
content referenced by the signature (**InclusiveNamespaces PrefixList**).
338+
:type inclusive_ns_prefixes: string
339+
:param signature_inclusive_ns_prefixes:
340+
Provide a list of XML namespace prefixes whose declarations should be preserved when canonicalizing the
341+
signature itself (**InclusiveNamespaces PrefixList**).
342+
:type inclusive_ns_prefixes: string
331343
332344
:returns:
333345
A :py:class:`lxml.etree.Element` object representing the root of the XML tree containing the signature and
@@ -352,12 +364,14 @@ def sign(self, data, key=None, passphrase=None, cert=None, reference_uri=None, k
352364
reference_uris = reference_uri
353365

354366
sig_root, doc_root, c14n_inputs, reference_uris = self._unpack(data, reference_uris)
355-
signed_info_element, signature_value_element = self._build_sig(sig_root, reference_uris, c14n_inputs)
356-
367+
signed_info_element, signature_value_element = self._build_sig(sig_root, reference_uris, c14n_inputs,
368+
sig_insp=signature_inclusive_ns_prefixes,
369+
payload_insp=payload_inclusive_ns_prefixes)
357370
if key is None:
358371
raise InvalidInput('Parameter "key" is required')
359372

360-
signed_info_c14n = self._c14n(signed_info_element, algorithm=self.c14n_alg)
373+
signed_info_c14n = self._c14n(signed_info_element, algorithm=self.c14n_alg,
374+
inclusive_ns_prefixes=signature_inclusive_ns_prefixes)
361375
if self.sign_alg.startswith("hmac-"):
362376
from cryptography.hazmat.primitives.hmac import HMAC
363377
signer = HMAC(key=key,
@@ -475,9 +489,12 @@ def _unpack(self, data, reference_uris):
475489
reference_uris = ["#object"]
476490
return sig_root, doc_root, c14n_inputs, reference_uris
477491

478-
def _build_sig(self, sig_root, reference_uris, c14n_inputs):
492+
def _build_sig(self, sig_root, reference_uris, c14n_inputs, sig_insp, payload_insp):
479493
signed_info = SubElement(sig_root, ds_tag("SignedInfo"), nsmap=self.namespaces)
480-
SubElement(signed_info, ds_tag("CanonicalizationMethod"), Algorithm=self.c14n_alg)
494+
sig_c14n_method = SubElement(signed_info, ds_tag("CanonicalizationMethod"), Algorithm=self.c14n_alg)
495+
if sig_insp:
496+
SubElement(sig_c14n_method, ec_tag("InclusiveNamespaces"), PrefixList=" ".join(sig_insp))
497+
481498
if self.sign_alg.startswith("hmac-"):
482499
algorithm_id = self.known_hmac_digest_tags[self.sign_alg]
483500
else:
@@ -490,11 +507,13 @@ def _build_sig(self, sig_root, reference_uris, c14n_inputs):
490507
SubElement(transforms, ds_tag("Transform"), Algorithm=namespaces.ds + "enveloped-signature")
491508
SubElement(transforms, ds_tag("Transform"), Algorithm=self.c14n_alg)
492509
else:
493-
SubElement(transforms, ds_tag("Transform"), Algorithm=self.c14n_alg)
510+
c14n_xform = SubElement(transforms, ds_tag("Transform"), Algorithm=self.c14n_alg)
511+
if payload_insp:
512+
SubElement(c14n_xform, ec_tag("InclusiveNamespaces"), PrefixList=" ".join(payload_insp))
494513

495514
SubElement(reference, ds_tag("DigestMethod"), Algorithm=self.known_digest_tags[self.digest_alg])
496515
digest_value = SubElement(reference, ds_tag("DigestValue"))
497-
payload_c14n = self._c14n(c14n_inputs[i], algorithm=self.c14n_alg)
516+
payload_c14n = self._c14n(c14n_inputs[i], algorithm=self.c14n_alg, inclusive_ns_prefixes=payload_insp)
498517
digest = self._get_digest(payload_c14n, self._get_digest_method_by_tag(self.digest_alg))
499518
digest_value.text = digest
500519
signature_value = SubElement(sig_root, ds_tag("SignatureValue"))

0 commit comments

Comments
 (0)