SSL Certificate Fingerprints

Software can extract fingerprints from SSL certificates, and use the fingerprints to authorize or verify the other end of the connection. This may be done either by servers--such as a SMTP server that allows relay for certificates that have particular fingerprints--or by clients, such as Trust On First Use (TOFU) used by gemini clients to associate a certificate with a server.

more on certificates

Fingerprints do not scale unless the process is largely automated; it is more common to trust certificates signed by a particular Certificate Authority (CA)—minus any present on a Certificate Revocation List—so that the software or, worse, humans need not fiddle with things every time a certificate changes. Of course certificate authorities are not without problems--can you always trust all of the CA in a typical browser?

one way to setup a local CA

The fingerprint is generally specific to an application or library so may not be portable unless pains are taken to derive the fingerprint the same way. Here is the amfora author on the topic:

The way to store cert data is not standardized, but my recommendation is a SHA-256 hash of the entire *binary* cert, or preferably, a SHA-256 hash of the binary "Subject Public Key Info" (SPKI) section of the cert.
...
As for why just hashing the SPKI is preferably, it's because that is the part of the certificate that stores the public key type, and the public key itself. If that part of the cert has not changed, then it doesn't matter if other parts of the cert have, like the signature algorithm or the serial number, because you know the same person is making the connection, because they still have control of that keypair.

gemini://makeworld.space/gemlog/2020-07-03-tofu-rec.gmi

https://github.com/makeworld-the-better-one/amfora

This perhaps bears some scrutiny. The code can be found in client/tofu.go, here extracted into a standalone script, certid.go, and replicated into the Perl script certid.pl for some OpenSSL flavor.

certid.go

certid.pl

thrig.pem

    $ go build certid.go
    $ ./certid thrig.pem
    old  35B73040D25807B6AB78AF29CB286044F79EC36569227E665A8615112BAB9028
    new  8E45637224E2FD37B21EA39CBC94FFB135AB25D1445CFAA6A7359BA5E2BE2398
    $ ./certid.pl thrig.pem
    35:B7:30:40:D2:58:07:B6:AB:78:AF:29:CB:28:60:44:F7:9E:C3:65:69:22:7E:66:5A:86:15:11:2B:AB:90:28
    8E45637224E2FD37B21EA39CBC94FFB135AB25D1445CFAA6A7359BA5E2BE2398
    $ grep thrig ~/.cache/amfora/tofu.toml
    "thrig/me" = "8E45637224E2FD37B21EA39CBC94FFB135AB25D1445CFAA6A7359BA5E2BE2398"
    "thrig/me/expiry" = 2296-10-03T19:35:58Z

This shows that the X509_get_fingerprint call in the Net::SSLeay module digests the same data as the origCertID code from amfora. More interesting may be to generate new certificates that do not change the fingerprint for the new certId code in amfora. This requires a private key, which I am not sharing here.

    $ cat recert
    #!/bin/sh
    openssl req -x509 -new -sha256 -days 99 -nodes -key thrig.key \
    -out "$1".cert -subj "/CN=thrig.me" -addext \
    "subjectAltName=DNS:thrig.me,IP:104.207.156.138,IP:2001:19f0:8001:143b:5400:4ff:fe1a:8ed6"
    $ ./recert foo
    $ ./certid foo.cert
    old  7316EC6EDF37A539299AD6D468CB23CE276031E6EEF35BC6085290F81909D73F
    new  8E45637224E2FD37B21EA39CBC94FFB135AB25D1445CFAA6A7359BA5E2BE2398
    $ openssl x509 -noout -dates < thrig.pem
    notBefore=Dec 20 19:35:58 2022 GMT
    notAfter=Oct  3 19:35:58 2296 GMT
    $ openssl x509 -noout -dates < foo.cert
    notBefore=Apr 12 21:08:46 2023 GMT
    notAfter=Jul 20 21:08:46 2023 GMT

This shows that a new certificate with a different expiration date will be verified as the same certificate by amfora. A gemini client that verifies the entire certificate will see a new fingerprint. Therefore, gemini clients probably should use the amfora form and only checksum the subject public key information section.

index.gmi