Issue with understanding keystore and ssl - java

These are the facts:
I have a client(android)-server(java - Ubuntu 14.04)-program with which I transmit my gps-data from my smartphone every 5 minutes to the server saving it into a mysql-database.
My problem is that I do not want to transmit my GPS data plain. So I want to use SSL, to verify the client(my smartphone) to the server(making it impossible for someone else to connect to the server - no handshake) and of course to encrypt.
My main issue is about understanding the keystore, truststore process.
With
keytool.exe -genkey -keyalg RSA -keysize 2048 -alias -serverKey
-keystore serverKeystore.jks -validity 1095
I am creating a new keystore (if not existing) named serverKeystore.jks. This keystore includes the private key and the public key wrapped by the certificate.
I can export the certificate with
-keytool.exe -export -alias serverKey -keystore serverKeystore.jks -file server.cer
So based on this tutorial he now creates a clientkeystore:
keytool -genkey -keyalg RSA -alias clientKey -keystore
clientkeystore.jks -validity 999 -keysize 2048
and I export the client.cer the same way like I did with the server before.
Now he adds the server.cer to the clients-keystore and the clients.cer to the servers-keystore. But now serverKeystore and clientKeystore have created a different private/public key-pair. The server is now aware of the clients public key and the client is now aware of the servers public key. That way the client can encrypt the plaintext with the public key of the server and the server can then decrypt it with his private key. Is this correct?
If so where is the truststore? Is the truststore the server-keystore storing the client.cer and that way trusting this client and vice-versa?

Now he adds the server.cer to the clients-keystore and the clients.cer to the server's keystore.
Wrong here. You should add the exported certificate to a truststore in each case. Export from server keystore to client truststore, client keystore to server truststore.
That way the client can encrypt the plaintext with the public key of the server and the server can then decrypt it with his private key. Is this correct?
It's correct in theory but it isn't used that way. SSL negotiates a symmetric session key. The certificates and their keys are only used for authentication, not for encryption.
If so where is the truststore?
See above.

Related

Creating a truststore in java

