views:

266

answers:

4

I've got a java applet that loads some pre-installed native code extensions to display custom content in the browser. Some of this content may include native code to be loaded by the JVM. Obviously, this is a security concern. I'd like to enforce that all content comes only from authorized servers.

The path I've been following to accomplish this is to create a keystore that contains just one SSL certificate. I set the keystore location and password and turned on debug output.

System.setProperty("javax.net.ssl.keyStore", "C:\\keys\\keystore");
System.setProperty("javax.net.ssl.keyStorePassword", "changeit");
System.setProperty("javax.net.debug", "ssl");

I was under the impression that this would mean that the JVM would have access to only the one keystore file and consequently the one key inside it. In fact, the SSL debug info lists something like 75 CA keys in addition to the one key I added. Clearly, this isn't going to keep anyone from sending us untrusted code.

Is there a way to tell the SSL system to only use a single certificate? Should I be using a completely different approach?

Update: Changing the cacerts file isn't really an option here. The JVM should continue to function normally for other applications using it. Is there a way, at runtime, to elect not to load that file? I'm looking at the TrustManager and KeyManager classes but I don't really understand how to use them.

A: 

You also have the global keystore installed with the JRE, which is where all the CA's are stored. Try to rename it and see what happens.

Thorbjørn Ravn Andersen
Renaming the cacerts file works but I can't go breaking the user's SSL libraries just for my app.
joegester
A: 

You still "see" the CA certificates of the system-wide JRE cacerts file located in java.home/jre/lib/security, which is normal.

Now, quoting the keytool documentation about this file:

IMPORTANT: Verify Your cacerts File
Since you trust the CAs in the cacerts file as entities for signing and issuing certificates to other entities, you must manage the cacerts file carefully. The cacerts file should contain only certificates of the CAs you trust. It is your responsibility to verify the trusted root CA certificates bundled in the cacerts file and make your own trust decisions. To remove an untrusted CA certificate from the cacerts file, use the delete option of the keytool command. You can find the cacerts file in the JRE installation directory. Contact your system administrator if you do not have permission to edit this file.

In your case, it might be easier to entirely replace the cacerts with your own key store instead of removing all 75 entries if this is really what you want. If not, then you should use a different approach indeed (why don't you just restrict or hard code the list of authorized servers?).

Pascal Thivent
+1  A: 

You need to set the javax.net.ssl.trustStore system property to point to a keystore with your one certificate in it. The keystore is for your authentication credentials, not your peer's.

GregS
That's exactly it! Thank you!
joegester
A: 

The very question is wrong here. A certificate is only a proof of identity. You don't authorize certificates, you authorize identities. What if the same client comes up with a new certificate?

The correct answer is to install a HandshakeCOmpletedListener that checks the peer identity. The truststore is only there for authentication, i.e. is that person who they said they were. What you are doing is authorization, which is a different thing completely. You shouldn't use the truststore (or any PKI mechanism) for authorization.

EJP
This is for an application distributed with single trusted CA certificate. We're issuing certificates to control which servers will be trusted by the client program.
joegester
That doesn't change anything. A certificate isn't an identity, it is a proof of identity. An identity can have multiple certificates. Treating the certificate as an identity is a grade A category mistake.
EJP