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.
Related
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
I want to connect to a TLS server with a self-signed certificate, so I need a custom trust store. keytool seems to absolutely require a password in order to import the certificate, but I really don't need to password-protect the trust store. Using the standard password "changeit" will work, but it I'd prefer to have no password at all.
Note that this is a "trust store" not a "key store", so there is no secret material in the trust store at all: just the server's certificate, so the client can authenticate that the server is trusted.
Is this possible with keytool? Are there other tools that can remove the password from the trust store? Understanding that authenticating the trust store might actually have its uses, are there any specific reasons why I should not use a trust store without a password?
I am pretty sure keytool will let you put in a blank password if you create a new trust store, but the problem with not having a password is that an attacker can insert any certificate they want and have it be trusted. This creates malicious opportunities such as a man-in-the-middle attack. Your application assumes it can trust that URL that an attacker has set up, so there's nothing stopping them from re-routing your web service calls for example.
It is definitely best practice to change your key store and trust store passwords in production environments from the default.
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.
This question already has answers here:
Handling passwords used for auth in source code
(7 answers)
Closed 7 years ago.
Assuming that a password for a keystore is not supplied by or bound to a user password (which more or less means its just a String or Array[] in the code somewhere), is it a sufficient protection that it just cannot or can only hardly be extracted out of the bytecode?
I know that the password for a keystore (JKS / BKS) is just used to verify the integrity of the keystore. Furthermore it is totally clear that I have to assume that an application runs in a more or less trusted environment to be "secure". But anyhow, is it possible to extract the password just from the apk file?
It just feels wrong to hardcode any password within the source of an application, so maybe there are some ideas, how to make it actually less threatening.
E.g. would it be better to make the password configurable within an external configuration file or generate it randomly during installation of the app (and where should it then be stored)?
is it a sufficient protection that it just cannot or can only hardly be extracted out of the bytecode?
"Sufficient" is a subjective term; only you can determine what you feel is sufficient for you.
is it possible to extract the password just from the apk file?
Yes, as APK files can be decompiled, unencrypted network conversations can be sniffed, etc.
how to make it actually less threatening
You can buy a license for DexGuard and use it, as that will encrypt hard-coded strings like your password. Whether that is worth the extra defense is your decision.
would it be better to make the password configurable within an external configuration file
Anyone who roots the device could get at the file.
or generate it randomly during installation of the app (and where should it then be stored)?
It would be stored somewhere that is available to rooted device users, at minimum.
It is quite common to encrypt keystores with a password, but it is not neccesarily required.
Storing the password close to the keystore is more or less equivalent to having a keystore that is not encrypted. That may be perfectly ok. It is i.e. not uncommon to have unencrypted keystores with both certificates an private keys on servers where the keystore file is protected by other means.
The kind of attack you seem to be trying to protect against here is if someone are able to change the content of the keystore. A password could be used to verify the integrity of the keystore, but only if it is unknown to the attacker. It can't think of a typical scenario where an attacker would have access to your keystore but not have access to the bytecode of your application or the other configuration of the application.
The file system for an application in Android is reasonable secure, but not bullet proof in any way. If you don't trust that file system, you will need to encrypt the keystore with a password the the user types in or that is fetched from somewhere else outside of the device. On the other hand, if you trust the file system you don't actually have to encrypt the keystore at all (or you may encrypt it with a well known password if that makes your development easier).
Try using null instead of the password (see this question)
final KeyStore keyStore = KeyStore.getInstance("BKS");
keyStore.load(context.getResources().openRawResource(R.raw.serverkeys), null);
final KeyManagerFactory keyManager = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManager.init(keyStore, null);
final TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(keyStore);
sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManager.getKeyManagers(), trustFactory.getTrustManagers(), null);
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).