Mutual Authentication - null cert chain - java

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?

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.

How to setup basic Jersey/Grizzly 2.21 SSL startup configuration

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.

Java code signing certificate issue

I generate a certificate signing request like this:
keytool -genkey -alias server -keyalg RSA -keysize 2048 -keystore xxxx -dname "CN=www.example.com,OU=Infrastructure and Operations, O=ACME, Inc., L=Test, ST=Test, C=US" && keytool -certreq -alias server -file xxxx.csr -keystore xxxx.jks
When a code signing certificate is created, for some reason the CN is set to the organization value instead of the FQDN, that I listed originally www.example.com
So the cert has CN=ACME, Inc.,OU=Infrastructure and Operations, O=ACME, Inc., L=Test, ST=Test, C=US
Not sure why it didn't take the FQDN.
Oracle docs say:
If a distinguished name string value contains a comma, the comma must be escaped by a "\" character when you specify the string on a command line, as in
cn=peter schuster, o=Sun Microsystems\, Inc., o=sun, c=us
So the valid dname is:
"CN=www.example.com,OU=Infrastructure and Operations, O=ACME\, Inc., L=Test, ST=Test, C=US"

COMODO SSL certificate on Jboss7

I registered a domain and would like to set up SSL encryption for it. My domain provider offered me to get a SSL certificate from COMODO. I generated a key and a csr file using openSSL:
openssl req -nodes -newkey rsa:2048 -keyout myserver.key -out server.csr
The command produced a private key, myserver.key and the csr file. I uploaded the content of the csr to comodo, and after verification, they sent me the following files:
Root CA Certificate - AddTrustExternalCARoot.crt
Intermediate CA Certificate - COMODORSAAddTrustCA.crt
Intermediate CA Certificate - COMODORSADomainValidationSecureServerCA.crt
Your PositiveSSL Certificate - mydomain.crt
I'm lost on where to go from here. I followed these instructions:
https://support.comodo.com/index.php?/Default/Knowledgebase/Article/View/638/0/certificate-installation-java-based-web-servers-tomcat-using-keytool
and created a domain.keystore file, but I'm not sure if that's the right thing to do or not. My configuration in Jboss now looks like this:
<connector name="https" protocol="HTTP/1.1" scheme="https" socket-binding="https" secure="true">
<ssl name="mydomain" password="*****" protocol="TLSv1" certificate-key-file="../standalone/configuration/domain.keystore"/>
</connector>
But that doesn't seem to work. I get no error in the server log, the page simply times out. If i use http it works normally. Any advice?
EDIT:
I took a different approach, I generated my keystore in this way:
keytool -genkey -alias domain -keyalg RSA -keysize 2048 -keystore domain.keystore
then I uploaded the new csr info to comodo and got the three .crt certificates back. I imported them into the keystore with this command:
keytool -import -trustcacerts -alias domain -file domain.crt -keystore domain.keystore
and then I used the keystore in the standalone.xml in this way:
<connector name="https" protocol="HTTP/1.1" scheme="https" socket-binding="https" secure="true">
<ssl name="domain-ssl" key-alias="domain" password="******" certificate-key-file="../standalone/configuration/domain.keystore" protocol="TLSv1"/>
</connector>
The server starts, but when I try to connect to it, my browser says that the connection is untrusted:
domain uses an invalid security certificate.
The certificate is not trusted because it is self-signed.
(Error code: sec_error_ca_cert_invalid)
I finally managed to get the installation right! Here's how you do it:
Install the COMODO certificates into your keystore wit this command:
keytool -import -trustcacerts -alias <filename> -file <filename>.crt -keystore domain.keystore
in the following order:
» Root: AddTrustExternalCARoot.crt
» Intermediate 1: COMODOAddTrustServerCA.crt
» Intermediate 2: COMODOExtendedValidationSecureServerCA.crt
Then install your domain certificate:
keytool -import -trustcacerts -alias mykey -file yourDomainName.crt -keystore domain.keystore
You should use the same alias instead of mykey, that you used to generate your keystore. If you do everything correctly, you should get this output:
Certificate reply was installed in keystore
Anything else means, you probably didn't use the correct alias. The final thing you need to do is to modify your standalone.xml like this:
<connector name="https" protocol="HTTP/1.1" scheme="https" socket-binding="https" secure="true">
<ssl name="<domain>-ssl" key-alias="<domain>" password="******" certificate-key-file="../standalone/configuration/<domain>.keystore"/>
</connector>
And you should be good to go!
My domain provider offered me to get a SSL certificate from COMODO...
...
Any advice?
Don't pay for the certificate. You can get a free Class 1 certificate from Startcom. The Class 1 is good for server authentication without a wildcard domain. If you want an extended validation certificate or a wilcard certificate, then you will have to buy a Class 2 or higher.
Also, while Startcom issues the certificate for free, they charge for revocation because that's where the cost lies.
I'm lost on where to go from here...
Convert Intermediate CA Certificate - COMODORSAAddTrustCA.crt, Intermediate CA Certificate - COMODORSADomainValidationSecureServerCA.crt and Your PositiveSSL Certificate - mydomain.crt to PEM files. PEM are the ones that start with ----- BEGIN CERTIFICATE ----- and finish with ----- END CERTIFICATE -----.
Then, concatenate your three PEM files into a single file. The file will have three certificates in it. Call it mydomain-chain.pem, and load that into your server. Also load myserver.key into your server.
Don't do anything with Root CA Certificate - AddTrustExternalCARoot.crt. Clients have to use it as a root. There's no {use|need} to send it to the client in the ServerHello.
You can test your setup with the following. Notice how the client uses the root:
openssl s_client -connect myserver:443 -CAfile AddTrustExternalCARoot.crt
The command should end with Verify (0) OK or similar.
Failed to load keystore type JKS with path ../standalone/configuration/mydomain-chain.pem due to Invalid keystore format: which mean your keystore is not valid. Dont create new one use the keystore file you were created while submitting csr file to them. Use same keystore if you change the keystore its not accept.