A vendor have given me a .jks to connect to their mq via jms. I am using the following code as a template for my proof of concept.
Connecting to a Websphere MQ in Java with SSL/Keystore
The creation of the Keystore is fine, however when it attempts to create a Truststore it loads a new .jks file. Am i supposed to generate this file or should it have been provided as currently I am unable to create it.
// instantiate a KeyStore with type JKS
KeyStore ks = KeyStore.getInstance("JKS");
// load the contents of the KeyStore
ks.load(new FileInputStream("/home/hudo/hugo.jks"), KSPW);
System.out.println("Number of keys on JKS: "
+ Integer.toString(ks.size()));
// Create a keystore object for the truststore
KeyStore trustStore = KeyStore.getInstance("JKS");
// Open our file and read the truststore (no password)
trustStore.load(new FileInputStream("/home/xwgztu2/xwgztu2.jks"), null);
Thanks
There are a lot of assumptions in this answer (as the question does't provide much of information), but I as well assume it comes with the amount of experience.
To create an SSL connection, the server must have a keypair (private, public key and a certificate bount to the public key) and client must trust the certificate (or its issuer). There is as well an option for mutual SSL (aka client auth ssl), where the client needs its own keypair and certificate and the server needs to trust the client's certificate.
Truststore it loads a new .jks file. Am i supposed to generate this file or should it have been provided as currently I am unable to create it.
The truststore should effectively contain the issuer certificate of the server's certificate (if a self-signed certificate is used, it is the same one).
You can get the certificate by connecting to the service
openssl s_client -connect host:port -showcerts
and then import the returned certificate into a new keystore (using e.g. keytool -importcert command)
keytool -importcert -keystore mytruststore.jks -alias mqserver -file servercert.pem
If the server returns you multiple certificates (certificate chain), you may import them all.
If you are not able to do so, just ask the service provider (someone who deploys the MQ) to provide you the certificate or the truststore.

Keytool genkey creates certificate or private key?

I need a clarification\confirm for keytool and Keys in general.
Many many sites show this is the way to obtain a keystore with a certificate:
keytool -genkey -keyalg RSA -alias my-certificate -keystore mykeystore.jks -validity 3600 -keysize 2048
And if u export it your can clearly see:
-----BEGIN CERTIFICATE-----
MIICVjCCAb8CCAogFQkp...
...rI7KvuXHX2JWNYLdBvC8V6aXAiIb
OaSAB3DoscgOqDh58bw5vEFwjxVo...
-----END CERTIFICATE-----
So this is a certificate indeed. But from this can be extracted only public key.
So we can say that a certificate is Secret key?
On the other hand with keytool command:
-genkeypair
generates a key pair (a public key and a private key). Private for the server and public for the others.
So basically certificate\secret key isn't the same as private key?
Both methods get public so basically a certificate is a private key?
In short keystore contains key pairs, and a key pair consists of a public and a private key. So keytool creates both.
What you call certificate is public key, since private keys is highly confidential to your application server, it should not be transfered insecurely, if possible it is not transfered at all. Which means you should create a keystore in the application server and from that keystore you should extract public key. And after it is signed by a certificate authority, it should be added to keystore to create a keychain.
A much detailed answer can be found in here
keytool creates two keys, a private key, which you use for signing, encrypting, decrypting, i.e. anything that needs to be traced back to you. In order to trace something back to you, to validate your 'identity' you give others your public key certificate. This wraps your public key with identity information. If it's a self signed public key certificate then you are saying you are, for example, ServerA but no-one can really verify you're ServerA as ServerA is claiming it's ServerA. To fix this, you export a Certificate Signing Request (CSR) from your keystore and send it to, e.g. Verisign who validate you are ServerA and then they sign the certificate. What you end up with is a public key certificate saying you are ServerA and that claim is signed by Verisign using their private key and just about every entity out there has the Verisign public key certificate so they can verify Verisign's signature which means they then trust you as ServerA. You then distribute your public key certificate and everyone can encrypt messages to you, knowing that you are indeed ServerA, because of the root signature from Verisign.

Two-way SSL between two applications on the same Tomcat Server

I have the following scenario: two Java applications are running on the same Tomcat server -- let's call them App A and App B -- and they need to talk to each other via a webservice that is already up and running on App A. This webservice only accepts authenticated clients (clientAuth="true").
After all is configured, my Tomcat, acting as a client, sends an empty certificate chain to the server (which is the same Tomcat). Here's what I have done.
I generated a self-signed certificate for the server using keytool:
keytool -genkeypair -keyalg RSA -keysize 2048 -keystore keystore.jks -alias server
Then exported this certificate:
keytool -exportcert -keystore keystore.jsk -alias server -file server.crt
And added it to the truststore:
keytool -importcert -keystore truststore.jsk -alias server -file server.crt
The SSL negotiation is as follows:
Client says hello
Server says hello and presents its certificate (generated above) for
the client
Client accepts it (since it's in the truststore)
Server requires client certificate by presenting a list of valid DNs (which contains a single entry, the certificate generated above)
Client somehow decides it has no valid certificates and sends an empty cert chain
SSL handshake fails
I didn't post the actual SSL log because the client and the server are the same Tomcat, so everything is a mixed up mess.
What have I done wrong here? Keep in mind that these two apps are on the same server and the cert is self-signed. I also did a test where I generated another self-signed cert, exported it to a .p12 file and installed it in my browser, then called the webservice via URL directly into the address box, it worked flawlessly.
Thanks!
For the record to anyone that gets here...
I was able to do it in two ways. One was to prepare a special configuration file for my client application, named cxf.xml, as explained in this link. The other one was to use code to force the loading of the configuration, as follows:
#WebEndpoint(name = "MyWebServicePort")
public IMyWebService getMyWebServicePort() {
IMyWebService port = super.getPort(new QName("http://my.namespace/", "MyWebServicePort"), IMyWebService.class);
try {
// loads keymanager
File keyStoreFile = new File(System.getProperty("javax.net.ssl.keyStore"));
String keyStorePass = System.getProperty("javax.net.ssl.keyStorePassword");
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream(keyStoreFile), keyStorePass.toCharArray());
KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, keyStorePass.toCharArray());
KeyManager[] km = keyFactory.getKeyManagers();
// loads trustmanager
File trustStoreFile = new File(System.getProperty("javax.net.ssl.trustStore"));
String trustStorePass = System.getProperty("javax.net.ssl.trustStorePassword");
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream(trustStoreFile), trustStorePass.toCharArray());
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(trustStore);
TrustManager[] tm = trustFactory.getTrustManagers();
// configuring the connection
Client cxfClient = ClientProxy.getClient(port);
HTTPConduit httpConduit = (HTTPConduit) cxfClient.getConduit();
TLSClientParameters tlsParams = httpConduit.getTlsClientParameters();
if (tlsParams == null) {
tlsParams = new TLSClientParameters();
}
tlsParams.setKeyManagers(km);
tlsParams.setTrustManagers(tm);
httpConduit.setTlsClientParameters(tlsParams);
} catch (Exception e) {
...
}
return port;
}
I really don't know why it did not load the default config (with the JVM params). It is a mistery: debugging, I found out that when building the SSL connection, it actually uses a DummyX509KeyManager, meaning the configuration was not loaded. Could be a bug? I don't know.

