💾 Archived View for gemi.dev › gemini-mailing-list › 000059.gmi captured on 2023-12-28 at 15:40:31. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-11-04)
-=-=-=-=-=-=-
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?
[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:
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
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
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
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
---