How to setup basic Jersey/Grizzly 2.21 SSL startup configuration - java

I'm trying to get a very basic Grizzly server up and running to allow for one-way SSL (HTTPS) connections to access jax-rs REST services. Eventually I want two-way SSL security.
I've gone through many of the examples and I just can't get anything to work. I keep running into a SSL Handshake error. Clearly I must be doing something stupid. Any help is appreciated.
Here is my code to start my embedded Grizzly server using the Jersey wrapper classes:
public static HttpServer startHttpsServer(URI listenerURI) throws IOException {
ResourceConfig resourceConfig = new ResourceConfig().packages("ws.argo.experiment.ssl");
// First I tried this configuration using the certs from the Jersey sample code
// Grizzly ssl configuration
SSLContextConfigurator sslContext = new SSLContextConfigurator();
// set up security context
sslContext.setKeyStoreFile("./src/main/resources/keystore_server"); // contains server keypair
sslContext.setKeyStorePass("asdfgh");
sslContext.setTrustStoreFile("./src/main/resources/truststore_server"); // contains client certificate
sslContext.setTrustStorePass("asdfgh");
// Then I tried just using a default config - didn't work either
// sslContext = SSLContextConfigurator.DEFAULT_CONFIG;
if (!sslContext.validateConfiguration(true)) {
LOGGER.severe("Context is not valid");
}
LOGGER.finer("Starting Jersey-Grizzly2 JAX-RS secure server...");
HttpServer httpServer; //= GrizzlyHttpServerFactory.createHttpServer(listenerURI, resourceConfig, false);
httpServer= GrizzlyHttpServerFactory.createHttpServer(
listenerURI,
resourceConfig,
true,
new SSLEngineConfigurator(sslContext).setClientMode(false).setNeedClientAuth(false)
);
httpServer.getServerConfiguration().setName("Test HTTPS Server");
httpServer.start();
LOGGER.info("Started Jersey-Grizzly2 JAX-RS secure server.");
return httpServer;
}
I also tried replaced SSLEngineConfigurator(sslContext).setClientMode(false).setNeedClientAuth(false) with null to see if that would help. Nope.
I always get the following error:
grizzly-nio-kernel(3) SelectorRunner, fatal error: 40: no cipher suites in common
javax.net.ssl.SSLHandshakeException: no cipher suites in common
%% Invalidated: [Session-2, SSL_NULL_WITH_NULL_NULL]
grizzly-nio-kernel(3) SelectorRunner, SEND TLSv1.2 ALERT: fatal, description = handshake_failure
grizzly-nio-kernel(3) SelectorRunner, WRITE: TLSv1.2 Alert, length = 2
grizzly-nio-kernel(3) SelectorRunner, fatal: engine already closed. Rethrowing javax.net.ssl.SSLHandshakeException: no cipher suites in common

To add on top of JMS comment, his answer solve my problem too .
Here is the command i used to generate the RSA certificate .
keytool -genkey -keystore ./keystore_client -alias clientKey -keyalg RSA -keypass changeit -storepass changeit -dname "CN=Client, OU=Jersey, O=changeit, L=KL, ST=SEL, C=MY"
keytool -export -alias clientKey -storepass changeit -keystore ./keystore_client -file ./client.cert
keytool -import -alias clientCert -file ./client.cert -storepass changeit -keystore ./truststore_server
keytool -genkey -keystore ./keystore_server -alias serverKey -keyalg RSA -keyalg RSA -keypass changeit -storepass changeit -dname "CN=changeit, OU=Jersey, O=changeit, L=KL, ST=SEL, C=MY"
keytool -export -alias serverKey -storepass changeit -keystore ./keystore_server -file ./server.cert
keytool -import -alias serverCert -file ./server.cert -storepass changeit -keystore ./truststore_client

I have seen this type of handshake issue come up in other posts while trying to run this issue to ground. In all of these handshake posts, the server key algorithm was never discussed - I wish it had been. It would have saved me a couple of hours. The issue that caused the above errors stemmed from assuming that the keystores that were created as part of the Jersey sample project would work. The server key was the problem.
The sample server certs are generated using the DSA algorithm. Apparently this is an issue.
I recreated the server keys using a RSA algorithm and 2048 bit strength. I restarted the server and the everything started to work like one would expect.
The error was that I assumed that the "sample" keys would work. Oops.

