enable HTTPS with self signed certificate on Sprint Boot - java

I'm trying to launch web server with HTTPS on Spring Boot 1.4 ( and on 2.0.X). But I fail to connect to started server.
Here is my steps:
Add SSL properties to application.yml
server:
ssl:
enabled: true
key-store: classpath:keystore.jks
key-store-password: password
key-password: password
key-alias: tomcat
port: 8443
Generate self sign certificate on src/main/resources
`keytool -genkey -alias tomcat -keyalg RSA -keystore keystore.jks
After run of application
`mvn clean install && java -jar target/audiochat.war
Then in browser https://localhost:8433 (Chrome, Firefox, Edge)
ERR_SSL_VERSION_OR_CIPHER_MISMATCH
I was try to test SSL handshake
openssl s_client -connect localhost:8443
CONNECTED(000001A8)
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 308 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : 0000
Session-ID:
Session-ID-ctx:
Master-Key:
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1522596727
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
28412:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:769:
Any ideas on correct setup of HTTPS on SpringBoot ?

Related

Trying to download and setup the certificate from a remote SSL address for WebSocket connection but getting a "Signature does not match" exception

First I downloaded the certificate with:
echo "" | openssl s_client -connect io.lightstream.bitflyer.com:443 -showcerts 2>/dev/null | openssl x509 -out bitflyer.cer
Then I imported the certificate into a keychain:
keytool -import -file bitflyer.cer -alias bitflyer -keystore bitflyer.jks -storepass "abc123" -keypass "abc123"
So I'm trying to connect to io.lightstream.bitflyer.com:443. Below my full handshake:
Sending HTTP handshake! req=GET / HTTP/1.1
Host: io.lightstream.bitflyer.com
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Sec-WebSocket-Key: 0enPg4mnHvLcT6s7+4mEGA==
Origin: http://www.websocket.org
Sec-WebSocket-Version: 13
But then I get:
Caused by: sun.security.validator.ValidatorException: Certificate signature validation failed
at sun.security.validator.SimpleValidator.engineValidate(SimpleValidator.java:215)
at sun.security.validator.Validator.validate(Validator.java:262)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:330)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:289)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:144)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1626)
... 16 more
Caused by: java.security.SignatureException: Signature does not match.
at sun.security.x509.X509CertImpl.verify(X509CertImpl.java:449)
at sun.security.x509.X509CertImpl.verify(X509CertImpl.java:392)
at sun.security.validator.SimpleValidator.engineValidate(SimpleValidator.java:213)
... 21 more
Any ideas what am I doing wrong or how to debug that? Thanks!
openssl s_client -connect io.lightstream.bitflyer.com:443
The certificates you get here depend on the OpenSSL version. Up to 1.0.2 the server_name extension (SNI) was not automatically used (i.e. you had to explicitly to use -servername) and without the the resulting certificate is a self-signed certificate for "Kubernetes Ingress Controller Fake Certificate". With SNI though the certificate is the proper certificate for "io.lightstream.bitflyer.com".
My guess is that you actually added to the certificate for "Kubernetes Ingress Controller Fake Certificate" while Java is using SNI and thus getting the certificate for "io.lightstream.bitflyer.com" instead. Or it might be the other way around, depending on your version of OpenSSL, of Java and of the actual Java code.

Spring Boot app calling another Spring Boot app over HTTPS and getting SSL certificate verification error: "signature check failed"

I have two Spring Boot applications each running in their own docker container.
One is REST Client and the other is REST API.
When the client calls the API ( i.e. GET https://localhost:8443/api/someResource ), I get the following error:
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: signature check failed
Each spring boot app has its own keystore and self-signed certificate stored in
src/main/resources/keystore.p12
... here's what I have in the application.yml files:
following properties:
server.ssl.key-store: classpath:keystore.p12
server.ssl.key-store-password: somethingsecure
server.ssl.keyStoreType: PKCS12
server.ssl.keyAlias: client or server (depending which .yml file your looking at)
I tested this outside of Docker and everything worked fine! I simply exported the API certificate out of the keystore.p12 file and imported it into my JRA cacerts file.
You can see from my REST Client Dockerfile, I do the same thing there:
FROM openjdk:8-jdk-alpine
EXPOSE 8443
WORKDIR /usr/src/app
COPY client.jar client.jar
COPY server.crt server.crt
RUN keytool -v -import -noprompt -alias server -file server.crt -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "client.jar"]
I've turned SSL debugging on and can see the following:
trustStore is: /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/cacerts
trustStore type is : jks
trustStore provider is :
init truststore
...
adding as trusted cert:
Subject: CN=localhost, OU=Development, O=Microgen, L=Fleet, ST=Hampshire, C=UK
Issuer: CN=localhost, OU=Development, O=Microgen, L=Fleet, ST=Hampshire, C=UK
Algorithm: RSA; Serial number: 0x4c1fbbc3
Valid from Mon Apr 16 09:49:33 GMT 2018 until Tue Apr 16 09:49:33 GMT 2019
Any ideas?
Thanks,
Ben
I am no expert but when exporting the certificate and importing I wonder if in your new location the certificate chain is the same as the location you took it from.
Here is a link that might provide some insight, under the Cause section
https://confluence.atlassian.com/kb/connecting-to-ssl-services-802171215.html
I've managed to figure this out this morning. The server certificate was simply corrupt and since regenerating, this worked.

