Peter Vernigorov pitr.vern at gmail.com
Sun Jul 19 22:27:18 BST 2020
- - - - - - - - - - - - - - - - - - -
Thanks for the reply Alex. My understanding is that your blog posttalks about how to get the server to request that the client sends thecertificate, and you are right that many Gemini servers don’t usuallydo that. When writing Gig framework - https://github.com/pitr/gig -and having the same issue, I noticed that most Go-based Gemini serversout there don’t do this but a quick search showed that it’s just amatter of one line change to get it working properly:
&tls.Config{ MinVersion: tls.VersionTLS12, ClientAuth: tls.RequestClientCert // <-- this line, default is NoClientCert}
Anyhow, when the client DOES send the certificate, it seems to do itin plain text. See this excerpt from TLS handshaking:
...- The server sends its ServerKeyExchange message (depending on theselected cipher suite, this may be omitted by the server)....- The client responds with a Certificate message, which contains theclient's certificate....- The client now sends a ChangeCipherSpec record, essentially tellingthe server, "Everything I tell you from now on will be authenticated(and encrypted if encryption was negotiated)."...
Notice how the certificate is sent before client starts encryptingmessages. This means that the CN (and other) fields are also in plainview and therefore cannot contain secret information.
On Sun, Jul 19, 2020 at 10:03 PM Alex Schroeder <alex at gnu.org> wrote:
On Sun, 2020-07-19 at 21:26 +0200, Peter Vernigorov wrote:
I am trying to implement a simple authentication for my Gemini site,
and was planning to use a client certificate CN field to pass
username:password pair to server. However, upon reading closely about
the TLS handshake -
https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_handshake
-
it seems that the client (just like the server) certificate is sent
before the ChangeCipherSpec record, i.e. insecure. That means to me
that the CN field would be passed before the TLS session is started
and therefore not suitable as an authentication medium. Is that
correct?
Well, my experience is that you tell the server that you want to verify
peer certificates (which is typically off for servers); then the client
sends you a server that won't validate if you do nothing else: you have
to overwrite the default validation code and return True for
everything. Then your code gets the client certificate and now you can
do the real validation in your app instead of on the TLS layer.
Here's a long blog post:
https://alexschroeder.ch/wiki/2020-07-13_Client_Certificates_and_IO%3a%3aSocket%3a%3aSSL_(Perl)
Here's where I tell my server that I want to verify peers (client
certificates) and that I will provide my own verification code:
https://alexschroeder.ch/cgit/gemini-wiki/tree/gemini-wiki#n758
Here's the verification code for the TLS library which accepts
anything:
https://alexschroeder.ch/cgit/gemini-wiki/tree/gemini-wiki#n775
Here's some example code that does actual validation, requests a client
certificate if none is available, etc:
https://alexschroeder.ch/cgit/gemini-wiki/about/#client-certificates
Good luck!
And yes, I'm using more traditional access tokens for my wiki per
default.