tls

Look at the TLS (https) side of a server: tls.certificate(host) fetches and describes its certificate (subject, issuer, dates, names, whether it is trusted), tls.versions(host) tries each TLS version, and tls.check(host) gives a verdict (expiry, hostname match, trust). No data is sent beyond the handshake. Only check servers you own or have written permission to test. Checking other people's systems can be against the law.

This library connects to servers to read their certificates, so it needs the TB app on your computer. The examples here show the code; run them with tb file.tb.

import tls

Example

Needs the TB app on your computer, so there is no Run button here.

import tls

# Only check servers you run or are allowed to test.
let c = tls.check("example.com")
say(c.ok, c.days_left, c.issuer.common_name)
for issue in c.issues {
  say("issue:", issue)
}

Functions

certificate(host, port?, options?)

returns map

Fetch a server's certificate and describe it. host may also be "host:port" or an https:// URL.

Returns a map with

  • "pem" the certificate as PEM text.
  • "subject", "issuer" maps with common_name, organization...
  • "not_before", "not_after" when it starts and stops being valid.
  • "days_left", "expired" how long it has left.
  • "san" the names it covers.
  • "serial" the serial number.
  • "verified" true if this computer trusts it. "verify_error" says why not.
  • "self_signed", "hostname_matches" true or false.
  • "version" the TLS version used, like "TLSv1.3".
  • "cipher" the cipher used.
  • "parsed" the crypto library's full x509 parse, when available.

Options

  • timeout seconds to wait (default: 5).
  • server_name the name to ask for (SNI).
  • ca_file a PEM file of certificates to trust.

Only check servers you own or have written permission to test. Checking other people's systems can be against the law.

Visualizehow tls.certificate works

tls.certificate("example.com", 443) gives {"subject": {"common_name": "example.com"}, "issuer": {"organization": "DigiCert Inc"}, "…

tls.certificate: your computer talking to another oneyour computerserverexample.com443httpssends: TLS hellogets back: its certificateresult · mapsubject{"common_name": "example.com"}issuer{"organization": "DigiCert Inc"}days_left74expiredfalseversion"TLSv1.3"

Illustration: example values, drawn from what the function does.

versions(host, port?, options?)

returns map

Which TLS versions the server accepts.

Returns a map of version name -> answer, like {"TLSv1.0": false, "TLSv1.1": false, "TLSv1.2": true, "TLSv1.3": true}.

  • true the server accepts it.
  • false the server refuses it.
  • nil this computer's OpenSSL can't even try it.

Old versions (1.0, 1.1) being on is a finding.

Only check servers you own or have written permission to test. Checking other people's systems can be against the law.

Visualizehow tls.versions works

tls.versions("example.com", 443) gives {"TLSv1.0": false, "TLSv1.1": false, "TLSv1.2": true, "TLSv1.3": true}

tls.versions: your computer talking to another oneyour computerserverexample.com443httpssends: try 1.0, 1.1, 1.2, 1.3gets back: accepted?result · mapTLSv1.0falseTLSv1.1falseTLSv1.2trueTLSv1.3true

Illustration: example values, drawn from what the function does.

check(host, port?, options?)

returns map

A verdict on a server's TLS.

Returns a map with

  • "ok" true if no issues were found.
  • "issues" a list of texts, one per problem.
  • "host", "port" the server checked.
  • "days_left", "expires" when the certificate runs out.
  • "verified", "hostname_matches", "self_signed" true or false.
  • "version", "cipher" what the connection used.
  • "issuer", "subject" who the certificate is from and for.

Issues it looks for

  • The certificate is not trusted.
  • The name does not match.
  • It has expired, or expires within warn_days.
  • An old TLS version was used.

Options (as for certificate(), plus)

  • warn_days warn when fewer days than this are left (default: 30).

Only check servers you own or have written permission to test. Checking other people's systems can be against the law.

Visualizehow tls.check works

tls.check("example.com", nil, {"warn_days": 30}) gives {"ok": true, "issues": [], "days_left": 74, "verified": true, "version": "TLSv1.3"}

tls.check: your computer talking to another oneyour computerserverexample.comsends: TLS hellogets back: certificateoptions?warn_days30result · mapoktrueissues[]days_left74verifiedtrueversion"TLSv1.3"

Illustration: example values, drawn from what the function does.

parse_pem(pem)

returns map

Describe a certificate you already have as PEM text.

Returns a map with "subject", "issuer", "not_before", "not_after", "days_left", "expired", "san", "serial" and "self_signed", as for certificate().

Visualizehow tls.parse_pem works

tls.parse_pem(fs.read("cert.pem")) gives {"subject": {"common_name": "example.com"}, "issuer": {"common_name": "R11"}, "not_after"…

tls.parse_pem: inputs flowing into the function and the resultpem-----BEGIN CERTIFICATE-----MIIF…-----END CERTIFICATE-----tls.parse_pemresult · mapsubject{map}common_name"example.com"issuer{map}common_name"R11"not_after"2027-01-09"days_left74self_signedfalse

Illustration: example values, drawn from what the function does.

Values

NameValueWhat it is
tls.versions_known["TLSv1.0", "TLSv1.1", "TLSv1.2", "TLSv1.3"]

The TLS version names versions() reports.

Visualizehow tls.versions_known works

tls.versions_known gives ["TLSv1.0", "TLSv1.1", "TLSv1.2", "TLSv1.3"]

The value tls.versions_knowntls.versions_known"TLSv1.0""TLSv1.1""TLSv1.2""TLSv1.3"what it isThe TLS version names versions() reports.

No inputs: call it as it is.

Real value, read from TB while the site was built.