Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SSL and public key security

I'm consuming a web service from an Android device using HTTP(s) with SSL. A self-signed (untrusted) certificate is used for client authentication.

I have a general understanding of how public/private keys are used for SSL. From my understanding I can clearly see how a certificate can be used to set up a secure connection and transmit data securely. However I do not understand how they are used for client authentication since the certificate contains the public key and is not kept a secret.

I have a few questions:

Where can I read about how SSL and certificates can be used for client authentication?

Even if the certificate was not made public...by visiting the HTTPS URL in a browser I can view and save the certificate. I can then package up the certificate in a key store and use it from an application.

In this post Jeremy Huiskamp writes

client auth will automatically be performed when the server requests it

...so client authentication as well as encryption of data can be performed with certificates?

Edited to answer the first part of my question: The client keystore should contain not only the server's public key but also the client's private key. The server must then be able to decrypt using the client's public key? Does this mean the keystore should have two certificates?

like image 263
Jack Avatar asked Oct 31 '11 02:10

Jack


1 Answers

First, a quick point about the terminology in public key cryptography:

  • you sign and decrypt/decipher using a private key,
  • you verify (a signature) and encrypt/encipher using a public key.

(You don't really "decrypt" using a public key.)

Using SSL/TLS with or without client-authentication, the server presents a certificate (*) for which it has the private key. The server sends its certificate during the SSL/TLS handshake (at the beginning of the connection) and is able to decipher what the client sends using its private key (which it keeps private). The private key and certificates are stored in the server's keystore (or equivalent if it's not implemented in Java).

As part of this, the client uses its truststore, which is a form a keystore that contains trusted certificates, to verify the server certificate. The server certificate could be trusted by being explicitly in the truststore or, in most cases, trusted by linking in to a trusted CA certificate in the truststore (PKI).

The terminology between keystore and truststore in Java can be a bit confusing, you can find more details in this answer.

Regarding your question, the client's truststore doesn't contain the server's public key, but either its certificate or a CA certificate with which it should be verifiable. (It's not just about having the public key, but knowing whose it is, using the other pieces of information in the certificate.)

When you use client-certificate authentication in addition to this, there is a truststore (or equivalent) on the server side and a keystore on the client side too, since the roles are reversed for this purpose.

In the SSL/TLS handshake that uses client-authentication, the server requests a certificate from the client, who sends it (if available).

At the end of this handshake, the client sends a CertificateVerify message, which signs all the messages exchanged so far between the client and the server (so it's something known to both) using the client certificate private key. The server is then able to verify this signature against the public key within the client certificate it has obtained as part of this exchange. This proves to the server that whoever is on the client side has the private key corresponding to the public key in the certificate it has sent.

The next step for the server is to verify whether to trust this certificate, i.e. whether to trust the binding between identity and public key as presented and "sealed" within the certificate. This is usually done using a PKI, whereby you check the certificate against a known CA, or if your deployment environment is sufficiently small, against a fixed set of trusted certificates. (There can be alternative methods of verification, but their usability will really depend on the circumstances where you want to deploy this system.)

Therefore, for your second question:

  • The client keystore should contain at least the client's certificate and its private key.
  • The client truststore should contain the server certificate or a CA certificate with which the server certificate can be verified.

Since both keystore and truststore are a keystore (in the storage format sense, usually a file) used for a different purpose, it's often possible to use the same keystore to serve both the purpose of keystore and truststore.

(*) There are cipher suites that don't rely on certificates, but that's unusual and off topic for this question.

like image 62
Bruno Avatar answered Sep 24 '22 21:09

Bruno