I see, Gemini is not to make the life of content creators easier, but the life of the server and client implementers.
The need for TLS is a bit strange regarding this, especially if they encourage the use of self-signed certificates.
4 TLS
Use of TLS for Gemini transactions is mandatory.
Clients can validate TLS connections however they like (including not at all) but the strongly RECOMMENDED approach is
to implement a lightweight "TOFU" certificate-pinning system which treats self-signed certificates as first- class
citizens. This greatly reduces TLS overhead on the network (only one cert needs to be sent, not a whole chain) and
lowers the barrier to entry for setting up a Gemini site (no need to pay a CA or setup a Let's Encrypt cron job,
just make a cert and go).
My understanding of the issue as it relates to Gemini is that the Gemini community is:
1. Largely using self-signed certificates on the servers. That gets you into the protocol, but doesn't really help with trust.
2. Using "trust on first use" (TOFU) in the clients, which doesn't scale. The clients have to know whether a particular cert is valid or not, and that means the user needs to manually verify or some trusted data source has to be distributed to clients. Manual verification turns into "yeah, yeah, just let me read the page" after a while. And a trusted data source is, well, hard to keep maintained, and even harder if it wasn't in the model from the start.
So TLS gets Gemini security, of a sort, but the way it's being used makes it less effective than it should be.
The push for TOFU really only began about a year after the protocol was first designed, as it was deemed "too difficult" to obtain a real certificate, even from Let's Encrypt.
On the other hand, those that want something SSH-like for the web have something to point to as an example, as well as those that don't think SSH-like for the web is a good idea as an example.
TLS gives you protection against casual eavesdropping or tampering.
Of course, self-signed certs + TOFU theoretically allow a third party to insert itself as a MITM at the first connection. This needs a lot of tracking and preparation beforehand; no adversary of this caliber is going to be interested in Gemini content.
Adversary of what caliber? All they have to be able to do is redirect a host (for instance by poisoning a local DNS lookup); the actual exploit is trivial. They're self-signed certificates; in the absence of a "TOFU" scheme that doesn't yet meaningfully exist, they provide no security against attackers willing to spoof DNS responses.
"TOFU" is also a truly abysmal fit for any application with a mass audience (at any given time, a huge percentage of your inbounds are going to be people making their first request, all totally open to attack --- contrast that with SSH, where you make first contact with a host on a new machine fairly rarely).
That's not really true, though. Like with SSH, the first time you receive a certificate for a server you are prompted to either trust it or not. If you choose to trust it then from that point on it remains trusted unless explicitly removed from the set of known hosts. Of course, the client could just take the option away from the user and automatically trust every host the first time. But then there's even less point in having TLS here.
Even Signal's TOFU method offers a way for users to manually verify that the keys of the people they're communicating with, even though it permits communication from the start without verification.
I understand that the admonition "never roll your own crypto" (as in develop your own encryption algorithm) is distinct from "never implement crypto on your own" (as in implement an existing encryption algorithm), although it is commonly misread as the latter.
The phrase "never roll your own crypto" was originally used in the context of algorithms.
Hopefully given the description / source code of "a published, well-used, tried-and-tested algorithm", most programmers could implement it in a language with which they are familiar.
I think it even applies to "never implement crypto on your own"---are you sure you've taken into account side-channel attacks? Timing attacks? Random number generation (if it's required)? Cleaning memory after use? That memset() isn't optimized out? There's a lot to get right ...
There's large class of exploits that appear despite the implementation having identical input-output behavior to a correct one -- a side-channel-free software implementation of AES is quite non-intuitive (bitslicing), and not the sort of thing I think most programmers could implement performantly. Worse than AES is RSA; there are a _ton_ of attacks that are subtle enough, that professional cryptographers' implementations end up being vulnerable (see [0]).
More recent algorithms (I'm thinking of ChaCha20 in particular, but there are quite a few others) are explicitly designed such that there shouldn't be any "more obvious" implementation than the secure one, but the programmer needs to know to implement them. I don't _think_ I've seen or heard of a vulnerable "rolled my own AES" since everyone started shipping AES in hardware, but people roll their own RSA all the time. I've had "write RSA" as a class assignment twice, and neither time was "don't use this for _anything_, you're definitely vulnerable to 20+ years of attacks" brought up.
Two things- one, as a sibling comment's mentioned, it absolutely includes implementation of cryptographic primitives too. There are quite a few subtle bugs (mostly, but not entirely, side-channels) that end up being utterly catastrophic.
Second - even using somebody else's (high-quality, trusted) implementation of (high-quality, trusted) primitives very much isn't enough to build a secure system that uses cryptography. The obvious example here is everybody and their dog going off to implement AES or something, not using a MAC ("we just care about secrecy, not integrity") or using a MAC wrong (e.g. MAC-then-encrypt), and then dying horribly to a trivial padding oracle.
Or, trying to build a secure transport protocol (i.e. a TLS-like API, where you just get "a secure socket" after doing some dance with certificates/keypairs)... you just encrypt (and MAC, this time) all the data before you send it out, and decrypt (and verify!) all data that comes in. But... wait, our API can't really handle that easily - we have to write the data out to the network in chunks. So, hm, encrypt and MAC each chunk? Oh, then chunks can be rearranged in transit, so we'll put a counter in there. What if the counter wraps around? Do you abort, or do you just reuse old counter values? Do you get a different session key for the same (client, server) pair- if not, is that an issue? Suppose you're using an AEAD mode, like GCM- how do you manage nonces? (If you reuse a nonce once in GCM, you often leak your authentication keys(!))
Hm, all of that sounds like ... a lot. So maybe we'll just sign+encrypt requests (and include our public key inside), and have the server sign+encrypt responses (to the public key we sent). Hm, but we need to tie responses to requests, though. So we'll need to put a hash of the request in the response. Ah, hmm, length extension attacks, right. Maybe GCM will save us? Hm, not sure... What if somebody wants to replay old content to us (send us an older version of a page)? Can they do that? Right, need to either include some "challenge"/nonce in requests, or at least make sure session keys are unique per-request. What about possible reflection attacks - if we send the server its own public key as our public key, does that cause any weirdness? Oh, what is a public key, anyways? If (God forbid) you're using RSA, does that include both the exponent and the modulus, or just the modulus? If you do a key exchange (e.g. for forward secrecy), who picks the parameters- are they just fixed?
Cryptography is the sort of thing that almost actively resists abstraction, and it's really tricky in a way that's hard to appreciate. It's a world where you find a claw hammer and use it to remove a nail from your floor- maybe even looking on CarpentryOverflow first to make sure a claw hammer can be used to remove nails from floors- and it works fine, so you then go to remove a nail from your wall and discover that this makes the hammer burst into flames because, yes, most people think "claw hammers can pull nails out of stuff" and that's usually true but the unstated assumption there is that you're holding the hammer with your right hand and you're actually left-handed and it's a Tuesday in the southern hemisphere so you actually should have used a completely different tool or used a higher-level misuse-resistant nail-pulling API which does almost exactly what you want, but that's what you thought the hammer did so...
> I see, Gemini is not to make the life of content creators easier, but the life of the server and client implementers.
As far as I understand, the distinction (content creator on the one hand, server and client implementers on the other) goes against the Gemini philosophy. The idea is rather that it should be reasonably easy to be both.
The need for TLS is a bit strange regarding this, especially if they encourage the use of self-signed certificates.
https://gemini.circumlunar.space/docs/specification.gmihttps://gemini.circumlunar.space/docs/best-practices.gmi