问题
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.
回答1:
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.
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.
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.
回答2:
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! :)
回答3:
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
来源:https://stackoverflow.com/questions/19930012/when-to-install-keystore-when-to-install-only-certificate-wrapped-in-keystore