Related

TLS in Java fails with javax.net.ssl.SSLHandshakeException Exception message: Received fatal alert: bad_certificate

I've seen some similar threads but None of them helped me.
I generate new key pair for the server using command:
keytool -genkey -alias test-tls-server -keystore TestServerKeyStore.jks -storetype JKS -keyalg RSA -sigalg SHA1withRSA -validity 365
I export servers certificate to cer file:
keytool -export -alias test-tls-server -file test_server.cer -keystore TestServerKeyStore.jks
I create client key store using command:
keytool -import -keystore TestClientKeyStore.jks -storetype JKS -alias test-tls-server -file test_server.cer
Note that the certificate is self-signed purposely.
I also configure locations and passwords for keystores on both sides:
System.setProperty("javax.net.ssl.keyStore", <path_to_keystore_file>);
System.setProperty("javax.net.ssl.keyStorePassword", <pass_to_keystore>);
When I try to connect to server, on client side everything looks OK until I try to read something from the socket.
On server side I get the following error:
javax.net.ssl.SSLHandshakeException Exception message: Received fatal
alert: bad_certificate
This code worked for previous certificate but since it expired I need to generate the new one. I have no clue what I'm doing wrong here.
I would appreciate any help.

KeyStore and TrustStore load failed - Private key must be accompanied by certificate chain

I have created a self signed certificate using the following command:
keytool -genkeypair -keyalg RSA -alias test-api -keystore test-api.p12 -storepass password -validity 3650 -keysize 2048 -storetype pkcs12
I then imported this keystore into new truststore:
keytool -import -trustcacerts -alias test-api-2018 -file test.crt -keystore trusted-keystore.p12 -storetype pkcs12
In Java, creating a custom SSL store provider (org.springframework.boot.context.embedded.SslStoreProvider). As a part of it, loaded keystore and truststore using the following Java code:
try {
try (final InputStream keyStoreStream = new ByteArrayInputStream(Base64.decode(keyStoreEncoded))) {
keyStore = KeyStore.getInstance(KEYSTORE_TYPE_PKCS12);
LOGGER.info("Loading a KeyStore object based on the decoded value.");
keyStore.load(keyStoreStream, serverSslKeyPassword.toCharArray());
}
....
trustStore.load(trustStoreStream, serverSslTrustStorePassword.toCharArray());
}
Created custom implementation of EmbeddedServletContainerCustomizer and set SSL Provider:
public void customize(final ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) {
configurableEmbeddedServletContainer.setSslStoreProvider(awsSslStoreProvider);
}
Application fails to start because of the following error:
Caused by: java.lang.IllegalArgumentException: Private key must be accompanied by certificate chain
at java.security.KeyStore.setKeyEntry(KeyStore.java:1136)
at org.apache.tomcat.util.net.jsse.JSSEUtil.getKeyManagers(JSSEUtil.java:253)
at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:114)
... 19 common frames omitted
I just jad this problem to today, the problem occurs when the security config in the application.properties file isnt configured properly, this causes the certificate chain to break.
in my case i used
server.ssl.key-password=123456789
instead of
server.ssl.key-store-password=123456789
minor issues like this can cause issues.
This also happens when using BouncyCastle as PKCS12 key store provider and the key alias is using incorrect upper case.
E.g. (incorrect):
server.ssl.key-alias=17B2E92E5694C7AE11A65C4A4EBFC75558399E05
instead (correct):
server.ssl.key-alias=17b2e92e5694c7ae11a65c4a4ebfc75558399e05
The strange thing about this error is that the key is found, so obviously is not case sensitive, but the check for ks.getCertificateChain(keyAlias) is.

Mutual Authentication - null cert chain

