Package: cert-hero
Python Stand-alone Library to Download the SSL Certificate forAny Host™Documentation:https://cert-hero.readthedocs.io.Why Use?This libraryalwaysreturns the SSL certificate, if a server has one. This works for expired
andself-signed certificate, whereas the builtinssllibrary returns an emptydictif verification fails
for any reason (source).Theonlydependency isasn1crypto(with over 300 stars on GitHub), which is ~94% more lightweight and robust
than a solution withpyOpenSSL(chart).If a hostredirectsto another URL, this info is captured inLocationandStatus.Convenience methods such as__repr__()to make output more human-readable.Core Exportscert_please- Retrieve the SSL certificate for a given hostname.certs_please- Retrieve (concurrently) the SSL certificate(s) for a list of hostnames.set_expired- Helper function  to check (at runtime) if a cert is expired or not.Install$pipinstallcert-heroUsageFetch the SSL certificate for ahostwithcert_please():importcert_herocert=cert_hero.cert_please('google.com')print('Cert is Valid Till:',cert.not_after_date.isoformat())# To get the output as a JSON string, use `str(cert)` or remove `!r` from belowprint(f'Cert ->\n{cert!r}')cert_hero.set_expired(cert)print(f'Validity ->\n{cert["Validity"]}')Output (Sample)Cert is Valid Till: 2023-10-28
Cert ->
CertHero(
  {
    "Cert Status": "SUCCESS",
    "Serial": "753DD6FF20CB1B4510CB4C1EA27DA2EB",
    "Subject Name": {
      "Common Name": "*.google.com"
    },
    "Issuer Name": {
      "Country": "US",
      "State/Province": "California",
      "Organization": "Zscaler Inc.",
      "Organization Unit": "Zscaler Inc.",
      "Common Name": "Zscaler Intermediate Root CA (zscalerthree.net) (t) "
    },
    "Validity": {
      "Not After": "2023-10-28",
      "Not Before": "2023-10-14"
    },
    "Wildcard": true,
    "Signature Algorithm": "SHA256WITHRSA",
    "Key Algorithm": "RSA-2048",
    "Subject Alt Names": [
      "*.google.com",
      "*.appengine.google.com",
      "youtu.be",
      "*.youtube.com",
      ...
    ],
    "Location": "https://www.google.com/",
    "Status": 301
  }
)
Validity ->
{'Not After': '2023-10-28', 'Not Before': '2023-10-14', 'Expired': False}Fetch (concurrently) the SSL certificates formultiple hostswithcerts_please():importcert_herohost_to_cert=cert_hero.certs_please(['google.com','cnn.com','www.yahoo.co.in','youtu.be'])cert_hero.set_expired(host_to_cert)forhost,certinhost_to_cert.items():print(f'==={host.center(17)}===')# To get the output as a JSON string, use `str(cert)` or remove `!r` from belowprint(f'{cert!r}')print()Output (Sample)===     google.com    ===
CertHero(
  {
    "Cert Status": "SUCCESS",
    "Serial": "753DD6FF20CB1B4510CB4C1EA27DA2EB",
    "Subject Name": {
      "Common Name": "*.google.com"
    },
    ...
  }
)

===      cnn.com      ===
CertHero(
  {
    "Cert Status": "SUCCESS",
    "Serial": "7F2F3E5C350554D71A6784CCFE6E8315",
    "Subject Name": {
      "Common Name": "cnn.com"
    },
    ...
  }
)

===  www.yahoo.co.in  ===
CertHero(
  {
    "Cert Status": "SUCCESS",
    "Serial": "7D7FD7B7C2EE7146B4D4E43E36908B72",
    "Subject Name": {
      "Common Name": "src1.yahoo.com"
    },
    ...
  }
)

===      youtu.be     ===
CertHero(
  {
    "Cert Status": "SUCCESS",
    "Serial": "753DD6FF20CB1B4510CB4C1EA27DA2EB",
    "Subject Name": {
      "Common Name": "*.google.com"
    },
    ...
  }
)Usage as a CLIAfter the installation step you can use cert-hero just typingchin your terminal window.Thechcommand allows you to retrieve the SSL certificate(s) for one or more given host.For example:ch google.com cnn.comYou can get help about the main command using:ch --helpRationaleThe builtin Python modulesslcan be used to retrieve a certificate from a server viagetpeercert,
but it’ll work only if the certificate of interest can be successfully verified (source).If, for any reason, verification fails, like, for example, with expired or aself-signed certificate,
we’ll getssl.SSLCertVerificationErrorinstead of the requested info.We can work around this by asking for the certificate in the binary form:getpeercert(binary_form=True)But now we have to convert it, and thus we can use a third partyasn1cryptomodule, instead of
the (bulkier)cryptographymodule.CreditsThis package was created withCookiecutterand thernag/cookiecutter-pypackageproject template.