2

I would like to implement kind of a trust-on-first-use (TOFU) scheme with TLS:

  • A client creates a key and a self-signed certificate.
  • The client connects to the server with this certificate.
  • The server accepts the connection and stores something about the client
  • Assuming that this first connection was not MITM'd, I want to be able to verify that the next connection comes from the same client.

Is this possible? And if yes, what is that something I have to store from the first connection to be able to verify the second connection?

In practice I am using the Golang TLS library so I think this is the information I have about the connecting certificate.

  • TOFU is mainly used for clients connecting to an unknown server, not for servers receiving connections from unknown clients. Think SSH, the first time you connect to a server it issues a warning on the client, not on the server. Perhaps you confused the concepts? – Purefan Mar 6 '17 at 13:32
  • @Purefan I used "client" for the endpoint that is initiating the connection, but I think it would work just the same with the words client/server swapped, wouldn't it? – AndreKR Mar 6 '17 at 13:41
  • Well its a bit different, because the client is the one initiating the connection, there's an inherent trust in the server because I am connecting to it, but for the server it is the one allowing a connection to itself and thus needs to auth it, cant trust everyone because it cant predict who will connect to it – Purefan Mar 6 '17 at 13:47
  • Comes from the same server? Don't you mean from the same client? – Ajedi32 Mar 6 '17 at 14:21
  • @Ajedi32 Yes, sorry. – AndreKR Mar 6 '17 at 15:32
3

Since you are using TLS with client certificates and want to detect if the same client with the same certificate connects again you can simply store the client certificate or the pubkey contained in the certificate, or a fingerprint (hash) of these. Since based on your description the key and thus the certificate are generated at the client and are unique for the client any of the mentioned features should be uniquely identify the client. And since only the owner of the private key (i.e. the client) can use the matching certificate for authentication against the server it is also impossible that just the knowledge of the fingerprint or certificate allows an attacker to impersonate the client.

5

Rather than design your own scheme for this, you could look into JWT using x509: https://jwt.io/introduction/.

Oauth also has this kind of option (I think), but I can't find decent documentation.

I think there are some aspects of your solution that seem problematic currently - notably, rather than storing something on the server per client, using x509 means you only need to validate the client-presented cert is correctly issued, rather than needing to do more complex checks.

There is no need (AFAIK) for the certs you issue to your clients to be valid outside of your own environment (i.e. you can use your own CA for this), so that you could have your flow as:

  • client requests a cert based on a CSR it generates (similar to Oauth)
  • if the client request is properly authenticated, the CSR is processed into a valid cert for your needs
  • the client then stores this cert, and presents it when needed
  • the server validates that cert is valid, and extracts its public key for its own needs (if any).

So, yes, what you propose may be possible, but there seem to be some established schemes that provide a similar approach already, and which might be worthwhile looking into.

  • I don't really understand how JWT solves my problem. Sending a CSR to the server to sign seems like a feasible method though. – AndreKR Mar 6 '17 at 19:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.