@@ -566,7 +566,7 @@ def _verify_signature_with_pubkey(self, signed_info_c14n, raw_signature, key_val
566
566
if der_encoded_key_value is not None :
567
567
key = load_der_public_key (b64decode (der_encoded_key_value .text ), backend = default_backend ())
568
568
if "ecdsa-" in signature_alg :
569
- if key_value :
569
+ if key_value is not None :
570
570
ec_key_value = self ._find (key_value , "ECKeyValue" , namespace = "dsig11" )
571
571
named_curve = self ._find (ec_key_value , "NamedCurve" , namespace = "dsig11" )
572
572
public_key = self ._find (ec_key_value , "PublicKey" , namespace = "dsig11" )
@@ -586,7 +586,7 @@ def _verify_signature_with_pubkey(self, signed_info_c14n, raw_signature, key_val
586
586
),
587
587
)
588
588
elif "dsa-" in signature_alg :
589
- if key_value :
589
+ if key_value is not None :
590
590
dsa_key_value = self ._find (key_value , "DSAKeyValue" )
591
591
p = self ._get_long (dsa_key_value , "P" )
592
592
q = self ._get_long (dsa_key_value , "Q" )
@@ -602,7 +602,7 @@ def _verify_signature_with_pubkey(self, signed_info_c14n, raw_signature, key_val
602
602
data = signed_info_c14n ,
603
603
algorithm = self ._get_signature_digest_method (signature_alg ))
604
604
elif "rsa-" in signature_alg :
605
- if key_value :
605
+ if key_value is not None :
606
606
rsa_key_value = self ._find (key_value , "RSAKeyValue" )
607
607
modulus = self ._get_long (rsa_key_value , "Modulus" )
608
608
exponent = self ._get_long (rsa_key_value , "Exponent" )
@@ -660,8 +660,8 @@ def _apply_transforms(self, payload, transforms_node, signature, c14n_algorithm)
660
660
661
661
return payload
662
662
663
- def verify (self , data , require_x509 = True , x509_cert = None , cert_subject_name = None , ca_pem_file = None , ca_path = None ,
664
- hmac_key = None , validate_schema = True , parser = None , uri_resolver = None , cert_resolver = None ,
663
+ def verify (self , data , require_x509 = True , x509_cert = None , cert_subject_name = None , cert_resolver = None ,
664
+ ca_pem_file = None , ca_path = None , hmac_key = None , validate_schema = True , parser = None , uri_resolver = None ,
665
665
id_attribute = None , expect_references = 1 , ignore_ambiguous_key_info = False ):
666
666
"""
667
667
Verify the XML signature supplied in the data and return the XML node signed by the signature, or raise an
@@ -704,6 +704,16 @@ def verify(self, data, require_x509=True, x509_cert=None, cert_subject_name=None
704
704
``None``, requires that the signature supply a valid X.509 certificate chain that validates against the
705
705
known certificate authorities. Implies **require_x509=True**.
706
706
:type x509_cert: string or OpenSSL.crypto.X509
707
+ :param cert_subject_name:
708
+ Subject Common Name to check the signing X.509 certificate against. Implies **require_x509=True**.
709
+ :type cert_subject_name: string
710
+ :param cert_resolver:
711
+ Function to use to resolve trusted X.509 certificates when X509IssuerSerial and X509Digest references are
712
+ found in the signature. The function is called with the keyword arguments ``x509_issuer_name``,
713
+ ``x509_serial_number`` and ``x509_digest``, and is expected to return an iterable of one or more
714
+ strings containing a PEM-formatted certificate and a chain of intermediate certificates, if needed.
715
+ Implies **require_x509=True**.
716
+ :type cert_resolver: callable
707
717
:param ca_pem_file:
708
718
Filename of a PEM file containing certificate authority information to use when verifying certificate-based
709
719
signatures.
@@ -713,9 +723,6 @@ def verify(self, data, require_x509=True, x509_cert=None, cert_subject_name=None
713
723
certificate-based signatures. If neither **ca_pem_file** nor **ca_path** is given, the Mozilla CA bundle
714
724
provided by :py:mod:`certifi` will be loaded.
715
725
:type ca_path: string
716
- :param cert_subject_name:
717
- Subject Common Name to check the signing X.509 certificate against. Implies **require_x509=True**.
718
- :type cert_subject_name: string
719
726
:param hmac_key: If using HMAC, a string containing the shared secret.
720
727
:type hmac_key: string
721
728
:param validate_schema: Whether to validate **data** against the XML Signature schema.
@@ -728,12 +735,6 @@ def verify(self, data, require_x509=True, x509_cert=None, cert_subject_name=None
728
735
Function to use to resolve reference URIs that don't start with "#". The function is called with a single
729
736
string argument containing the URI to be resolved, and is expected to return a lxml.etree node or string.
730
737
:type uri_resolver: callable
731
- :param cert_resolver:
732
- Function to use to resolve X.509 certificates when X509IssuerSerial and X509Digest references are found in
733
- the signature. The function is called with the keyword arguments ``x509_issuer_name``,
734
- ``x509_serial_number`` and ``x509_digest``, and is expected to return an iterable of one or more
735
- strings containing PEM-formatted certificates.
736
- :type cert_resolver: callable
737
738
:param id_attribute:
738
739
Name of the attribute whose value ``URI`` refers to. By default, SignXML will search for "Id", then "ID".
739
740
:type id_attribute: string
@@ -761,7 +762,7 @@ def verify(self, data, require_x509=True, x509_cert=None, cert_subject_name=None
761
762
self .x509_cert = x509_cert
762
763
self ._parser = parser
763
764
764
- if x509_cert :
765
+ if x509_cert or cert_resolver :
765
766
self .require_x509 = True
766
767
767
768
if id_attribute is not None :
@@ -803,15 +804,20 @@ def verify(self, data, require_x509=True, x509_cert=None, cert_subject_name=None
803
804
x509_iss = x509_data .find ("ds:X509IssuerSerial/ds:X509IssuerName" , namespaces = namespaces )
804
805
x509_sn = x509_data .find ("ds:X509IssuerSerial/ds:X509SerialNumber" , namespaces = namespaces )
805
806
x509_digest = x509_data .find ("dsig11:X509Digest" , namespaces = namespaces )
806
- if cert_resolver is not None and (x509_iss or x509_sn or x509_digest ):
807
- certs = cert_resolver (x509_issuer_name = x509_iss .text if x509_iss is not None else None ,
808
- x509_serial_number = x509_sn .text if x509_sn is not None else None ,
809
- x509_digest = x509_digest .text if x509_digest is not None else None )
807
+ if cert_resolver and any (i is not None for i in (x509_iss , x509_sn , x509_digest )):
808
+ cert_chain = cert_resolver (x509_issuer_name = x509_iss .text if x509_iss is not None else None ,
809
+ x509_serial_number = x509_sn .text if x509_sn is not None else None ,
810
+ x509_digest = x509_digest .text if x509_digest is not None else None )
811
+ if len (cert_chain ) == 0 :
812
+ raise InvalidCertificate ("No certificate found for given X509 data" )
813
+ if not all (isinstance (c , X509 ) for c in cert_chain ):
814
+ cert_chain = [load_certificate (FILETYPE_PEM , add_pem_header (cert )) for cert in cert_chain ]
810
815
else :
811
816
msg = "Expected to find an X509Certificate element in the signature"
812
817
msg += " (X509SubjectName, X509SKI are not supported)"
813
818
raise InvalidInput (msg )
814
- cert_chain = [load_certificate (FILETYPE_PEM , add_pem_header (cert )) for cert in certs ]
819
+ else :
820
+ cert_chain = [load_certificate (FILETYPE_PEM , add_pem_header (cert )) for cert in certs ]
815
821
signing_cert = verify_x509_cert_chain (cert_chain , ca_pem_file = ca_pem_file , ca_path = ca_path )
816
822
elif isinstance (self .x509_cert , X509 ):
817
823
signing_cert = self .x509_cert
0 commit comments