Skip to content

Commit 980d2e6

Browse files
committed
Refactor OpenSSLWrapper.verify for better diagnostics and simpler flow
Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
1 parent 2502413 commit 980d2e6

1 file changed

Lines changed: 55 additions & 47 deletions

File tree

‎src/saml2/cert.py‎

Lines changed: 55 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ def verify_chain(self, cert_chain_str_list, cert_str):
278278
return False, message
279279
else:
280280
cert_str = tmp_cert_str
281-
return (True, "Signed certificate is valid and correctly signed by CA " "certificate.")
281+
return (True, "Signed certificate is valid and correctly signed by CA certificate.")
282282

283283
def verify(self, signing_cert_str, cert_str):
284284
"""
@@ -299,60 +299,68 @@ def verify(self, signing_cert_str, cert_str):
299299
otherwise false.
300300
Message = Why the validation failed.
301301
"""
302-
try:
303-
cert_str_bytes = cert_str if isinstance(cert_str, bytes) else cert_str.encode("ascii")
304-
signing_cert_bytes = (
305-
signing_cert_str if isinstance(signing_cert_str, bytes) else signing_cert_str.encode("ascii")
306-
)
307-
308-
cert_crypto = saml2.cryptography.pki.load_pem_x509_certificate(cert_str_bytes)
309-
ca_cert_crypto = saml2.cryptography.pki.load_pem_x509_certificate(signing_cert_bytes)
310-
311-
now = datetime.now(timezone.utc)
312-
313-
if now < ca_cert_crypto.not_valid_before_utc:
314-
return False, "CA certificate is not valid yet."
315-
316-
if now >= ca_cert_crypto.not_valid_after_utc:
317-
return False, "CA certificate is expired."
318-
319-
if now >= cert_crypto.not_valid_after_utc:
320-
return False, "The signed certificate is expired."
321-
322-
if now < cert_crypto.not_valid_before_utc:
323-
return False, "The signed certificate is not valid yet."
324302

325-
ca_cn = ca_cert_crypto.subject.get_attributes_for_oid(_x509.NameOID.COMMON_NAME)
326-
cert_cn = cert_crypto.subject.get_attributes_for_oid(_x509.NameOID.COMMON_NAME)
327-
if ca_cn and cert_cn and ca_cn[0].value == cert_cn[0].value:
328-
return False, "CN may not be equal for CA certificate and the signed certificate."
303+
cert_str_bytes = cert_str if isinstance(cert_str, bytes) else cert_str.encode("ascii")
304+
signing_cert_bytes = (
305+
signing_cert_str if isinstance(signing_cert_str, bytes) else signing_cert_str.encode("ascii")
306+
)
329307

330-
if cert_crypto.signature_hash_algorithm is None:
331-
return False, "Unsupported signature algorithm (no hash algorithm present)."
308+
try:
309+
cert_crypto = saml2.cryptography.pki.load_pem_x509_certificate(cert_str_bytes)
310+
except ValueError as e:
311+
return False, f"Failed to load certificate: {e}"
332312

333-
ca_public_key = ca_cert_crypto.public_key()
313+
try:
314+
ca_cert_crypto = saml2.cryptography.pki.load_pem_x509_certificate(signing_cert_bytes)
315+
except ValueError as e:
316+
return False, f"Failed to load CA certificate: {e}"
317+
318+
now = datetime.now(timezone.utc)
319+
if now < ca_cert_crypto.not_valid_before_utc:
320+
return False, "CA certificate is not valid yet."
321+
if now >= ca_cert_crypto.not_valid_after_utc:
322+
return False, "CA certificate is expired."
323+
if now < cert_crypto.not_valid_before_utc:
324+
return False, "The signed certificate is not valid yet."
325+
if now >= cert_crypto.not_valid_after_utc:
326+
return False, "The signed certificate is expired."
327+
328+
ca_cn_attr = ca_cert_crypto.subject.get_attributes_for_oid(_x509.NameOID.COMMON_NAME)
329+
ca_cn_value = ca_cn_attr and ca_cn_attr[0].value
330+
cert_cn_attr = cert_crypto.subject.get_attributes_for_oid(_x509.NameOID.COMMON_NAME)
331+
cert_cn_value = cert_cn_attr and cert_cn_attr[0].value
332+
if ca_cn_value == cert_cn_value:
333+
return False, "CN may not be equal for CA certificate and the signed certificate."
334+
335+
if cert_crypto.signature_hash_algorithm is None:
336+
return False, "Unsupported signature algorithm (no hash algorithm present)."
337+
338+
ca_public_key = ca_cert_crypto.public_key()
339+
340+
if isinstance(ca_public_key, _rsa.RSAPublicKey):
341+
try:
342+
ca_public_key.verify(
343+
signature=cert_crypto.signature,
344+
data=cert_crypto.tbs_certificate_bytes,
345+
padding=_padding.PKCS1v15(),
346+
algorithm=cert_crypto.signature_hash_algorithm,
347+
)
348+
return True, "Signed certificate is valid and correctly signed by CA certificate."
349+
except InvalidSignature as e:
350+
return False, f"Certificate is incorrectly signed: {str(e)}"
334351

352+
if isinstance(ca_public_key, _ec.EllipticCurvePublicKey):
335353
try:
336-
if isinstance(ca_public_key, _rsa.RSAPublicKey):
337-
ca_public_key.verify(
338-
cert_crypto.signature,
339-
cert_crypto.tbs_certificate_bytes,
340-
_padding.PKCS1v15(),
341-
cert_crypto.signature_hash_algorithm,
342-
)
343-
elif isinstance(ca_public_key, _ec.EllipticCurvePublicKey):
344-
ca_public_key.verify(
345-
cert_crypto.signature,
346-
cert_crypto.tbs_certificate_bytes,
347-
_ec.ECDSA(cert_crypto.signature_hash_algorithm),
348-
)
349-
else:
350-
return False, f"Unsupported public key type: {type(ca_public_key)}"
354+
ca_public_key.verify(
355+
signature=cert_crypto.signature,
356+
data=cert_crypto.tbs_certificate_bytes,
357+
signature_algorithm=_ec.ECDSA(cert_crypto.signature_hash_algorithm),
358+
)
351359
return True, "Signed certificate is valid and correctly signed by CA certificate."
352360
except InvalidSignature as e:
353361
return False, f"Certificate is incorrectly signed: {str(e)}"
354-
except Exception as e:
355-
return False, f"Certificate is not valid for an unknown reason. {str(e)}"
362+
363+
return False, f"Unsupported public key type: {type(ca_public_key)}"
356364

357365

358366
def read_cert_from_file(cert_file, cert_type="pem"):

0 commit comments

Comments
 (0)