I recently had to add my corporate root CA (based on AD CS) into the JRE default truststore (the $JAVA_HOME/lib/security/cacerts file). I then discovered (as I am new to this) that the default password is changeit.
I found various posts explaining how to change it but there are two questions I can't find answers to:
Is keeping the default password a security risk? I guess an attacker could then import compromised certificates so clients trust them
What are the impacts of changing this truststore password? I also guess the JRE can look for root CA inside because it knows the default password. Once changed, will it have to be provided somewhere (config file, ...)?
We mainly use Java on Windows for websites which have applets, so we don't start anything from the command line (on which I know the password can be provided).
Regarding your second question, there are system properties to specify passwords for default trust store and default key store. The one for the trust store is:
javax.net.ssl.trustStorePassword
I found that information at https://stackoverflow.com/a/5871352/5629418
If the attacker can read your Java system properties, either in a config file or by running a Java program, then changing the password will be mostly futile though.
Regarding your second question: "What are the impacts of changing this truststore password?"
One of the implications of changing of that password is that the memory bits holding the new password value is better to allocate and to store somewhere for their following retrievals, provisions for the corresponding accesses. And if that password is not stored, it is better to have a procedure about how to restore it then.
That article contains the code for changing such password:
thetechawesomeness.ideasmatter.info
Related
I recently joined a project that has an application running in Tomcat that uses a single file as both the KeyStore and the TrustStore. In other words, it includes both entries of types trustedCertEntry and PrivateKeyEntry.
While upgrading from Tomcat 8.5.6 to 8.5.20, I realized catalina.out was giving me
java.lang.IllegalArgumentException: java.security.KeyStoreException: Cannot store non-PrivateKeys
The solution was to make to remove the trustedCertEntry entries from the keystore.
To me, this seems fairly obvious that you would want to keep these separate. My question is, are there any possible security consequences to using the same file as a keystore and truststore? If so, why does Java (or SSL) allow these to be kept in the same file?
SSL and TLS are interoperable protocols; by IETF policy and tradition they say nothing about storage of anything and everything at either or any endpoint. "That's a local matter."
Java historically used one file format (JKS) for both TrustedCert's and PrivateKey's, not only for SSL/TLS but for all public-key crypto (and optionally with JCEKS some symmetric crypto also), and Java9 is switching to PKCS12 for both. Using the same format doesn't mean you must use the same file, and I would say it's preferable to use separate files, but I don't see an actual security problem in using a single file as long as you keep any file containing a privatekey restricted to one system, or as few systems as absolutely necessary, plus appropriate backup; however that's not really a programming Q and you might try for better answers on security.SX.
Tomcat 8.5 sorta-kinda combines the previously separate and (often confusingly) different config for Java-JSSE and APR=OpenSSL stacks, and I believe this restriction that the keystore can only contain PrivateKey's is a result of that change.
I'm working on a java application that uses JKS keystores for mutual authentication. One thing I noticed is a bug where our keystore password and alias password have to be the same for one of our applications to work.
Besides not having unique passwords is typically bad practice, I was wondering if there were any studies or way to quantify the risk of not making nested keystore passwords and aliases different?
Using a separate key-alias password in JSSE makes certain things impossible. For example there is no system property for it, so if you're relying on system properties to configure JSSE you have to not use key-alias passwords at all.
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).
We had been using java standard keystore ($JAVA_HOME/jre/lib/security/cacerts) as the trusted store for tomcat. And that tomcat server would communicate with some other server. A recent OS(AIX) upgrade apparently over-wrote the file at $JAVA_HOME/jre/lib/security/cacerts and that resulted in lost certificates and lot of issues with application hosted in tomcat.
Looking at this is it a bad practice to relay up on $JAVA_HOME/jre/lib/security/cacerts ?
What are the alternate (better|standard) ways to tackle this scenario?
It's not a bad practice if you have a build process that will repeat the imports.
Not sure, but assuming your assumptions are correct, caution where you put your keystore. I would strongly suggest it is placed inside Apache folder.
By default in Websphere the keystore works this way, since it brings it's own JVM :)
In terms of what is in the cacerts file, it's not necessarily worse practice than relying on the default CA certificates installed in your OS or your browser, but that doesn't mean it's great.
Sun/Oracle have a little "important note" somewhere in the middle of the JSSE Reference Guide about this:
IMPORTANT NOTE: The JDK ships with a limited number of trusted root
certificates in the /lib/security/cacerts file. As
documented in keytool, it is your responsibility to maintain (that is,
add/remove) the certificates contained in this file if you use this
file as a truststore.
Depending on the certificate configuration of the servers you contact,
you may need to add additional root certificate(s). Obtain the needed
specific root certificate(s) from the appropriate vendor.
In terms of configuration, for specific applications where I've had to install "local" CA certificates, I find it more stable to use a local trust store (for example, specified with javax.net.ssl.trustStore).
Yes it is a bad practice to do that.
The best practice is to have to limit your trusted certificates as much as needed.
So you should have used you own keystore with only the certificates trusted by your application.
The AIX upgrade is a patch. Any patch must not delete / overwrite user data. I would suggest that users affected by this kind of data loss ask IBM to fix the patch procedure. In comparison, a patch of the httpd server does not overwrite / delete the configuration even though it is in the program directory.