SSL with Spring and Jetty

I am tryign to implement SSL to my Spring App. I generated SSL key by keytool and put it to my application.properties. During compilation i get message:
Jetty started on port(s) 8443 (ssl, http/1.1)
but when i try to send rest query from my Angular 2 i got response: "Aborted". Also from terminal crud query i get :
Trying ::1...
Connected to localhost (::1) port 8443 (#0)
found 173 certificates in /etc/ssl/certs/ca-certificates.crt
found 694 certificates in /etc/ssl/certs
ALPN, offering http/1.1
gnutls_handshake() failed: Handshake failed
Closing connection 0
curl: (35) gnutls_handshake() failed: Handshake failed
Any idea? Thank you in advance.
Try to create your self signed certificate with following
keytool -genkeypair -keystore keystore.jks -storepass PASSWORD -keypass PASSWORD -alias jetty -keyalg RSA -keysize 2048 -validity 5000 -dname "CN=HOSTNAME, OU=Example, O=Example, L=Unspecified, ST=Unspecified, C=US" -ext "SAN=DNS:HOSTNAME,IP:IPADDRESS" -ext "BC=ca:true"
Change PASSWORD, HOSTNAME and IPADDRESS where needed.
Check if Angular 2 connecting via HTTP/1.1 protocol, also verify localhost:8443 with curl, curl performs SSL certificate verification by default, if there's any error, please write it here.

Configuring SSL in dropwizard using code

I'm using Dropwizard 0.7.0-rc2 for REST API. I have tried configuring SSL through config.yaml and it is working on local machine.
Below is the content in config.yaml
server:
# softNofileLimit: 1000
# hardNofileLimit: 1000
applicationConnectors:
- type: http
port: 8080
- type: https
port: 13790
keyStorePath: xxx.keystore
keyStorePassword: xxx
validateCerts: false
validatePeers: false
#this requires the alpn-boot library on the JVM's boot classpath
#- type: h2
# port: 8445
# keyStorePath: xxx.keystore
# keyStorePassword: xxx
# validateCerts: false
# validatePeers: false
adminConnectors:
- type: http
port: 8081
- type: https
port: 13790
keyStorePath: xxxx.keystore
keyStorePassword: xxxxx
validateCerts: false
validatePeers: false
I tried with this on production server but it gives me the error Failed to parse configuration at: server.applicationConnectors; Could not resolve type id 'http' into a subtype
Then I tried by adding code.
public void run(MyConfiguration configuration, Environment environment)
throws Exception {
((DefaultServerFactory) configuration.getServerFactory()).getApplicationConnectors().add(new HttpsConnectorFactory());
((DefaultServerFactory) configuration.getServerFactory()).getAdminConnectors().add(new HttpsConnectorFactory());
((HttpConnectorFactory) ((DefaultServerFactory) configuration.getServerFactory()).getApplicationConnectors().get(0)).setPort(13789);
((HttpConnectorFactory) ((DefaultServerFactory) configuration.getServerFactory()).getAdminConnectors().get(0)).setPort(13777);
((HttpsConnectorFactory) ((DefaultServerFactory) configuration.getServerFactory()).getApplicationConnectors().get(1)).setPort(13790);
((HttpsConnectorFactory) ((DefaultServerFactory) configuration.getServerFactory()).getAdminConnectors().get(1)).setPort(13791);
HttpsConnectorFactory cf1 = (HttpsConnectorFactory) ((HttpConnectorFactory) ((DefaultServerFactory) configuration.getServerFactory()).getApplicationConnectors().get(1));
cf1.setKeyStoreType("JKS");
cf1.setKeyStorePath("/var/***.jks");
cf1.setKeyStorePassword("*****");
cf1.setValidateCerts(true);
cf1.setValidatePeers(true);
}
By above code,it binds the port but fail to connect.
I get following error while testing using openssl
140573632874312:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:598:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 0 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : SSLv3
Cipher : 0000
Session-ID:
Session-ID-ctx:
Master-Key:
Key-Arg : None
Krb5 Principal: None
PSK identity: None
PSK identity hint: None
Start Time: 1457936036
Timeout : 7200 (sec)
Verify return code: 0 (ok)
---
I have also tried with using shaded-jar for deployment, but it was not working.
Please help me resolve the issue.

Java TLS client can't find certificate when accessing soap service

I have a java app that runs inside Tomcat. It is trying to access a TLS client certificate authenticated SOAP service. All certificates being used are self-signed. I specify the trustStore and keyStore via the Java Options in Tomcat and I have also tried doing it in code for all the needed properties before creating my service. Both keyStore and trustStore are JKS with RSA certificates. I have verified the certificates exist in the server's trustStore and that the self client certificate exists in the client keyStore and that the hashes are the same.
Client side:
c:\Program Files\Java\jre7\bin>keytool -list -keystore c:\tomcat\certs\tomcat.keystore
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
tomcat, Jan 20, 2014, PrivateKeyEntry,
Certificate fingerprint (SHA1): 78:F3:30:A0:40:B0:CC:8D:86:1F:99:FF:7C:3B:85:7C:6D:C7:F2:D2
Server side:
C:\Program Files (x86)\Java\jre7\bin>keytool -list -keystore c:\tomcat\certs\tomcat.truststore
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
clientcert, Jan 23, 2014, trustedCertEntry,
Certificate fingerprint (SHA1): 78:F3:30:A0:40:B0:CC:8D:86:1F:99:FF:7C:3B:85:7C:6D:C7:F2:D2
When I start Tomcat I see the loading of the keystore like this:
keyStore is : c:\tomcat\certs\tomcat.keystore
keyStore type is : JKS
keyStore provider is :
init keystore
init keymanager of type SunX509
***
found key for : tomcat
chain [0] = [
[
Version: V3
Subject: CN=Name, OU=Engineering, O=MyOrg, ST=NJ, C=US
...
At the end of server hello I see the certificate DN that I expect and was loaded from the keystore above:
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Cert Authorities:
<CN=Name, OU=Engineering, O=MyOrg, ST=NJ, C=US>
[read] MD5 and SHA1 hashes: len = 115
...
Then immediately after the ServerHelloDone I see an empty Certificate chain with no "matching alias: mycert" logging like I would expect to see.
*** ServerHelloDone
[read] MD5 and SHA1 hashes: len = 4
0000: 0E 00 00 00 ....
*** Certificate chain
***
Server side I get this:
http-nio-8443-exec-2, READ: TLSv1 Handshake, length = 269
*** Certificate chain
***
http-nio-8443-exec-2, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain
%% Invalidated: [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA]
http-nio-8443-exec-2, SEND TLSv1 ALERT: fatal, description = bad_certificate
http-nio-8443-exec-2, WRITE: TLSv1 Alert, length = 2
http-nio-8443-exec-2, fatal: engine already closed. Rethrowing javax.net.ssl.SSLHandshakeException: null cert chain
http-nio-8443-exec-2, called closeOutbound()
http-nio-8443-exec-2, closeOutboundInternal()
When I take the client's certificate and I load it into my browser and navigate to the site, I am prompted to choose the certificate and able to see the wsdl and such. So I believe the certificate is fine.
The Java client uses it's trustStore specified in the Java options just fine to validate the server which makes me believe the trustStore is loaded and used just fine. Finally, here's the client piece of code I think is responsible for creating the service:
System.setProperty("javax.net.ssl.keyStore","C:\\tomcat\\certs\\tomcat.keystore");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
System.setProperty("javax.net.ssl.keyStoreType", "JKS");
System.setProperty("javax.net.ssl.trustStore","C:\\tomcat\\certs\tomcat.truststore");
System.setProperty("javax.net.ssl.trustStorePassword", "password");
System.setProperty("javax.net.ssl.trustStoreType", "JKS");
URL url = DocumentRepositoryProxy.class.getClassLoader().getResource("XDS.b_DocumentRepositoryWSDLSynchMTOM.wsdl");
QName qname = new QName("urn:ihe:iti:xds-b:2007", "DocumentRepository_Service");
DocumentRepositoryService service = new DocumentRepositoryService(url, qname);
if (handlerResolver != null)
service.setHandlerResolver(handlerResolver);
proxy = service.getDocumentRepositoryPortSoap12(new MTOMFeature(true, 1));
BindingProvider bp = (BindingProvider) proxy;
SOAPBinding binding = (SOAPBinding) bp.getBinding();
binding.setMTOMEnabled(true);
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);
I've spent the majority of a week going down this rabbit hole and if anyone can help it'll save me some hairs.
Here's the answer. In my WEB-INF/cxf-servlet.xml file for my WebApp I needed to add this chunk of XML and the associated namespaces. The Java options in code were ignored completely so I removed them. Once I added this and restarted Tomcat everything worked on the first try.
Namespaces:
xmlns:sec="http://cxf.apache.org/configuration/security"
xmlns:http="http://cxf.apache.org/transports/http/configuration"
Elements:
<http:conduit name="*.http-conduit">
<http:tlsClientParameters>
<sec:keyManagers keyPassword="XXX">
<sec:keyStore type="JKS"
password="password"
file="C:/tomcat/certs/tomcat.keystore"/>
</sec:keyManagers>
<sec:trustManagers>
<sec:keyStore type="JKS"
password="password"
file="C:\tomcat\certs\tomcat.truststore"/>
</sec:trustManagers>
</http:tlsClientParameters>
</http:conduit>

Categories

Resources