Creating an SSL Connection in Java

I looked around and did not see any questions that fully answered what I wanted, though if this is a duplicate, point me to the question and I will be on my way.
Right now I am trying to write a Java server that will receive data from an SSLServerSocket and for now, just print it out. I would eventually like to have this data come from an Android, but right now it throws an SSLException before it even starts listening for data.
code:
System.setProperty("javax.net.ssl.keyStore","C:\\ProgramFiles\\jre6\\bin\\server.jks");
System.setProperty("javax.net.ssl.keyStorePassword","password");
SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
ServerSocket ss = factory.createServerSocket(6543);
Socket s = ss.accept();
There is more code after that to process it, but it gets hung up and throws the exception there, so I'm not sure posting it will help any, but if it will, just comment for it.
I created the certificate following a tutorial for openssl on Ubuntu and transferred it over and created my keystore using:
keytool -import -file "C:\Documents and Settings\matt\Desktop\server.crt" -keystore server.jks
I can easily admit that I don't fully understand how a large portion of this works, so any help would be appreciated. Also, I suppose I am going to leave it outside the scope of this question becauseI feel like this is a pretty big question on its own, butI would also like some insight as to how to connect the client if possible. Sorry for all the trouble and thanks ahead of time for all the help.
EDIT:
the tutorial I followed is here:
http://www.akadia.com/services/ssh_test_certificate.html
Thanks again!
EDIT:
The Exception being throw is:
javax.net.ssl.SSLException: No available certificate or key corresponds to the SSL cipher suites which are enabled
I tried to Google the exception and most everything was a tutorial describing how to create a keystore (which I am under the impression that I already have). I will continue to sift through these search results.
Thanks!
When you create a keystore like this, you only put a certificate in your keystore:
keytool -import -file "server.crt" -keystore server.jks
What you need is to have a private key + a certificate.
Either you import them from somewhere else if you already have a certificate issued by a Certification Authority, or you can create a self-signed certificate if it's for limited use.
If the certificate you've created with OpenSSL is self-signed (or from a mini CA for your own use, e.g. with CA.pl), it's probably not worth the trouble of doing the conversion. You might as well generate a self-signed certificate directly with keytool. See the "Generating Your Key Pair" example in the official keytool documentation:
keytool -genkeypair -dname "cn=Mark Jones, ou=JavaSoft, o=Sun, c=US"
-alias business -keypass kpi135 -keystore /working/mykeystore
-storepass ab987c -validity 180
Make sure you use cn=your.fqdn.host.name (or cn=localhost if it's for local tests only). (I think keytool provided with Java 7 also has support for subject alternative names, which would be better.)
If you already have a private key + certificate you want to re-use in PKCS#12 format (usually .p12 file), you can import it using the method described in this question.
If what you've produced with OpenSSL is in PEM format, it might be easier to bundle them in a PKCS#12 file with OpenSSL and then import them as above. This can be done with this:
openssl pkcs12 -export -in cert.pem -inkey key.pem -out creds.p12

Java Sign jars with server certificate

Is it possible to use a server certificate to sign a java web start app? What I want to know is if will it work. I have a trusted certificate for my server, and I would like to reuse the same certificate to sign an app.
Right now, I have this warning:
This jar contains entries whose signer certificate's ExtendedKeyUsage
extension doesn't allow code signing. This jar contains entries whose
signer certificate's NetscapeCertType extension doesn't allow code
signing.
Will I be able to launch my app without the warning that the certificate is not trusted?
You will get warning if you don't use a code signing certificate. For most CA, code signing cert costs more than the server cert. In my opinion, this is just a marketing scheme to make you to pay for another cert. There is no technical difference between two certs. Some CA may provide combo deals with usage for both.
I assume you have created the JKS file using the KEY and CRT of your SSL and hence you get the error..
I have a simple solution here:
As you know you can create a JKS using the following command
keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias
and when you use this JKS you get self signed certification message which is absolutely fine to make the app live at Google play store.. But buying code signing certificate is good if you can afford it ..

Categories

Resources