You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Some certificate in the chain expired, which makes the revocation test fail. Can be seen on versions 0.3 and 0.4.
_________________ ValidationTestCase.test_revoked_certificate __________________
self = <signify.x509.context.VerificationContext object at 0x7fffeef62fd0>
certificate = <signify.x509.certificates.Certificate object at 0x7fffeef62f70>
def verify(self, certificate):
"""Verifies the certificate, and its chain.
:param Certificate certificate: The certificate to verify
:return: A valid certificate chain for this certificate.
:rtype: Iterable[Certificate]
:raises AuthenticodeVerificationError: When the certificate could not be verified.
"""
# we keep track of our asn1 objects to make sure we return Certificate objects when we're done
to_check_asn1cert = certificate.to_asn1crypto
all_certs = {to_check_asn1cert: certificate}
# we need to get lists of our intermediates and trusted certificates
intermediates, trust_roots = [], []
for store in self.stores:
for cert in store:
asn1cert = cert.to_asn1crypto
# we short-circuit the check here to ensure we do not check too much possibilities
(trust_roots if store.trusted else intermediates).append(asn1cert)
all_certs[asn1cert] = cert
# construct the context and validator for certvalidator
timestamp = self.timestamp
context = ValidationContext(
trust_roots=list(trust_roots),
moment=timestamp,
weak_hash_algos=set() if self.allow_legacy else None,
revocation_mode=self.revocation_mode,
allow_fetching=self.allow_fetching,
crl_fetch_params={'timeout': self.fetch_timeout},
ocsp_fetch_params={'timeout': self.fetch_timeout},
crls=self.crls,
ocsps=self.ocsps
)
validator = CertificateValidator(
end_entity_cert=to_check_asn1cert,
intermediate_certs=list(intermediates),
validation_context=context
)
# verify the chain
try:
> chain = validator.validate_usage(
key_usage=set(self.key_usages) if self.key_usages else set(),
extended_key_usage=set(self.extended_key_usages) if self.extended_key_usages else set(),
extended_optional=self.optional_eku
)
signify/x509/context.py:291:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <certvalidator.CertificateValidator object at 0x7fffee54e4f0>
key_usage = set(), extended_key_usage = set(), extended_optional = True
def validate_usage(self, key_usage, extended_key_usage=None, extended_optional=False):
"""
Validates the certificate path and that the certificate is valid for
the key usage and extended key usage purposes specified.
:param key_usage:
A set of unicode strings of the required key usage purposes. Valid
values include:
- "digital_signature"
- "non_repudiation"
- "key_encipherment"
- "data_encipherment"
- "key_agreement"
- "key_cert_sign"
- "crl_sign"
- "encipher_only"
- "decipher_only"
:param extended_key_usage:
A set of unicode strings of the required extended key usage
purposes. These must be either dotted number OIDs, or one of the
following extended key usage purposes:
- "server_auth"
- "client_auth"
- "code_signing"
- "email_protection"
- "ipsec_end_system"
- "ipsec_tunnel"
- "ipsec_user"
- "time_stamping"
- "ocsp_signing"
- "wireless_access_points"
An example of a dotted number OID:
- "1.3.6.1.5.5.7.3.1"
:param extended_optional:
A bool - if the extended_key_usage extension may be ommited and still
considered valid
:raises:
certvalidator.errors.PathValidationError - when an error occurs validating the path
certvalidator.errors.RevokedError - when the certificate or another certificate in its path has been revoked
certvalidator.errors.InvalidCertificateError - when the certificate is not valid for the usages specified
:return:
A certvalidator.path.ValidationPath object of the validated
certificate validation path
"""
> self._validate_path()
/nix/store/qxzqxa6k9rznbidjcnjj1ra1ascizy7n-python3.9-certvalidator-0.11.1/lib/python3.9/site-packages/certvalidator/__init__.py:193:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <certvalidator.CertificateValidator object at 0x7fffee54e4f0>
def _validate_path(self):
"""
Builds possible certificate paths and validates them until a valid one
is found, or all fail.
:raises:
certvalidator.errors.PathValidationError - when an error occurs validating the path
certvalidator.errors.RevokedError - when the certificate or another certificate in its path has been revoked
"""
if self._path is not None:
return
exceptions = []
if self._certificate.hash_algo in self._context.weak_hash_algos:
raise InvalidCertificateError(pretty_message(
'''
The X.509 certificate provided has a signature using the weak
hash algorithm %s
''',
self._certificate.hash_algo
))
try:
paths = self._context.certificate_registry.build_paths(self._certificate)
except (PathBuildingError) as e:
if self._certificate.self_signed in set(['yes', 'maybe']):
raise InvalidCertificateError(pretty_message(
'''
The X.509 certificate provided is self-signed - "%s"
''',
self._certificate.subject.human_friendly
))
raise
for candidate_path in paths:
try:
validate_path(self._context, candidate_path)
self._path = candidate_path
return
except (ValidationError) as e:
exceptions.append(e)
if len(exceptions) == 1:
> raise exceptions[0]
/nix/store/qxzqxa6k9rznbidjcnjj1ra1ascizy7n-python3.9-certvalidator-0.11.1/lib/python3.9/site-packages/certvalidator/__init__.py:128:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <certvalidator.CertificateValidator object at 0x7fffee54e4f0>
def _validate_path(self):
"""
Builds possible certificate paths and validates them until a valid one
is found, or all fail.
:raises:
certvalidator.errors.PathValidationError - when an error occurs validating the path
certvalidator.errors.RevokedError - when the certificate or another certificate in its path has been revoked
"""
if self._path is not None:
return
exceptions = []
if self._certificate.hash_algo in self._context.weak_hash_algos:
raise InvalidCertificateError(pretty_message(
'''
The X.509 certificate provided has a signature using the weak
hash algorithm %s
''',
self._certificate.hash_algo
))
try:
paths = self._context.certificate_registry.build_paths(self._certificate)
except (PathBuildingError) as e:
if self._certificate.self_signed in set(['yes', 'maybe']):
raise InvalidCertificateError(pretty_message(
'''
The X.509 certificate provided is self-signed - "%s"
''',
self._certificate.subject.human_friendly
))
raise
for candidate_path in paths:
try:
> validate_path(self._context, candidate_path)
/nix/store/qxzqxa6k9rznbidjcnjj1ra1ascizy7n-python3.9-certvalidator-0.11.1/lib/python3.9/site-packages/certvalidator/__init__.py:121:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
validation_context = <certvalidator.context.ValidationContext object at 0x7fffee4df6d0>
path = <certvalidator.path.ValidationPath object at 0x7fffee534880>
def validate_path(validation_context, path):
"""
Validates the path using the algorithm from
https://tools.ietf.org/html/rfc5280#section-6.1, with the exception
that name constraints are not checked or enforced.
Critical extensions on the end-entity certificate are not validated
and are left up to the consuming application to process and/or fail on.
:param validation_context:
A certvalidator.context.ValidationContext object to use for
configuring validation behavior
:param path:
A certvalidator.path.ValidationPath object of the path to validate
:raises:
certvalidator.errors.PathValidationError - when an error occurs validating the path
certvalidator.errors.RevokedError - when the certificate or another certificate in its path has been revoked
:return:
The final certificate in the path - an instance of
asn1crypto.x509.Certificate
"""
> return _validate_path(validation_context, path)
/nix/store/qxzqxa6k9rznbidjcnjj1ra1ascizy7n-python3.9-certvalidator-0.11.1/lib/python3.9/site-packages/certvalidator/validate.py:50:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
validation_context = <certvalidator.context.ValidationContext object at 0x7fffee4df6d0>
path = <certvalidator.path.ValidationPath object at 0x7fffee534880>
end_entity_name_override = None
def _validate_path(validation_context, path, end_entity_name_override=None):
"""
Internal copy of validate_path() that allows overriding the name of the
end-entity certificate as used in exception messages. This functionality is
used during chain validation when dealing with indirect CRLs issuer or
OCSP responder certificates.
:param validation_context:
A certvalidator.context.ValidationContext object to use for
configuring validation behavior
:param path:
A certvalidator.path.ValidationPath object of the path to validate
:param end_entity_name_override:
A unicode string of the name to use for the final certificate in the
path. This is necessary when dealing with indirect CRL issuers or
OCSP responder certificates.
:return:
The final certificate in the path - an instance of
asn1crypto.x509.Certificate
"""
if not isinstance(path, ValidationPath):
raise TypeError(pretty_message(
'''
path must be an instance of certvalidator.path.ValidationPath,
not %s
''',
type_name(path)
))
if not isinstance(validation_context, ValidationContext):
raise TypeError(pretty_message(
'''
validation_context must be an instance of
certvalidator.context.ValidationContext, not %s
''',
type_name(validation_context)
))
moment = validation_context.moment
if end_entity_name_override is not None and not isinstance(end_entity_name_override, str_cls):
raise TypeError(pretty_message(
'''
end_entity_name_override must be a unicode string, not %s
''',
type_name(end_entity_name_override)
))
# Inputs
trust_anchor = path.first
# We skip the trust anchor when measuring the path since technically
# the trust anchor is not part of the path
path_length = len(path) - 1
# We don't accept any certificate policy or name constraint values as input
# and instead just start allowing everything during initialization
# Step 1: initialization
# Step 1 a
valid_policy_tree = PolicyTreeRoot('any_policy', set(), set(['any_policy']))
# Steps 1 b-c skipped since they relate to name constraints
# Steps 1 d-f
# We do not use initial-explicit-policy, initial-any-policy-inhibit or
# initial-policy-mapping-inhibit, so they are all set to the path length + 1
explicit_policy = path_length + 1
inhibit_any_policy = path_length + 1
policy_mapping = path_length + 1
# Steps 1 g-i
working_public_key = trust_anchor.public_key
# Step 1 j
working_issuer_name = trust_anchor.subject
# Step 1 k
max_path_length = path_length
if trust_anchor.max_path_length is not None:
max_path_length = trust_anchor.max_path_length
# Step 2: basic processing
index = 1
last_index = len(path) - 1
completed_path = ValidationPath(trust_anchor)
validation_context.record_validation(trust_anchor, completed_path)
cert = trust_anchor
while index <= last_index:
cert = path[index]
# Step 2 a 1
signature_algo = cert['signature_algorithm'].signature_algo
hash_algo = cert['signature_algorithm'].hash_algo
if hash_algo in validation_context.weak_hash_algos:
raise PathValidationError(pretty_message(
'''
The path could not be validated because the signature of %s
uses the weak hash algorithm %s
''',
_cert_type(index, last_index, end_entity_name_override, definite=True),
hash_algo
))
if signature_algo == 'rsassa_pkcs1v15':
verify_func = asymmetric.rsa_pkcs1v15_verify
elif signature_algo == 'dsa':
verify_func = asymmetric.dsa_verify
elif signature_algo == 'ecdsa':
verify_func = asymmetric.ecdsa_verify
else:
raise PathValidationError(pretty_message(
'''
The path could not be validated because the signature of %s
uses the unsupported algorithm %s
''',
_cert_type(index, last_index, end_entity_name_override, definite=True),
signature_algo
))
try:
key_object = asymmetric.load_public_key(working_public_key)
verify_func(key_object, cert['signature_value'].native, cert['tbs_certificate'].dump(), hash_algo)
except (oscrypto.errors.SignatureError):
raise PathValidationError(pretty_message(
'''
The path could not be validated because the signature of %s
could not be verified
''',
_cert_type(index, last_index, end_entity_name_override, definite=True)
))
# Step 2 a 2
if not validation_context.is_whitelisted(cert):
validity = cert['tbs_certificate']['validity']
if moment < validity['not_before'].native:
raise PathValidationError(pretty_message(
'''
The path could not be validated because %s is not valid
until %s
''',
_cert_type(index, last_index, end_entity_name_override, definite=True),
validity['not_before'].native.strftime('%Y-%m-%d %H:%M:%SZ')
))
if moment > validity['not_after'].native:
> raise PathValidationError(pretty_message(
'''
The path could not be validated because %s expired %s
''',
_cert_type(index, last_index, end_entity_name_override, definite=True),
validity['not_after'].native.strftime('%Y-%m-%d %H:%M:%SZ')
))
E certvalidator.errors.PathValidationError: The path could not be validated because the end-entity certificate expired 2021-10-08 12:00:00Z
/nix/store/qxzqxa6k9rznbidjcnjj1ra1ascizy7n-python3.9-certvalidator-0.11.1/lib/python3.9/site-packages/certvalidator/validate.py:358: PathValidationError
During handling of the above exception, another exception occurred:
self = <tests.test_context.ValidationTestCase testMethod=test_revoked_certificate>
def test_revoked_certificate(self):
root = FileSystemCertificateStore(root_dir / "certs" / 'digicert-global-root-ca.pem', trusted=True)
intermediate = FileSystemCertificateStore(root_dir / "certs" / 'digicert-sha2-secure-server-ca.pem')
with open(str(root_dir / "certs" / 'revoked.badssl.com.pem'), "rb") as f:
cert = Certificate.from_pem(f.read())
# check that when we do not verify the CRL it does not fail
context = VerificationContext(root, intermediate)
> context.verify(cert)
tests/test_context.py:42:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <signify.x509.context.VerificationContext object at 0x7fffeef62fd0>
certificate = <signify.x509.certificates.Certificate object at 0x7fffeef62f70>
def verify(self, certificate):
"""Verifies the certificate, and its chain.
:param Certificate certificate: The certificate to verify
:return: A valid certificate chain for this certificate.
:rtype: Iterable[Certificate]
:raises AuthenticodeVerificationError: When the certificate could not be verified.
"""
# we keep track of our asn1 objects to make sure we return Certificate objects when we're done
to_check_asn1cert = certificate.to_asn1crypto
all_certs = {to_check_asn1cert: certificate}
# we need to get lists of our intermediates and trusted certificates
intermediates, trust_roots = [], []
for store in self.stores:
for cert in store:
asn1cert = cert.to_asn1crypto
# we short-circuit the check here to ensure we do not check too much possibilities
(trust_roots if store.trusted else intermediates).append(asn1cert)
all_certs[asn1cert] = cert
# construct the context and validator for certvalidator
timestamp = self.timestamp
context = ValidationContext(
trust_roots=list(trust_roots),
moment=timestamp,
weak_hash_algos=set() if self.allow_legacy else None,
revocation_mode=self.revocation_mode,
allow_fetching=self.allow_fetching,
crl_fetch_params={'timeout': self.fetch_timeout},
ocsp_fetch_params={'timeout': self.fetch_timeout},
crls=self.crls,
ocsps=self.ocsps
)
validator = CertificateValidator(
end_entity_cert=to_check_asn1cert,
intermediate_certs=list(intermediates),
validation_context=context
)
# verify the chain
try:
chain = validator.validate_usage(
key_usage=set(self.key_usages) if self.key_usages else set(),
extended_key_usage=set(self.extended_key_usages) if self.extended_key_usages else set(),
extended_optional=self.optional_eku
)
except Exception as e:
> raise CertificateVerificationError("Chain verification from %s failed: %s" % (certificate, e))
E signify.exceptions.CertificateVerificationError: Chain verification from CN=revoked.badssl.com, O=Lucas Garron Torres, L=Walnut Creek, ST=California, C=US (serial:4578095623763233818958520798617405692, sha1:23fc13ba6f27bf8dd1761bda7bb41921f59c21f7) failed: The path could not be validated because the end-entity certificate expired 2021-10-08 12:00:00Z
signify/x509/context.py:297: CertificateVerificationError
The text was updated successfully, but these errors were encountered:
Some certificate in the chain expired, which makes the revocation test fail. Can be seen on versions 0.3 and 0.4.
The text was updated successfully, but these errors were encountered: