Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine if SSL certificate is self signed using Python

I am trying to determine if an SSL certificate is self signed or not. Currently I have the following code which compares the issuer CN and the subject CN and if they are the same, marks the result as self signed.

with open(cert_file, "r") as f: 
    x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, f.read())

result = {
    'subject': dict(x509.get_subject().get_components()),
    'issuer': dict(x509.get_issuer().get_components()),
    'serialNumber': x509.get_serial_number(),
    'version': x509.get_version(),
    'notBefore': datetime.strptime(x509.get_notBefore(), '%Y%m%d%H%M%SZ'),
    'notAfter': datetime.strptime(x509.get_notAfter(), '%Y%m%d%H%M%SZ'),
}

extensions = (x509.get_extension(i) for i in range(x509.get_extension_count()))
extension_data = {e.get_short_name(): str(e) for e in extensions}
result.update(extension_data)

if result['issuer']['CN'] == result['subject']['CN']:
    result.update({'self-signed': True})
else:
    result.update({'self-signed': False})

This comparison is very simplistic, but works in a lot of cases. I'm not trying to verify SSL certs or reimplement OpenSSL. How can I make this better and be roughly 95% sure if a certificate is self signed or not?

My one requirement is that I would like to do this in Python and not call other processes or use shell commands.

like image 309
Kredns Avatar asked Jun 25 '19 23:06

Kredns


People also ask

How do I know if my SSL certificate is self-signed?

A certificate is self-signed if the subject and issuer match. A certificate is signed by a Certificate Authority (CA) if they are different. To validate a CA-signed certificate, you also need a CA certificate. The Details tab (not shown here) sections can be expanded to show each field in a certificate.

Why is my SSL certificate self-signed?

By default the SSL certificate that would be configured on your server would be a self-signed one, essentially meaning that it has not been issued by a CA, but instead your own server has signed the certificate as being valid.

How do I get a self-signed certificate for SSL?

Open IIS manager (inetmgr) on your web server. Click on the server node (one of the root nodes) in the left panel, and double click "Server certificates". Click on "Create Self-Signed Certificate" on the right panel and type in anything you want for the friendly name.

What is SSL certificate verification – Python?

SSL Certificate Verification – Python requests Last Updated : 05 Mar, 2020 Requests verifies SSL certificates for HTTPS requests, just like a web browser. SSL Certificates are small data files that digitally bind a cryptographic key to an organization’s details.

What is SSL certificate_verify_failed and how to fix it?

SSL certificate_verify_failed errors typically occur as a result of outdated Python default certificates or invalid root certificates. We will cover how to fix this issue in 4 ways in this article. Why certificate_verify_failed happen? The SSL connection will be established based on the following process.

What is SSL certificate and how does it work?

SSL Certificates are small data files that digitally bind a cryptographic key to an organization’s details. Often, a website with a SSL certificate is termed as secure website. By default, SSL verification is enabled, and Requests will throw a SSLError if it’s unable to verify the certificate.

Are self-signed certificates as trustworthy as SSL certificates?

However, browsers do not consider self-signed certificates to be as trustworthy as SSL certificates issued by a certificate authority. Server certificates are known as SSL/TLS certificates.


1 Answers

The OpenSSL definition of self-signed is:

The subject and issuer names match and extension values imply it is self signed.

The code that determines whether a cert is self-signed is:

/* Return 1 is a certificate is self signed */
static int cert_self_signed(X509 *x)
{
    X509_check_purpose(x, -1, 0);
    if (x->ex_flags & EXFLAG_SS)
        return 1;
    else
        return 0;
}

And the code that sets EXFLAG_SS:

/* Does subject name match issuer ? */
if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) {
    x->ex_flags |= EXFLAG_SI;
    /* If SKID matches AKID also indicate self signed */
    if (X509_check_akid(x, x->akid) == X509_V_OK &&
        !ku_reject(x, KU_KEY_CERT_SIGN))
        x->ex_flags |= EXFLAG_SS;
}

So basically three things to check:

  • The subject name and the issuer name must match
  • The subject key identifier and the authority key identifier must match
  • The cert must contain a key usage extension with the KU_KEY_CERT_SIGN bit set

You are already comparing the subject name and the issuer name. The next important thing to do would be to compare the SKID and the AKID. After a cursory glance at pyopenssl it doesn't look like it provides a way to check this, so if you want a pure Python solution you might have to extend the library. However even the code you have would probably cover you in 95% of cases you said you wanted it to cover.

like image 95
mnistic Avatar answered Oct 10 '22 00:10

mnistic