Adding certificate chain to p12(pfx) certificate

I have aplication in java and cxf which connects to WebServices with client certificate.
I got certificates form WebService owner
certificate.p12
certificate.pem
certificate.crt
trusted_ca.cer
root_ca.cer
I have problem with straightforward converting this p12 certficate to working jks keystore requred by java.
I did this:
keytool -importkeystore -srckeystore certificate.p12 -srcstoretype PKCS12 -destkeystore certificate1.jks -deststoretype JKS -storepass secret
keytool -import -alias root -file root_ca.cer -trustcacerts -keystore certificate1.jks -storepass secret
keytool -import -alias trusted -file trusted_ca.cer -trustcacerts -keystore certificate1.jks -storepass secret
but this jks doesn`t work and I get HTTP response '403: Forbidden' when using this certificate1.jks
However if I import this p12(pfx) certificate to Internet Explorer and then export this certificate from IE to pfx format selecting "Include all certificates in the certification path" checkbox and use:
keytool -importkeystore -srckeystore certificate.pfx -srcstoretype PKCS12 -destkeystore certificate2.jks -deststoretype JKS -storepass secret
keytool -import -alias root -file root_ca_kir.cer -trustcacerts -keystore certificate2.jks -storepass secret
keytool -import -alias trusted -file trusted_ca_kir.cer -trustcacerts -keystore certificate2.jks -storepass secret
Then everything works fine and I can connect to WebService using certificate2.jks.
I found that original certificate.p12(pfx) contains only one entry (Certificate chain length: 1):
keytool -list -keystore certificate.p12 -storepass secret -storetype PKCS12 -v
*******************************************
*******************************************
Alias name: alias
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=MyCompany, EMAILADDRESS=my.email#domain.com, O=bla, C=PL
Issuer: CN=Trusted CA, O=ble, C=PL
Serial number: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Valid from: ... until: ...
Certificate fingerprints:
MD5: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
SHA1: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
Signature algorithm name: SHA1withRSA
Version: 3
Extensions:
#1: ObjectId: X.X.XX.XX Criticality=false
KeyUsage [
DigitalSignature
Key_Encipherment
]
...
*******************************************
*******************************************
while certificate.pfx exported from IE with "Include all certificates in the certification path" contains certificate chain with second Trusted CA certificate (Certificate chain length: 2):
keytool -list -keystore certificate.p12 -storepass secret -storetype PKCS12 -v
*******************************************
*******************************************
Alias name: alias
Entry type: PrivateKeyEntry
Certificate chain length: 2
Certificate[1]:
Owner: CN=MyCompany, EMAILADDRESS=my.email#domain.com, O=bla, C=PL
Issuer: CN=Trusted CA, O=ble, C=PL
Serial number: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Valid from: ... until: ...
Certificate fingerprints:
MD5: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
SHA1: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
Signature algorithm name: SHA1withRSA
Version: 3
Extensions:
#1: ObjectId: X.X.XX.XX Criticality=false
KeyUsage [
DigitalSignature
Key_Encipherment
]
...
Certificate[2]:
Owner: CN=Trusted CA, O=ble ble ble, C=PL
Issuer: CN=ROOT CA, O=ble ble ble, C=PL
Serial number: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Valid from: ... until: ...
Certificate fingerprints:
MD5: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
SHA1: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
Signature algorithm name: SHA1withRSA
Version: 3
Extensions:
*******************************************
*******************************************
So to solve my problem I need to have p12 certificate with chain to trusted CA certificate.
I can do this by importing p12 to IE and then exporting back with "Include all certificates in the certification path".
How can I do this without IE using keytool or other tool?
Bary
Own answer.
I figured out how to do this with OpenSSL:
openssl pkcs12 -in certificate.p12 -out clientcert.pem -nodes -clcerts
openssl x509 -in trusted_ca.cer -inform DER -out trusted_ca.pem
openssl x509 -in root_ca.cer -inform DER -out root_ca.pem
cat clientcert.pem trusted_ca.pem root_ca.pem >> clientcertchain.pem
openssl pkcs12 -export -in clientcertchain.pem -out clientcertchain.pfx
If you are working in Windows OS, you can install the certificate as usual through the IIS, then open mmc.exe -> File -> Add / Remove Snap In -> Double click on "Certificates" Select "Computer Account", next, finish, OK.
Expand certificates, if needed add the certificates from the CA into "Intermediate Certification Authorities" or "Trusted Root Certification Authorities".
Then go to "Web Hosting", here must be your webSite certificates, select the certificate, left click on it, select Export and follow the wizard, the important things to check are "Include Private Key", Include all certificates on the chain, export all extended properties, you must set a password, select the output flie name and this is it. Now you have a certificate with the complete chain on it. No more problems with Facebook or similar.

Categories

Resources