15

I have a PKCS#12 file which I considered as a keystore file since it contains one key entry & one certificate entry.

In Android, I see people programmatically install keystore in the following way (The code is from Android developer blog):

byte[] keystore = . . (read from a PKCS#12 keystore)

Intent installIntent = KeyChain.createInstallIntent();
installIntent.putExtra(KeyChain.EXTRA_PKCS12, keystore);
startActivityForResult(installIntent, INSTALL_KEYSTORE_CODE);

I also see people programmatically install only the certificate wrapped inside keystore:

Intent intent = KeyChain.createInstallIntent();
intent.putExtra(KeyChain.EXTRA_CERTIFICATE, cert);
startActivity(intent);

Besides, I also see people install both the keystore & the certificate wrapped in keystore. For example, this article shows us how to first install keystore & then install the certificate wrapped in keystore programmatically.

I really get confused about when should I install keystore only & when should I install certificate (wrapped inside keystore) only ? And when should I install both ?? Could someone make me clear about this please?

For example, my keystore PKCS#12 file (mycert.p12) contains key/certificate pair, it is used to connect to VPN server. When should my android client install both keystore and certificate wrapped in the keystore ? When should client install only certificate wrapped in keystore? What are the differences ? I am quite confused about this.

Leem.fin
  • 40,781
  • 83
  • 202
  • 354

3 Answers3

4

I have a PKCS#12 file which I considered as a keystore file since it contains one key entry & one certificate entry.

Correct.

In Android, I see people programmatically install keystore in the following way ...

This is done when you have a keystore, i.e. a keypair and certificate.

I also see people programmatically install only the certificate wrapped inside keystore

This is done when you have someone else's certificate, typically a self-signed one, that isn't trusted by any of the default CA's (certificate authorities) that are already installed. You should never have to do this.

So note that you never do both with the same certificate, because the cases (the ownerships) are different. There can never be any doubt about which process is appropriate. If it's yours, import the keystore. If it's someone else's, import the certificate.

The ultimate normative reference for all this stuff is ITU Recommendation X.509.

Finally, some notes on the poor quality blog articles you have linked.

From Unifying key store access in ICS:

In the past, it was common practice for apps to maintain their own key store if they needed to authenticate a secure SSL web server, or authenticate the user to a server via a client certificate.

This is already incorrect.

  1. To authenticate a web server you shouldn't need anything, if it has a CA-signed certificate. If it has a self-signed certificate you will need to import it into your truststore.

  2. To authenticate yourself to a web server, you need a keystore containing your own private key and a certificate, preferably a CA-signed one. Otherwise the server has to import your self-signed certificate into its truststore, i.e. the converse of (1) above. Don't go down this path. Self-signed certificates are far more trouble than they are worth, which is nothing, as you can tell from the price you pay for them.

From Using ICS keychain API:

We first get the private key and certificate chain using the key alias and then create and verify a signature to check if the key is actually usable.

Complete nonsense. We already have the private key, the public key, and the certificate. They are already usable. Creating a signature and verifying it locally is just a complete waste of time.

Installing a CA certificate is not very different from installing a PKCS#12 file: you load the certificate in a byte array and pass it as an extra to the install intent.

The difference being that you use KeyChain.EXTRA_CERTIFICATE in the CA certificate case, and KeyChain.EXTRA_PKCS12 in the keystore case.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Hi @EJP, can I ask a question, I still confuse `self-signed certificate` because my English is not so good, according to [this Wiki](https://en.wikipedia.org/wiki/Self-signed_certificate), `a self-signed certificate is an identity certificate that is signed by the same entity whose identity it certifies...` then if I use `openssl` to create a certificate (for example, Issued To A, Issued By B, detail steps at `http://pastebin.com/KMdjujYv`), this cert is not a self-signed one, am I correct? Thanks – BNK Jun 22 '16 at 07:08
  • @EJP If you want the 50+ Rep, read the note. I have asked for an answer drawing from credible and/or official sources. You have said why the resources are not creditable. – CrandellWS Jun 22 '16 at 17:56
  • 1
    @BNK That is correct. – user207421 Jun 23 '16 at 05:22
  • 1
    @CrandellWS It's implicit in the meaning of private keys and certificates, but the [`keytool` documentation](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html) says much the same thing, albeit somewhat obscurely. Also the [Tomcat SSL how-to documentation](http://tomcat.apache.org/tomcat-9.0-doc/ssl-howto.html). – user207421 Jun 23 '16 at 05:24
  • Thanks @EJP, so if the cert of issuer (rootca) added in User trusted credentials, so my app will not need a custom truststore. – BNK Jun 23 '16 at 05:32
  • 1
    @BNK If your application will use the 'user trusted credentials' by default, whatever that means on your unstated platform, the answer to that is also 'yes', *provided* the peer sends the entire chain correctly, which evidently doesn't always happen. There isn't really enough information here about your application to discuss it in detail. If you have an actual problem about this, I can only suggest you post your own question. – user207421 Jun 23 '16 at 07:49
  • Oh man LOL @EJP nice edit – CrandellWS Jan 11 '17 at 10:41
  • @EJP could you help at http://stackoverflow.com/questions/42137828/volley-library-and-https-requests? – BNK Feb 10 '17 at 01:20
-1

Since no one has answered you yet, I hope I can at least clarify some points from the blog article you have linked to.

In the past, it was common practice for apps to maintain their own key store if they needed to authenticate a secure SSL web server, or authenticate the user to a server via a client certificate.

These are the two basic use-cases right here:

  • If you are authenticating with a client certificate (which proves to the server that you are an authorized client), then you would only install a certificate.
  • If you are trying to verify the server's identity, then you will want to validate the server's certificate. In this case you will need a keystore installed (possibly a chain if you're not using self-signed certs). The private key in the keystore will be used to validate the server's certificate.

That second bit of code you have in your question was intended for creating a certificate chain (when you're NOT using self-signed certs):

We first get the private key and certificate chain using the key alias and then create and verify a signature to check if the key is actually usable. Since we are using a self-signed certificate the 'chain' consists of a single entry, but for a certificate signed by a CA you will need to find the actual end entity certificate in the returned array.

Installing a CA certificate is not very different from installing a PKCS#12 file: you load the certificate in a byte array and pass it as an extra to the install intent.

Intent intent = KeyChain.createInstallIntent();
intent.putExtra(KeyChain.EXTRA_CERTIFICATE, cert);
startActivity(intent);

I hope this explanation helps! :)

user207421
  • 305,947
  • 44
  • 307
  • 483
bischoje
  • 197
  • 1
  • 8
  • 3
    Are you sure you haven't gotten these reversed? In your second bullet/use-cases, you state you need a private key to verify the server. That is incorrect. You need the public key/cert to verify the server. That and you need to have one of the CA's in the cert chain to be trusted. Those are all public certificates - no private keys. The private keys for the server are only on the server. In addition, the first bullet is incorrect. To use a client certificate for authenticating to a server, you need the private key of the client (as well as the certificate). – BJV Mar 05 '14 at 21:14
  • So if my first bullet point said "public key in the keystore," you would agree with it? It's possible I am mistaken on that detail. – bischoje Mar 06 '14 at 02:38
  • As for client certificates, why would you need the private key in order to present a client certificate to the server? – bischoje Mar 06 '14 at 02:39
  • 2
    If you only have a public certificate for your client, how does the server know that someone other than you are providing the certificate? The way it typically works is that when a client connects to the server, it provides both the client's certificate (with public key) and some data (typically a hash) that has been signed using the client's private key. The server can then verify the signature using the client's public key. TLS/SSL take care of this for you, but in order to use TLS with client certs, you must provide a private key. – BJV Mar 06 '14 at 15:48
  • 1
    So while your explanation is somewhat wrong, the steps are correct: install the client certificate and its private key via the PKCS#12 file and KeyChain.EXTRA_PKCS12 and install the CA certificate via a .pem or .crt file using KeyChain.EXTRA_CERTIFICATE. – BJV Mar 06 '14 at 15:55
  • @CrandellWS Your edit was completely incorrect. Don't add to the confusion. – user207421 Jun 19 '16 at 03:07
  • 2
    You have this completely back to front. If you are presenting a certificate you must have the corresponding private key. If you are verifying a peer you only need a set of trusted signer certificates. The second quotation about creating a signature to verify your own private key is pointless. Creating a signature with your own private key and then verifying it with your own public key accomplishes precisely nothing. 'To check if the key is actually usable' is just drivel. – user207421 Jun 19 '16 at 04:59
-1

With respect to an android or any other 'client', that is, an application, the following hold -

A truststore (public key only) is required whenever it needs to validate the certificate (or a certificate chain) that is sent across by the server during SSL communication (in case of ssl communication the server will always present its certificate to the client).

If the server's certificate is already signed by a trusted certificate authority (implying that certificate is already present in the java-runtime-truststore that can usually be found under $JAVA_HOME/jre/lib/security/cacerts), then this step is not required unless a customized SSLContext is being used (which also means that a customized TrustManager is being used).

For example SO's current certificate is signed by DigiCert identified by SHA1-Thumbprint : 5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25 and would likely be present in the 'cacerts' truststore under the alias 'digicerthighassuranceevrootca'. If a java client were to make a request to https://stackoverflow.com then by default there would not be any specific keystore or truststore required for communication.

A keystore (private and public key) is generally required when the client is required to digitally-sign some data which is being posting to the server. A common example is xml-signing, you can find a mention here

It is also required if the server expects the client to present its own certificate for authentication as part of two-way ssl handshake. From what I have come across this is not common.

Links :

Two Way SSL

SO's own Keystore and truststore post

Community
  • 1
  • 1
Ravindra HV
  • 2,558
  • 1
  • 17
  • 26
  • A truststore does not contain the 'public key only'. It contains the certificates of trusted signers, possibly including self-signers. A customized `SSLContext` does not imply that a custom `TrustManager` is being used. A keystore used for client authentication contains not only private and public keys but also a signed certificate wrapping the public key. Your 'Two Way SSL' link is riddled with mistakes: for example, 'client certificate (encrypted with Private Key Client) ' is nonsense, and the master secret is not the same thing as the session key. Too many errors here. – user207421 Jan 11 '17 at 09:20
  • Was just trying to explain in as simple terms as possible (the second link does contain what you describe). Same goes for the link (I find illustrations easier to follow than text). From my understanding, the only reason I'd say an `SSLContext` was customized is if it were initialized with a custom keystore-manager or truststore-manager implementation. – Ravindra HV Jan 12 '17 at 18:06