💾 Archived View for thegonz.net › certRecs.gmi captured on 2024-07-08 at 23:37:49. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

Recommendations for changing your gemini server's TOFU certificate

So you want to change your certificate, but don't want users who've visited you before to get scary warnings? Here is what I advise.

There are two reasons you might want to change your certificate:

1: The key is fine, but the certificate is about to expire

In this case, I recommend keeping the same key but signing a new certificate with it. This way, gemini clients which do TOFU based on the key rather than the certificate will accept the new certificate without complaint.

Here's an openssl command to generate a long-lived new self-signed certificate new.crt for a key my.key for the domain example.net:

openssl req -key my.key -subj "/CN=example.net" -addext "subjectAltName = DNS:example.net" -new -x509 -days 2000000 -out test.crt

2: You want to change the key

Maybe you fear your key has been compromised, or the encryption it uses is out-dated and you want to switch to something more secure or efficient.

In this case, I recommend making a certificate for the new key which is signed by the old key rather than being self-signed. That way, anyone who has trusted the old key can transfer their trust to the new key. To my knowledge, at the time of writing, diohsc is the only client which does this automatedly. Perhaps other clients will implement this feature -- though it does require the client to store the whole public key when TOFU-trusting a certificate, rather than just a hash.

Here's an openssl recipe for generating a new key new.key and a certificate new.crt for the domain example.net, signed by old.key and old.crt:

openssl ecparam -genkey -name prime256v1 > new.key
openssl req -new -days 2000000 -x509 -sha256 -subj "/CN=example.net/GN=2" -addext "subjectAltName = DNS:example.net" -key new.key | \
    openssl x509 -CA old.crt -CAkey old.key -CAcreateserial -days 2000000 > new.crt

(If you eventually repeat this process, increment GN each time; the DN needs to be unique.)

Client support

I tested a few clients to see which support these methods of passing on trust to a new certificate. "Y" means that the client will accept (or recommend acceptance of) a certificate generated from a previously trusted key using the given method described above. "N" means that it acts as if the certificate has nothing to do with the previously trusted key.

                  |  1  |  2  | Date tested |
------------------+-----+-----+-------------+
Amfora            |  Y  |  N  |  2022-06-02 |
AV-98             |  N  |  N  |  2022-06-02 |
Diohsc            |  Y  |  Y  |  2024-06-12 |
gemini.koplugin   |  Y  |  N  |  2024-06-12 |
Lagrange          |  Y  |  N  |  2022-06-02 |

For bonus points...

The "-days 2000000" parameters here are an ugly compromise. As far as I can see, there is no reason to want your TOFU certificate to expire, so the correct thing to do according to RFC5280 is to set Not After to the maximal value 99991231235959Z to indicate that expiration does not apply. The openssl req command doesn't make this easy, but actually it can be done using libfaketime as follows:

faketime '1999-12-31 23:59:59' openssl req -days 2921940 ...