@@ -36,6 +36,9 @@ def ds_tag(tag):
3636def dsig11_tag (tag ):
3737 return "{" + namespaces .dsig11 + "}" + tag
3838
39+ def ec_tag (tag ):
40+ return "{" + namespaces .ec + "}" + tag
41+
3942def _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