I am trying to create a bespoke SSL context through code as we are unable to provide keystore.jks using VM arguments -Djavax.net.ssl.trustStore in the code.
I am creating a rest template along the lines:
#Bean
RestTemplate restTemplate() throws Exception {
SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(
keyStore.getURL(),
keyStorePassword.toCharArray()
).loadKeyMaterial(keyStore.getURL(),
keyStorePassword.toCharArray(),
keySecret.toCharArray(),
(aliases, socket) -> keyAlias
).build();
SSLConnectionSocketFactory socketFactory =
new SSLConnectionSocketFactory(sslContext);
HttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(socketFactory).build();
HttpComponentsClientHttpRequestFactory factory =
new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(factory);
}
but I am getting the following error:
http-nio-8080-exec-1, handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I am sure that the certificate is being loaded in as I have -Djavax.net.debug=ssl enabled and I see the following
adding as trusted cert:
...
...
and on the handshake I can see till
%% Invalidated: [Session-1, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384]
http-nio-8080-exec-1, SEND TLSv1.2 ALERT: fatal, description = certificate_unknown
http-nio-8080-exec-1, WRITE: TLSv1.2 Alert, length = 2
http-nio-8080-exec-1, called closeSocket()
Related
I wrote an Http Client using Apache HttpClient 4.1.13 which call a remote HTTP service using 2way-ssl.
I configured:
keystore.jks : contains the private key and the client certificate
keystore password: the password of keystore.jks
truststore.jks: contains the certificate of CA e intermediate CA of the server
truststore password: the password of truststore.jks
the code:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(new File(keystore));
try {
keyStore.load(instream, keyStorePassword.toCharArray());
} finally {
instream.close();
}
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
instream = new FileInputStream(new File(trustore));
try {
trustStore.load(instream, trustorePassword.toCharArray());
} finally {
instream.close();
}
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(keyStore, keyStorePassword.toCharArray())
.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
.build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslContext,
new String[] {"TLSv1.1","TLSv1.2"},
null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
poolingConnManager = new PoolingHttpClientConnectionManager(
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", sslsf)
.build());
If I run a java main (JDK Java(TM) SE Runtime Environment (build 1.8.0_231-b11) which does the call, I got a successful connection and I see in the logs
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - Secure session established
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - negotiated protocol: TLSv1.2
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - negotiated cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - peer principal: XXXXX
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - peer alternative names: [YYYYY]
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - issuer principal: XXXXX
If I run the same code with the same keystores and passwords in Docker OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_252-b09)) I got the following handshake error
http-nio-8080-exec-1, READ: TLSv1.2 Alert, length = 2
http-nio-8080-exec-1, RECV TLSv1.2 ALERT: fatal, handshake_failure
%% Invalidated: [Session-1, SSL_NULL_WITH_NULL_NULL]
%% Invalidated: [Session-2, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]
http-nio-8080-exec-1, called closeSocket()
http-nio-8080-exec-1, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
[2022-01-25 16:47:45][SESSION_NOT_INITIALIZED][10.60.168.202][http-nio-8080-exec-1] [DEBUG]o.a.h.i.c.DefaultManagedHttpClientConnection - http-outgoing-0: Shutdown connection
[2022-01-25 16:47:45][SESSION_NOT_INITIALIZED][10.60.168.202][http-nio-8080-exec-1] [DEBUG]o.a.h.impl.execchain.MainClientExec - Connection discarded
What should I search ? Any hints?
UPDATE:
The keystore contains the private key and the certificate chain : certificate -> intermediate CA -> Root CA; I don't understand why the client doesn't find the right certificate to send to the server.
In the working test I got this log
*** ServerHelloDone
[read] MD5 and SHA1 hashes: len = 4
0000: 0E 00 00 00 ....
matching alias: 1
*** Certificate chain
In the failed test I got:
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
It was my mistake and the problem was in totally different point.
The above code was right.
I am currently new in grpc.
I wanted to provide ssl for my grpc server
the javav code for starting looks like this:
InputStream publicKey = ServerStarter.class.getResourceAsStream("/my-public-key-cert.pem");
InputStream privateKey = ServerStarter.class.getResourceAsStream("/my-private-key.pem");
SslContext sslContext = GrpcSslContexts.forServer(publicKey, privateKey).build();
Server server = NettyServerBuilder.forPort(5555)
.sslContext(sslContext)
.addService(new RedirectService())
.intercept(new AuthorizationInterceptor())
.build();
server.start();
SSL certificates were generated with openssl. And here how openssl command looks like:
openssl req -x509 -newkey rsa:4096 -keyout ./grpc-server/src/main/resources/my-private-key.pem -out ./grpc-server/src/main/resources/my-public-key-cert.pem -days 365 -nodes -subj "/CN=192.168.88.132" -addext "subjectAltName = DNS.1:192.168.88.132, DNS.2:localhost"
Server runs fine.
But I can't connect to server.
My clients code looks like this:
InputStream certificate = GalamatClient.class.getResourceAsStream("/my-public-key-cert.pem");
SslContext context = GrpcSslContexts.forClient().trustManager(certificate).build();
ManagedChannel channel = NettyChannelBuilder.forTarget("192.168.88.132:5555")
.sslContext(context)
.build();
GreetingServiceGrpc.GreetingServiceBlockingStub stub = GreetingServiceGrpc.newBlockingStub(channel)
GreetingService.GreetingRequest request = GreetingService.GreetingRequest.newBuilder().setMessage("Hi").build();
GreetingService.GreetingResponse response = stub.greet(request);
channel.shutdownNow();
And when I try to run client next Error occurs:
Exception in thread "main" io.grpc.StatusRuntimeException: UNAVAILABLE: io exception
Channel Pipeline: [SslHandler#0, ProtocolNegotiators$ClientTlsHandler#0, WriteBufferingAndExceptionHandler#0, DefaultChannelPipeline$TailContext#0]
at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:262)
at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:243)
at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:156)
at com.example.GreetingServiceGrpc$GreetingServiceBlockingStub.recognize(SpeechRecognitionGrpc.java:246)
at com.example.main(Client.java:59)
Caused by: javax.net.ssl.SSLHandshakeException: General OpenSslEngine problem
at io.grpc.netty.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslEngine.handshakeException(ReferenceCountedOpenSslEngine.java:1772)
at io.grpc.netty.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslEngine.wrap(ReferenceCountedOpenSslEngine.java:777)
at javax.net.ssl.SSLEngine.wrap(SSLEngine.java:509)
at io.grpc.netty.shaded.io.netty.handler.ssl.SslHandler.wrap(SslHandler.java:1079)
at io.grpc.netty.shaded.io.netty.handler.ssl.SslHandler.wrapNonAppData(SslHandler.java:970)
at io.grpc.netty.shaded.io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1443)
at io.grpc.netty.shaded.io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1275)
at io.grpc.netty.shaded.io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1322)
at io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:501)
at io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:440)
at io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.grpc.netty.shaded.io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
at io.grpc.netty.shaded.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.grpc.netty.shaded.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.grpc.netty.shaded.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address 192.168.88.132 found
at sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:168)
at sun.security.util.HostnameChecker.match(HostnameChecker.java:94)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:459)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:440)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:261)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:144)
at io.grpc.netty.shaded.io.netty.handler.ssl.OpenSslTlsv13X509ExtendedTrustManager.checkServerTrusted(OpenSslTlsv13X509ExtendedTrustManager.java:223)
at io.grpc.netty.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslClientContext$ExtendedTrustManagerVerifyCallback.verify(ReferenceCountedOpenSslClientContext.java:261)
at io.grpc.netty.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslContext$AbstractCertificateVerifier.verify(ReferenceCountedOpenSslContext.java:698)
at io.grpc.netty.shaded.io.netty.internal.tcnative.SSL.readFromSSL(Native Method)
at io.grpc.netty.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslEngine.readPlaintextData(ReferenceCountedOpenSslEngine.java:596)
at io.grpc.netty.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslEngine.unwrap(ReferenceCountedOpenSslEngine.java:1203)
at io.grpc.netty.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslEngine.unwrap(ReferenceCountedOpenSslEngine.java:1325)
at io.grpc.netty.shaded.io.netty.handler.ssl.SslHandler$SslEngineType$1.unwrap(SslHandler.java:201)
at io.grpc.netty.shaded.io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1380)
... 21 more
Suppressed: javax.net.ssl.SSLHandshakeException: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED
at io.grpc.netty.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslEngine.sslReadErrorResult(ReferenceCountedOpenSslEngine.java:1288)
at io.grpc.netty.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslEngine.unwrap(ReferenceCountedOpenSslEngine.java:1249)
... 24 more
Error says that I don't provide needed Ip in subject alternative names:
No subject alternative names matching IP address 192.168.88.132 found
but I provided it in command of creation certificate.
I will apreciate if you could help with that.
Use overrideAuthority(String authority) to match what the certificate has in its SAN. Use an OpenSsl command to display what you have in your server cert.
I'm trying to make a request with OKHttp and Retrofit 2. This request should be done by sending a certificate (it must be a p12 or a crt). We've tried different ways, but no one allows me to succeed. I am testing with badssl.com, which allows me to make request to this URL: https://client.badssl.com with a certificate that you can find here: https://badssl.com/download/
I've tried to include the p12 and the crt in the assets folder and in the raw folder of the project and creating a Keystore, SSLSocketFactory and TrustManager.
Since this wasn't working, I've also tried to create an unsafe OkHttpClient that can make any request, but I didn't succeed.
In both the cases, I've got:
"javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found"
public static SSLContext getSSLConfig(Context context) throws CertificateException, IOException,
KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
// Loading CAs from an InputStream
CertificateFactory cf = null;
cf = CertificateFactory.getInstance("X.509");
Certificate ca;
// I'm using Java7. If you used Java6 close it manually with finally.
try (InputStream cert = context.getResources().openRawResource(R.raw.somecert)) {
ca = cf.generateCertificate(cert);
}
// Creating a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Creating a TrustManager that trusts the CAs in our KeyStore.
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Creating an SSLSocketFactory that uses our TrustManager
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
return sslContext;
}
val client: OkHttpClient = OkHttpClient.Builder()
.sslSocketFactory(SSLConfigUtils.getSSLConfig(MyClass.getContext()).socketFactory)
.hostnameVerifier { _, _ -> true }
.build()
val retrofit = Retrofit.Builder()
.addCallAdapterFactory(
RxJava2CallAdapterFactory.create())
.addConverterFactory(
GsonConverterFactory.create(gson))
.baseUrl("https://client.badssl.com/")
.client(client)
.build()
I expect to make correctly Retrofit requests, but every request returns me this error:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.google.android.gms.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(:com.google.android.gms#17122040#17.1.22 (100700-245988633):43)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:319)
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:283)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:168)
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
at okhttp3.RealCall.execute(RealCall.java:92)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:186)
at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:41)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:578)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:656)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:615)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:505)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:424)
at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:352)
at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:89)
at java.lang.reflect.Method.invoke(Native Method)
at com.google.android.gms.org.conscrypt.Platform.checkTrusted(:com.google.android.gms#17122040#17.1.22 (100700-245988633):2)
2019-05-23 11:37:15.389 5640-5640/it.sogetel.agtcs E/Errore: at com.google.android.gms.org.conscrypt.Platform.checkServerTrusted(:com.google.android.gms#17122040#17.1.22 (100700-245988633):1)
at com.google.android.gms.org.conscrypt.ConscryptFileDescriptorSocket.verifyCertificateChain(:com.google.android.gms#17122040#17.1.22 (100700-245988633):12)
at com.google.android.gms.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.google.android.gms.org.conscrypt.NativeSsl.doHandshake(:com.google.android.gms#17122040#17.1.22 (100700-245988633):7)
at com.google.android.gms.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(:com.google.android.gms#17122040#17.1.22 (100700-245988633):14)
... 33 more
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
... 47 more
There’s a test case in OkHttp that configures client authentication. It might need useful as an example, though you should note that it generates certificates in memory rather than loading them from a file.
The relevant code is in the okhttp-tls module.
Also note that your TrustManager must include the server’s certificate, or one of the certificate authority root certificates that signed it.
what is wrong with this code, it is supposed to trust all hosts, but it doesn't..
It works fine with for example google.com but not with an API Gateway service running locally on my machine, why?
SSL DEBUG OUTPUT
trigger seeding of SecureRandom done seeding SecureRandom Ignoring
unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 ...
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256
Allow unsafe renegotiation: false Allow legacy hello messages: true Is
initial handshake: true Is secure renegotiation: false Thread-6,
setSoTimeout(0) called %% No cached client session
*** ClientHello, TLSv1 RandomCookie: GMT: 1434280256 bytes = { 216 ... 40 } Session ID: {} Cipher Suites:
[TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, ....
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_RC4_128_MD5,
TLS_EMPTY_RENEGOTIATION_INFO_SCSV] Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1 .. secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Thread-6, WRITE: TLSv1 Handshake, length = 163 Thread-6, READ: TLSv1
Alert, length = 2 Thread-6, RECV TLSv1 ALERT: fatal,
handshake_failure Thread-6, called closeSocket() Thread-6, handling
exception: javax.net.ssl.SSLHandshakeException: **
Received fatal alert: handshake_failure
**
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
public class ConnectHttps {
public static void main(String[] args) throws Exception {
/*
* fix for
* Exception in thread "main" javax.net.ssl.SSLHandshakeException:
* sun.security.validator.ValidatorException:
* PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
* unable to find valid certification path to requested target
*/
TrustManager[] trustAllCerts = [
[ getAcceptedIssuers: { -> null },
checkClientTrusted: { X509Certificate[] certs, String authType -> },
checkServerTrusted: { X509Certificate[] certs, String authType -> } ] as X509TrustManager
]
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
/*
* end of the fix
*/
//URL url = new URL("https://google.com"); //WORKS
URL url = new URL("https://localhost:8090"); // DOES NOT WORK, WHY?
URLConnection con = url.openConnection();
Reader reader = new InputStreamReader(con.getInputStream());
while (true) {
int ch = reader.read();
if (ch==-1) {
break;
}
System.out.print((char)ch);
}
}
}
Running the code found here it shows that TLSv1.2 is not enabled on the client side:
Supported Protocols: 5
SSLv2Hello
SSLv3
TLSv1
TLSv1.1
TLSv1.2
Enabled Protocols: 2
SSLv3
TLSv1
.. it is supposed to trust all hosts, but it doesn't..
.. RECV TLSv1 ALERT: fatal, handshake_failure Thread-6
A handshake failure alert from the server is unrelated to the validation of the servers certificate on the client and can thus not stopped by disabling certificate validation. Lots of things can cause such a failure, like no common ciphers, unsupported protocol version, missing SNI extension (only supported starting with JDK7). Since the error is issued by the server you might find more details about the problem in the servers log messages.
EDIT: from the server logs the cause of the problem is visible:
error handling connection: SSL protocol error error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher
This means that there is no common cipher between client and server.
A typical cause for this is a wrong setup of the certificates at the server. If you don't configure any certificates the server might require anonymous authentication with ADH ciphers, which are usually not enabled on the client side. I suggest that you check if you could connect with a browser.
Another common misconfiguration is disabling all SSLv3 ciphers at the server in the believe that this is necessary to disable the SSL3.0 protocol (it is not). This effectively disables all ciphers except some new ciphers introduced with TLS 1.2. Modern browsers will be still able to connect but older clients not. This misconfiguration can be seen in this case (from the comment):
From server log,, interface ciphers: FIPS:!SSLv3:!aNULL,,
!SSLv3 disables all ciphers available for version SSL3.0 and higher. This in effect leaves only the TLS1.2 ciphers because there are no new ciphers with TLS1.0 and TLS1.1. Since the client seems to be only support TLS1.0 there will be no shared ciphers:
...WRITE: TLSv1 Handshake
Use of !SSLv3 in the ciphers is usually caused by a lack of understanding of the difference between protocol version and ciphers. To disable SSLv3 you should only set the protocol accordingly but not the ciphers.
I have problem with certificate. This is my stack trace:
trustStore is: /usr/user/programs/java/jdk1.7.0_10/jre/lib/security/jssecacerts
trustStore type is : jks
trustStore provider is :
init truststore
adding as trusted cert:
Subject: EMAILADDRESS=******, CN=865409164, OU=http://www.sistem.net, O=DOO, L=Citluk, ST=Text, C=BA
Issuer: EMAILADDRESS=***********, CN=ecommtest.rbbh.ba, OU=ITRIOSS.CARD, O=BANK, L=CITY, ST=******, C=BA
Algorithm: RSA; Serial number: 0xf6e5b0e213f9b11b
Valid from Tue Jul 30 14:43:23 CEST 2013 until Wed Jul 30 14:43:23 CEST 2014
and at the end I got this:
***
%% Invalidated: [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA]
main, SEND TLSv1 ALERT: fatal, description = certificate_unknown
main, WRITE: TLSv1 Alert, length = 2
[Raw write]: length = 7
0000: 15 03 01 00 02 02 2E .......
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
main, IOException in getSession(): javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
main, called close()
main, called closeInternal(true)
I've got certifacte as PKCS12, then I importkeystore by keytool in jssecacerts and copy it in JDK/jre/lib/security
I use apache HttpClient to execute POST request.
Thanks for any help
Zlaja
We have found solution. These are steps:
Run InstallCert from https://code.google.com/p/java-use-examples/source/browse/trunk/src/com/aw/ad/util/InstallCert.java. It will create jssecacerts.
Backup your cacerts from jre/lib/security
Replace cacerts with jssecacert
Change your code like this:
val clientStore = KeyStore.getInstance("PKCS12")
clientStore.load(new FileInputStream("/home/zlaja/Downloads/imakstore_80009164.p12"), "12348765".toCharArray())
val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
kmf.init(clientStore, "12348765".toCharArray())
val kms = kmf.getKeyManagers()
val trustStore = KeyStore.getInstance("JKS")
trustStore.load(new FileInputStream("/usr/user/programs/java/jdk1.7.0_10/jre/lib/security/cacerts"), "changeit".toCharArray())
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
tmf.init(trustStore)
val tms = tmf.getTrustManagers()
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(kms, tms, new SecureRandom())
val schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("https", new SSLSocketFactory(init), 443))
val client = new DefaultHttpClient(new ThreadSafeClientConnManager(httpParameters, schemeRegistry), httpParameters);
I had this problem as well, but I finally have a solution that works for my JAX-WS client with SSL.
The problem in my case was JAX not able to look in another keystore but cacerts, and my certificate has 2 chained which was impossible to import via command line to cacerts.