I have a keystore which has multiple keys and certificates added to it
I want to used a certificate based on the aliases from the key store and use it for SSL
I tried to set the following System properties but nothing helped
System.setProperty("javax.net.ssl.keyAlias", "abcd");
System.setProperty("javax.net.ssl.keyStoreAlias", "abcd");
It always uses the first certificate from the keystore instead of matching the key aliases
If you look at the Customization section of the JSSE Reference Guide (or the entire guide), there's no javax.net.ssl.keyAlias or javax.net.ssl.keyStoreAlias property.
It's up to the application to have a way to select which certificate it wants, using its alias name, but it has to load it explicitly itself. Some frameworks use their own properties or configuration options.
Related
I'm implementing a mutual authentication with a web server in Java on Windows.
I have a certificate on a SmartCard which is supposed to be used to authenticate me (or other user).
So far I've figured out that I can access the certificates using Windows-MY key store.
I do it like that:
KeyStore keyStore = KeyStore.getInstance("Windows-MY");
keyStore.init(null, null);
This works. I can see all certificates inside keystoreSpi (in debugger). One of them is the one which I need to use - I confirmed that.
The problem is as follows:
KeyStore api allows me to get a certificate only by using it's alias. e.g. keyStore.getCertificate("alias") or keystore.getCertificateChain("alias")
I noticed that there are multiple different certificates with the same alias in this keystore. I cannot change the aliases. I just physicaly got the smartcard with given certificates.
When I call one of the mentioned methods, keystore returns just the first certificate in the list with given alias. (generally, in the implementation there is a map where aliases are it's keys, so all duplicated aliases are ignored).
Unfortunately first certificate's purpose is "email encryption", etc. The second certificate's purpose is "SmartCard Logon" and this one I need to use. I confirmed that by going into debugger and manually hacking the list of certificates.
The question is: how do I get a proper certificate using the API (eg. the second one) when there are duplicated aliases?
If this can be done by external libraries, I can opt for that.
More details which may be useful:
I use KeyStore, then create KeyStoreManager.
I initialize SSLContext with given keyStoreManager sslContext.init(keyManagerFactory.getKeyManagers(), ...)
I create HttpsUrlConnection with given ssl context, which is my objective.
This has been fixed a while ago. Just update to a recent JRE. For more information see here: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6483657
Class KeyStore has a method called setCertificateEntry(alias, certificate). Most client examples I see use "ca" as the alias name. Is the server asking for "ca" automatically during the client-server handshake? What really would happen if I use "abc" instead of "ca?" Regards.
The alias is really just a name that is local to the keystore you are using. It is what identifies the entry in the keystore, so you can't re-use it for two entries, but it can be whatever you like (although I must admit I have never tried with non-ASCII characters, and the official truststore only uses lower case letters or numbers).
The documentation also says:
Whether aliases are case sensitive is implementation dependent. In order to avoid problems, it is recommended not to use aliases in a KeyStore that only differ in case.
Some keystore implementations and formats might have more constraints or use that name differently. For example, the WINDOWS-ROOT keystore (which is a front-end for the Windows native store) uses Windows's "friendly name" as the alias, which is unfortunately not unique in the Windows certificate store, so some certificates from the native store may be hidden and not usable (it's a map from alias to entry, loading a new entry with the same name replaces the other one). However, this shouldn't be a concern on Android, of course.
If you're building a keystore that you'll use as a truststore, which is likely to contain a number of CAs, calling one "ca" would make it difficult to identify them later on. (This is mostly an administrative problem to be able to find manually which cert is where.)
If you look at the default truststore, you'll get aliases with names the resemble the Subject DN of these CA certificates, for example "verisignclass1g2ca".
Having an identifier you can remember is generally more important for keystores that are used as keystores (as opposed to truststores) and which contain multiple private key entries, since this can help you configure your application to use a particular certificate to identify itself.
A keystore (no matter if it's used for "keystores" or "truststores") is initialized after creation using the load() method. One version expects an InputStream corresponding to the keystore file, and the password to decrypt the file. Providing the password to the method programmatically seems strange to me.
For example, a server uses a keystore to store its private keys and the associated certificates. The information present in the keystore is sensible so it is protected by a password. What are the problems of passing the password to the load() method programmatically? What is the best practice?
The other example, but for now concerning truststores. The client has a truststore where it stores the certificates of trusted CAs. As I understand it, the truststore doesn't contain the certificate of the server but only the certificates of the CAs that allow verifying the server's certificate. One truststore example I see is the one present with the JRE (in the security folder - cacerts). By looking at the configuration, I can see it is protected by the default password changeit. I understand that a truststore is implemented using a keystore, so it has (or maybe it's optional?) to be encrypted using a password. But, since truststores generally store public information (trusted CA's certificates) in the file, why changing the password is recommended?
Thanks
Providing the password to the method programmatically seems strange to
me.
I'm not sure why this would be strange. The application will need to be able to get hold of the content of the keystore at one point or another. The password will need to be passed to it, somehow. Passing it to the load() method doesn't make less sense than other solutions (avoid hard-coding, of course). Alternatively, you can use the method that uses a callback instead. If you don't think that's suitable, you can use a PKCS#11 provider and a hardware token (although you'll still need to enter the password/PIN somewhere) or use something like the Apple KeychainStore (where the password isn't used, but the OS keychain service takes care of that).
Regarding the truststore, there are in fact two passwords in use. They can be different, when using the JKS format. One protects the keystore itself, and one protects access to the private entries (getKey). In this case, the keystore password is used to prevent unauthorised parties from altering the truststore (and adding their own CA or server certificates).
I read this article on how to use keytool to generate CSRs for your organization. It was simple and easy, but left me with a few questions that I couldn't find clear, descriptive answers to:
What is Java's concept of a CSR alias and why would you want to use one? Where is this alias field stored and what other tools/APIs have access to it?
What is the difference between a key and a keystore?
What is Java's concept of a CSR alias and why would you want to use one? Where is this alias field stored and what other tools/APIs have access to it?
First of all, java uses keystores to keep keys (and certificates) inside. Single keystore can hold many certificates, so you need a way to differentiate them. That's what aliases are for. Having a keystore, an alias (and a password if needed) you can get the certificate from the keystore using Java Crypto API (specifically classes like Keystore). Here, you have a an example of how the Crypto API can be used to load a key from keystore
What is the difference between a key and a keystore?
The keystore is a container. The keys are kept inside keystores.
A keystore is a file format used to hold certificates and private keys, and alias is used to identify each entry in the keystore.
Can we load multiple Certificates & Keys in a Key Store?
Is it always required to load only Pairs (i.e. Certificates & Keys together)?
If a Key Store has multiple Certificates and Keys, which one will get selected when Java SSL tries to establish connection as a Server?
Although this depends on the KeyStore type, generally, you can store multiple private keys and certificates in a single store.
Which key and certificate combination is used for a Java-based server will depend on how the application was implemented. A number of applications let you select a given certificate using the alias name. The key and certificate getters in KeyStore take an alias parameter to make this choice. Usually, when this is not specified in the configuration, the application or framework will use the first suitable one it finds based on the KeyStore.aliases() enumeration.
Tomcat, for example, uses the keyAlias attribute in its Connector configuration:
keyAlias: The alias used to for the server
certificate in the keystore. If not
specified the first key read in the
keystore will be used.
Regarding key pairs, some KeyStores (again, depending on the type) can be used to store SecretKeys (e.g. DES), that is shared keys, as well as public-private key pairs.
You can have a keystore with as many certificates and keys as you like.
If there are multiple certificates in a keystore a client uses as its truststore, all certificates are being looked at until one is found that fits. You can look at the preinstalled certificates, they are in /lib/security/cacerts. It's just a big collection of root CAs' certificates.
Regarding the keys I don't know. I'd reckon the client uses a key that is signed by the same CA as the certificate that is provided by the server and if there are multiple, the first is used. But I can't say that for sure.