Skip to content

Commit b09c0e4

Browse files
committed
De-duplicate verify methods
1 parent 953a0c5 commit b09c0e4

File tree

1 file changed

+21
-26
lines changed

1 file changed

+21
-26
lines changed

signxml/verifier.py

+21-26
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from dataclasses import dataclass, replace
33
from typing import Callable, FrozenSet, List, Optional, Union
44

5+
import cryptography.exceptions
56
from cryptography import x509
67
from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa, utils
78
from cryptography.hazmat.primitives.asymmetric.padding import MGF1, PSS, AsymmetricPadding, PKCS1v15
@@ -114,14 +115,20 @@ def _get_signature(self, root):
114115

115116
def _verify_signature_with_pubkey(
116117
self,
118+
*,
117119
signed_info_c14n: bytes,
118120
raw_signature: bytes,
119-
key_value: etree._Element,
120-
der_encoded_key_value: Optional[etree._Element],
121121
signature_alg: SignatureMethod,
122+
key_value: Optional[etree._Element] = None,
123+
der_encoded_key_value: Optional[etree._Element] = None,
124+
signing_certificate: Optional[x509.Certificate] = None,
122125
) -> None:
123126
if der_encoded_key_value is not None:
124127
key = load_der_public_key(b64decode(der_encoded_key_value.text)) # type: ignore
128+
elif signing_certificate is not None:
129+
key = signing_certificate.public_key()
130+
elif key_value is None:
131+
raise InvalidInput("Expected one of key_value, der_encoded_key_value, or signing_certificate to be set")
125132

126133
digest_alg_impl = digest_algorithm_implementations[signature_alg]()
127134
if signature_alg.name.startswith("ECDSA_"):
@@ -137,8 +144,8 @@ def _verify_signature_with_pubkey(
137144
key = ecpn.public_key()
138145
elif not isinstance(key, ec.EllipticCurvePublicKey):
139146
raise InvalidInput("DER encoded key value does not match specified signature algorithm")
140-
dss_signature = self._encode_dss_signature(raw_signature, key.key_size)
141-
key.verify(dss_signature, data=signed_info_c14n, signature_algorithm=ec.ECDSA(digest_alg_impl))
147+
signature_for_ecdsa = self._encode_dss_signature(raw_signature, key.key_size)
148+
key.verify(signature_for_ecdsa, data=signed_info_c14n, signature_algorithm=ec.ECDSA(digest_alg_impl))
142149
elif signature_alg.name.startswith("DSA_"):
143150
if key_value is not None:
144151
dsa_key_value = self._find(key_value, "DSAKeyValue")
@@ -167,7 +174,7 @@ def _verify_signature_with_pubkey(
167174
padding = PSS(mgf=MGF1(algorithm=digest_alg_impl), salt_length=digest_alg_impl.digest_size)
168175
key.verify(raw_signature, data=signed_info_c14n, padding=padding, algorithm=digest_alg_impl)
169176
else:
170-
raise NotImplementedError()
177+
raise InvalidInput(f"Unsupported signature algorithm {signature_alg}")
171178

172179
def _encode_dss_signature(self, raw_signature: bytes, key_size_bits: int) -> bytes:
173180
want_raw_signature_len = bits_to_bytes_unit(key_size_bits) * 2
@@ -226,16 +233,6 @@ def _apply_transforms(self, payload, *, transforms_node: etree._Element, signatu
226233
def get_cert_chain_verifier(self, ca_pem_file, ca_path):
227234
return X509CertChainVerifier(ca_pem_file=ca_pem_file, ca_path=ca_path)
228235

229-
def _verify_signature_with_public_key_impl(self, *, signature, data, public_key, signature_alg_impl):
230-
verify_args = dict(signature=signature, data=data)
231-
if isinstance(public_key, rsa.RSAPublicKey):
232-
verify_args.update(padding=PKCS1v15(), algorithm=signature_alg_impl)
233-
elif isinstance(public_key, dsa.DSAPublicKey):
234-
verify_args.update(algorithm=signature_alg_impl)
235-
elif isinstance(public_key, ec.EllipticCurvePublicKey):
236-
verify_args.update(signature_algorithm=ec.ECDSA(signature_alg_impl))
237-
public_key.verify(**verify_args)
238-
239236
def verify(
240237
self,
241238
data,
@@ -406,17 +403,15 @@ def verify(
406403
if subject_cn_from_signing_cert != cert_subject_name:
407404
raise InvalidSignature("Certificate subject common name mismatch")
408405

409-
if signature_alg.name.startswith("ECDSA"):
410-
raw_signature = self._encode_dss_signature(raw_signature, signing_cert.public_key().key_size)
411-
412-
cert_public_key = signing_cert.public_key()
413-
signature_alg_impl = digest_algorithm_implementations[signature_alg]()
414-
self._verify_signature_with_public_key_impl(
415-
signature=raw_signature,
416-
data=signed_info_c14n,
417-
public_key=cert_public_key,
418-
signature_alg_impl=signature_alg_impl,
419-
)
406+
try:
407+
self._verify_signature_with_pubkey(
408+
signed_info_c14n=signed_info_c14n,
409+
raw_signature=raw_signature,
410+
signing_certificate=signing_cert,
411+
signature_alg=signature_alg,
412+
)
413+
except cryptography.exceptions.InvalidSignature as e:
414+
raise InvalidSignature(f"Signature verification failed: {e}")
420415

421416
# If both X509Data and KeyValue are present, match one against the other and raise an error on mismatch
422417
if key_value is not None:

0 commit comments

Comments
 (0)