Client certificates

1. Julien Blanchard (julien (a) typed-hole.org)

Hello Geminauts,
When trying to implement client certificate support in my client I 
wondered whether or not we would want to be able to use different 
certificates for different gemini places?
I figured why not so started I my implementation by searching for a 
certificate that matches the host domain name like 
astrobotany.mozz.us.key and astrobotany.mozz.us.crt.
Does it make sense? Where should one put its certificates if such a 
place exists in a filesystem?

Link to individual message.

2. Ciprian Dorin Craciun (ciprian.craciun (a) gmail.com)

[Disclaimer:  I'm not directly involved in Gemini development or
ecosystem, but I follow closely these developments.]


On Mon, Apr 20, 2020 at 12:23 AM Julien Blanchard <julien at typed-hole.org> wrote:
> When trying to implement client certificate support in my client I
> wondered whether or not we would want to be able to use different
> certificates for different gemini places?

I would definitively want to have different "personas" for different
sites.  In fact even for the same site I would like to have different
ones, for example:  one for administrative purposes, and one for
normal (but authenticated) access.



> I figured why not so started I my implementation by searching for a
> certificate that matches the host domain name like
> astrobotany.mozz.us.key and astrobotany.mozz.us.crt.
> Does it make sense? Where should one put its certificates if such a
> place exists in a filesystem?


Automatically choosing a client certificate and presenting it to the
server, I believe is a bad idea from a privacy perspective.  I would
implement something like this:  when connecting to a domain for which
one could use a client certificate, ask the user the first time if he
wants to:

but prefers to confirm it for each new "tab" (or browsing context);
(i.e. sort of "last-used" but "confirm";)


Ciprian.

Link to individual message.

3. solderpunk (solderpunk (a) SDF.ORG)

On Mon, Apr 20, 2020 at 04:02:00PM +0300, Ciprian Dorin Craciun wrote:
 
> On Mon, Apr 20, 2020 at 12:23 AM Julien Blanchard <julien at typed-hole.org> wrote:
> > When trying to implement client certificate support in my client I
> > wondered whether or not we would want to be able to use different
> > certificates for different gemini places?
> 
> I would definitively want to have different "personas" for different
> sites.  In fact even for the same site I would like to have different
> ones, for example:  one for administrative purposes, and one for
> normal (but authenticated) access.

Yes, absolutely the idea is that different certificates would be used to
identify the client to different servers.  A universal client
certificate would allow server admins to compare logs and track users.

Possibly this question was provoked by the way the (wonderful!)
astrobotany app advices people to use client certs with AV-98, where you
provide a cert path when starting AV-98 and it's used for everything.  I
should clarify that this way of handling client certs was added to AV-98
as a kind of quick-and-dirty way to get the astrobotany app usable.
It's not supposed to be the standard way of using client certificates.

> > I figured why not so started I my implementation by searching for a
> > certificate that matches the host domain name like
> > astrobotany.mozz.us.key and astrobotany.mozz.us.crt.
> > Does it make sense? Where should one put its certificates if such a
> > place exists in a filesystem?

Transient certificates are explicitly bound to a domain in the spec.
Nothing is said about non-transient certificates, but I guess it makes
sense that they would work similarly.  The META part of response headers
with status 6x have no explicit semantics yet - it's possible we could
implement a syntax for binding certificates to subdomains?  Or even
paths?

I should remind myself how this works for cookies...
 
> Automatically choosing a client certificate and presenting it to the
> server, I believe is a bad idea from a privacy perspective.  I would
> implement something like this:  when connecting to a domain for which
> one could use a client certificate, ask the user the first time if he
> wants to:
> * always use the same certificate for that particular domain;
> * wants to use a particular certificate (assuming there are multiple),
> but prefers to confirm it for each new "tab" (or browsing context);
> (i.e. sort of "last-used" but "confirm";)
> * never use any certificate;

Bugging the user about certs upon each connection to a new domain would
be a pretty unpleasant user experience!  I would expect clients not to
use client certificates by default and not to ask the user about client
certificates until receieving a response with a status of 60, 61 or 62.

When a user opts to generate a new non-transient certificate to send to
a site, I guess it would be handy if the client offered a "Remember me"
option, such that the same certificate would then automatically be used
for all connections to that domain (which would involve saving the key
and certificate to disk, presumably in some client-specific location).
This way one could automatically and invisibly log in to places like
astrobotany on each visit.  One of course could reverse this decision at
any time.

While we're talking details on client certificates - I never envisaged
client certificates being signed by the server they're destined for.
This does no harm, but it also does no good, either, if the server signs
them without any kind of validation process.  In general I don't see a
need for it and it just adds a lot of friction to the "signup process".
But, I'm aware that lots of TLS libraries are very inflexible when it
comes to certificate validation, and accepting self-signed client
certificates may not be possible - I wouldn't be surprised if this was
the cause for astrobotany, since Python's standard library is precisely
one of these inflexible ones...

Cheers,
Solderpunk

Link to individual message.

4. Michael Lazar (lazar.michael22 (a) gmail.com)

On Mon, Apr 20, 2020 at 2:20 PM solderpunk <solderpunk at sdf.org> wrote:
> While we're talking details on client certificates - I never envisaged
> client certificates being signed by the server they're destined for.
> This does no harm, but it also does no good, either, if the server signs
> them without any kind of validation process. In general I don't see a
> need for it and it just adds a lot of friction to the "signup process".
> But, I'm aware that lots of TLS libraries are very inflexible when it
> comes to certificate validation, and accepting self-signed client
> certificates may not be possible - I wouldn't be surprised if this was
> the cause for astrobotany, since Python's standard library is precisely
>one of these inflexible ones...

To be honest, I never even considered doing it that way. Assuming I have
access to a half-decent TLS library, does this flow make sense for self-signed
client certificates?

- The client requests "gemini://astrobotany.mozz.us/" and receives a
  "62 AUTHORISED CERTIFICATE REQUIRED" response.
- The client generates a self-signed certificate and makes a second request to
  the same endpoint. This certificate generation could be done through the
  gemini client software itself, or the user could provide their own cert.
- The server accepts the self-signed client certificate and saves a hashed
  fingerprint of the peer cert. This fingerprint is now associated with that
  user and represents a unique UUID that nobody else can spoof.
- We kick the can down the road concerning the user needing to update or
  re-associate their client certificate. We hope that they set an expiration
  date far enough in the future for this to never matter.

Are there any flaws that I'm not seeing here? I actually like this a lot more
than the current solution now that I look at it.

- Michael

Link to individual message.

5. solderpunk (solderpunk (a) SDF.ORG)

On Mon, Apr 20, 2020 at 06:02:32PM -0400, Michael Lazar wrote:
 
> - The client requests "gemini://astrobotany.mozz.us/" and receives a
>   "62 AUTHORISED CERTIFICATE REQUIRED" response.
> - The client generates a self-signed certificate and makes a second request to
>   the same endpoint. This certificate generation could be done through the
>   gemini client software itself, or the user could provide their own cert.
> - The server accepts the self-signed client certificate and saves a hashed
>   fingerprint of the peer cert. This fingerprint is now associated with that
>   user and represents a unique UUID that nobody else can spoof.
> - We kick the can down the road concerning the user needing to update or
>   re-associate their client certificate. We hope that they set an expiration
>   date far enough in the future for this to never matter.

Yes, this is more or less precisely as I imagined it working!

With "nice" clients, the user basically gets a prompt like "Would you
like to create a persistent identity for this service? Y/N", and if Y,
the client itself generates and saves a self-signed certificate to use
without the user having to drop to the commandline and use openssl
commands.  The cert is associated with a particular domain and, if the
client is set up to do so, can be used automatically for all requests
to that domain.  This gives a pretty fluid user experience: the user
doesn't need to understand anything technical about TLS at all.  They
just get a transparently working account which is basically bound to
the device/client they used at sign up (advanced users of course can
export/import cert-key pairs to multiple devices).  No passwords to
forget, or to be brute-forced.  Even a full compromise of the server's
database does not allow account hijacking, even with all the rainbow
tables and time in the world, because the private key never leaves the
client.  Of course, good backups of the cert-key pairs becomes
essential to avoid getting locked out of things after a disk
failure...

You raise good points about cert expiry.  Let's think about that.

Cheers,
Solderpunk

Link to individual message.

6. Alex Schroeder (alex (a) gnu.org)

People on the #gemini IRC channel and on Mastodon might have seen me
struggle with client certificates on the server side and it occured to
me that I didn't post my solution to the list so here it is.

Background: I'm using Perl, with a library that uses OpenSSL bindings
in the background, so as you dig deeper, you soon end up reading the
OpenSSL documentation...

Longer write-up:
gemini://alexschroeder.ch/page/2020-07-
13_Client_Certificates_and_IO%3A%3ASocket%3A%3ASSL_%28Perl%29

Short version:

In the TOFU world, the default OpenSSL setup doesn't quite work. The
default is that clients don't send their client certificates to the
server unless the server asks for them during the handshake. In the
OpenSSL world, the server can be told to do this by telling it to
verify the client certificate. When you do that, the server will then
reject the connection because the client certificate is self-signed. In
order to force the server to still accept it, you need to provide your
own verification callback which simply returns 1 for all certificates
in the chain of certificates the client presents you with.

"SSL_set_verify() sets the verification flags for ssl to be mode and
specifies the verify_callback function to be used. If no callback
function shall be specified, the NULL pointer can be used for
verify_callback. In this case last verify_callback set specifically for
this ssl remains."
https://www.openssl.org/docs/manmaster/man3/SSL_set_verify.html

Keywords to look for in your SSL or TLS library's documentation are
"peer verification", "verification mode", "verification callback", etc.

Once you have all that, then you can get the fingerprint of the client
cert on the server side and compare it to the list of fingerprints you
know (if you're trying to only allow some people access), or save the
combination of fingerprint and common name in your database if you want
to create an account (like astrobotany does), or send a 60 code back if
there is no certificate, or a 61 code if the fingerprint doesn't match
anything in your database, or a 62 if you decide to do further tests
such as checking the validity start date or the expiry date of the
client certificate.

Hope that helps somebody
Cheers
Alex

Link to individual message.

---

Previous Thread: IRC

Next Thread: Gemini mentioned on Hacker News and Lobsters