I'm trying to set up mutual (2 way) SSL authentication. Ultimately I will have a mulesoft application (as client) calling a webapp (as the server). For now I am testing using Firefox browser as the client to simplify testing.
I followed this tutorial
http://www.baeldung.com/x-509-authentication-in-spring-security
and managed to get this working fine. This uses a self signed certificate for the server and a self signed certificate for the client which is installed into firefox to make the client call.
So far so good...
However I am having issues once I try and use certificates signed by my company.
So I have a client certificate which my company has signed. This has been provided as a client.cer file. I can view the details of this and see that it is issued by the company intermediary (which in turn is issued by the company root CA)
The client CSR was created with
keytool -genkey -alias client -keyalg RSA -keysize 2048 -keystore client.jks -dname "CN=client-dev,OU=Dept, O=Company, L=London, ST=Greater London, C=GB"
keytool -certreq -alias client -file client.csr -keystore client.jks
The next step of my testing is to try and use this company signed client.cer file to call my server on localhost (which is using a self signed certificate as per the tutorial).
On having received the signed client.cer file the steps I have taken are...
Import the companies Root.cer into the keystore I used to generate my
client certificate signing request.
Import the companies Intermediate.cer into the same keystore.
Import the client.cer into the same keystore
I then export a p12 file from this keystore and install this into firefox as my client certificate.
The commands I use to do this are as follows
keytool -import -trustcacerts -alias primaryintermediate -file Root.cer -keystore client.jks -storepass <pwd>
keytool -import -trustcacerts -alias secondaryintermediate -file Int.cer -keystore client.jks -storepass <pwd>
keytool -import -trustcacerts -alias client -file client.cer -keystore client.jks -storepass <pwd>
keytool -importkeystore -srcalias client -srckeystore client.jks -srcstorepass <pwd> -destkeystore "client.p12" -deststorepass <pwd> -deststoretype PKCS12
However when I try and hit my localhost app endpoint from firefox and view the log output I see the server side SSL handshake succeed but then get a "null cert chain" error in the client handshake. So the following steps look to succeed
ClientHello
ServerHello
Certificate
CertificateRequest
ServerHelloDone
Certificate - Error occurs here
The relevant part of the log looks like this...
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
Cert Authorities:
<CN=Root>
<CN=client-dev, OU=Dept, O=Company, L=London, ST=Greater London, C=GB>
<CN=Intermediate, DC=HBEU, DC=ADROOT, DC=Company>
*** ServerHelloDone
https-jsse-nio-8443-exec-1, WRITE: TLSv1.2 Handshake, length = 2710
https-jsse-nio-8443-exec-2, READ: TLSv1.2 Handshake, length = 77
*** Certificate chain
<Empty>
***
https-jsse-nio-8443-exec-2, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain
I'm unclear what I have done wrong but assume I must have created the p12 file incorrectly?
Can anyone point me in the right direction?

Unable to load certificate chain to java keystore

I have a blah.p7b certificate type PKCS#7 which i want to import it to a java keystore using keytool in order to enable HTTPS on tomcat , i don't have the alias name and keystore when the certificate was generated i took it from the client whose want to enable https on our web-application server that they use, can this works without having the original alias name and keystore ?
when i tried to import the certificate i used this command
keytool -import -trustcacerts -file certificate.p7b -keystore keystore -storepass <mypasswd> -alias "myalias"
but it gives me this error
keytool error: java.lang.Exception: Certificate reply does not contain public key for <mydomain>
Please help...
If you haven't got the original KeyStore you are hosed. You have to generate a new KeyStore, a new keypair, a new CSR, get it signed, and then import the signed cert and its chain into the KeyStore using the same alias as the keypair.

java.security.KeyStoreException: failed to extract any certificates or private keys - maybe bad password?

I'm using Not-yet commons SSL to develop my own TLS Socket.
But always got No private keys found in keystore on following code
private SSLServer sslS=null;
//...
sslS=new SSLServer();
KeyMaterial km=new KeyMaterial(certChain, privateKeyFile, certPassword.toCharArray(), privateKeyPassword.toCharArray());
The certChain used original JRE's cacert:
C:/Program Files/Java/jre1.8.0_101/lib/security/cacerts
This give me a java.security.KeyStoreException: No private keys found in keystore!
The certChain used my own:
keytool -certreq -alias 127.0.0.1 -keystore ServerKey.jks -file 127.0.0.1.csr
This give me a java.security.KeyStoreException: failed to extract any certificates or private keys - maybe bad password?
But I can 100% sure that my password is right. My password is a simple "123456", there is no reason I can do wrong on it.
The privateKey I generated by:
keytool -genkey -alias 127.0.0.1 -keyalg RSA -keystore ServerKey.jks -keysize 2048
How can I solve this problem, any suggestion ?

Categories

Resources