-- Leo's gemini proxy

-- Connecting to gemini.thegonz.net:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini

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 -- but hopefully other clients will implement this feature eventually.


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. The latest versions as of 2022-06-02 were tested. "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  |
---------+-----+-----+
Amfora   |  Y  |  N  |
AV-98    |  N  |  N  |
Diohsc   |  Y  |  Y  |
Lagrange |  Y  |  N  |

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 ...

-- Response ended

-- Page fetched on Sat May 4 11:20:35 2024