💾 Archived View for gemini.susa.net › gemini_prep_kit.gmi captured on 2023-09-08 at 15:54:28. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2022-05-25)

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

Minimum Gemini Survival Kit

For those times when all you have is a Unixy shell. I'll use the words prep, prepper, and prepping so it can be found via GUS when you need it most! Below are some seed URLs to might want to use to start exploring.

gemini://gemini.circumlunar.space/

gemini://gus.guru/

The following sections will cover 1) a minimal client, 2) creating a client certificate, 3) creating a server certificate. A client certificate is only used if you need to authenticate yourself, and a server certificate is only needed if you're running your own server.

Simplest Client

Here are some examples, each using a different TLS client utility.

echo -ne "gemini://g.susa.net/\r\n" | ncat --ssl g.susa.net 1965

echo -ne "gemini://g.susa.net/\r\n" | gnutls-cli --no-ca-verification --port=1965 g.susa.net

echo -ne "gemini://g.susa.net/\r\n" | openssl s_client -connect "g.susa.net:1965" -quiet

Create Client Certificate

You won't need this for general browsing, but if the server has protected resources, or if it needs to identify you between sessions, then client certificates are Gemini's neat way of doing this.

The subject's CN value would typically be your user-name.

# openssl allows us to do everything in a single line
openssl req -x509 -newkey rsa:2048 -nodes -keyout my.key -out my.crt -subj '/CN=kevinsan'

# certtool requires separate steps - key, template, then certificate
certtool -p --rsa --bits=2048 --outfile my.key
echo "cn = kevinsan" >/tmp/template
certtool -s --load-privkey my.key --outfile my.crt --template /tmp/template

The Simplest Client with Client Certificate

Just give your client certificate to whatever command you're using, and it will supply it to the server when it's requested.

echo -ne 'gemini://g.susa.net/private\r\n' | \
    ncat --ssl --ssl-cert ./my.crt --ssl-key ./my.key g.susa.net 1965

echo -ne 'gemini://g.susa.net/private\r\n' | \
    openssl s_client -connect g.susa.net:1965 -key my.key -cert my.crt -ign_eof -quiet

Create Server Certificate

This is almost identical to a self-signed client certificate.

The subject's CN value should be your server's hostname, or a wildcard domain. The client may check this and reject the session if your server's CN value is different from the hostname you're asking it to fetch from.

# The openssl approach
openssl req -x509 -newkey rsa:2048 -nodes -keyout serv.key -out serv.crt -subj '/CN=*.susa.net'

# The certtool approach
certtool -p --rsa --bits=2048 --outfile serv.key
echo "cn = *.susa.net" >/tmp/template
certtool -s --load-privkey serv.key --outfile serv.crt --template /tmp/template

Elliptic Curve Keys

If you prefer elliptic curves over big primes, then use the following examples (I link to the original source).

gemini://makeworld.gq/gemlog/2020-07-06-openssl.gmi

# Simple server key, corresponding to the RSA example above
openssl req -new -subj "/CN=g.susa.net" -x509 -newkey ec -days 36500 \
    -pkeyopt ec_paramgen_curve:prime256v1 -nodes -out serv.crt -keyout serv.key

# makeworld's example below supports multiple hosts/domains
openssl req -new -subj "/CN=example.com" \
    -addext "subjectAltName = DNS:example.com, DNS:example2.com" \
    -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
    -nodes -out cert.pem -keyout key.pem

The following, for reference only, generates key using the curve 25519 (which as I understand it is not widely supported yet, despite being computationally much simpler than other curves.

# Generate a private key
openssl genpkey -algorithm X25519 -out private.pem

# Generate a public key
openssl pkey -in private.pem -pubout -out public.pem

I intend to generate a certificate from a 25519 key to see what clients/servers work well with it, but my current Debian version doesn't seem to have a recent enough version to do this. On the back burner I suppose...

A good article on ED25519 certificates.

Check a Certificate

You can use s_client to connect to a server's port, which by default will display the certificate details. If you include -servername, then the appropriate host will be set in the Server Name Indication (SNI) details of the request.

# Check the default certificate on an IP
openssl s_client -connect example.com:1965

# Check certificate on an IP for a specific SNI host
openssl s_client -connect example.com:1965 -servername 'example.com'

Bear in mind that the purpose of SNI is to allow the appropriate certificate to be used during TLS negotiation. It is mandatory in the Gemini specification, so any client that doesn't specify the SNI is not Gemini compliant.

Some further reading

An interactive breakdown of a TLS connection.