Open vxgmichel opened 2 years ago
If you could provide a PR with a test case that fails using the current implementation, that would make it a bit easier to tweak the implementation to handling such "mis-encoded" certificates.
If you could provide a PR with a test case that fails using the current implementation, that would make it a bit easier to tweak the implementation to handling such "mis-encoded" certificates.
Here you go: https://github.com/wbond/asn1crypto/pull/241 :)
This issue is about the attribute
2.5.4.45
, also calleduniqueIdentifier
orx500UniqueIdentifier
:https://ldapwiki.com/wiki/X500UniqueIdentifier
The OID specification for this attribute requires a value of type
BIT STRING
(universal tag 3), but in the wild we might see aUTF8String
type instead (universal tag 12). For instance, it can easily be generated using the followingopenssl
command:The problem is that
asn1crypto
raises aValueError
when building the corresponding subject, which might cause other apparently unrelated operations to fail. I have listed three such cases in the test module below:from asn1crypto import x509, pem from certvalidator import CertificateValidator, ValidationContext, errors
@pytest.fixture( params=[False, True], ids=["without_unique_identifier", "with_unique_identifier"] ) def self_signed_certificate(request, tmp_path): key_file = tmp_path / "ca.key" cert_file = tmp_path / "ca.pem"
Certificate subject
def test_subject_common_name(self_signed_certificate): assert self_signed_certificate.subject.native["common_name"] == "test_ca"
def test_validate_certificate_with_trust_root(self_signed_certificate): validation_context = ValidationContext(extra_trust_roots=[self_signed_certificate]) validator = CertificateValidator( self_signed_certificate, validation_context=validation_context ) validator.validate_usage({"digital_signature"})
def test_validate_certificate_without_trust_root(self_signed_certificate): validator = CertificateValidator(self_signed_certificate) with pytest.raises(errors.InvalidCertificateError): validator.validate_usage({"digital_signature"})
test_asn1crypto.py::test_subject_common_name[without_unique_identifier] PASSED test_asn1crypto.py::test_subject_common_name[with_unique_identifier] FAILED test_asn1crypto.py::test_validate_certificate_with_trust_root[without_unique_identifier] PASSED test_asn1crypto.py::test_validate_certificate_with_trust_root[with_unique_identifier] FAILED test_asn1crypto.py::test_validate_certificate_without_trust_root[without_unique_identifier] PASSED
test_asn1crypto.py::test_validate_certificate_without_trust_root[with_unique_identifier] FAILED
This patch is trickier than I expected because simply registering
UTF8String.tag
as a bad tag forOctetBitString
wasn't enough: the content ofOctetBitString
also has to be prepended withb"\x00"
in order for the utf-8 string to be interpreted as a bit string.I hope I didn't miss anything important while investigating this issue, and I'll be happy to provide more information if necessary.