I have a java/angular application installed in a tomcat windows corp server.
The application is accessed remotely using http just fine.
Now I need to install ssl to it.
I already have the certificate from the certification authority and generated the mycert.jks file.
Then placed that file in the tomcat \conf folder and configured tomcat server.xml connector like this:
<Connector port="xxx" maxHttpHeaderSize="8192" maxThreads="100"
minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
SSLEnabled="true" clientAuth="false"
sslProtocol="TLS" keyAlias="myalias"
keystoreFile="conf\mycert.jks"
keystorePass="mypass" />
Now when I access the application remotely (https://10.10.100.10/myapp), the application loads fine in the browser, but I'm getting a Not secure - Certificate is not valid
message.
When I click the Certificate is not valid
message it opens the certificate details.
The information there is correct (Issued To - Common Name, Validity Period...).
So it means the server can correctly find my certificate.
The validity period has not expired. So it is ok also.
The date/time on the server is also correct.
What else can it be?
UPDATE
Adding data seen when "Certificate is not valid" message is clicked on the browser:
Issued To
Common Name (CN) mycn
Organization (O) myorg
Organizational Unit (OU) <Not Part Of Certificate>
Issued By
Common Name (CN) mycn
Organization (O) myorg
Organizational Unit (OU) <Not Part Of Certificate>
Validity Period
Issued On Tuesday, September 26, 2023 at 9:38:18AM
Expires On Monday, December 25, 2023 at 9:38:18AM
Fingerprints
SHA-256 Fingerprint XX XX XX XX XX XX...
SHA-1 Fingerprint XX XX XX XX XX XX...
UPDATE 2:
I tried it this other way, but still getting the same error message.
Generated the .jks using this command:
keytool -genkey -alias myservername -keyalg RSA -keysize 2048 -keystore myservername.jks -dname "CN=myservername, O=MyOrg, L=, ST=, C=" && keytool -certreq -alias myservername -file myservername.csr -keystore myservername.jks
It generated a myservername.csr file and a myservername.jks file.
Then, I ran this command
keytool -list -keystore myservername.jks
and got this result:
myservername, Oct 20, 2023, PrivateKeyEntry,
Certificate fingerprint (SHA-256): xxxxxxxx
Then I sent the myservername.csr file to the certificate authority and they sent me back this:
-----BEGIN CERTIFICATE-----
xxxxxxx
-----END CERTIFICATE-----
I pasted that into a myservername.cer file.
I double click the myservername.cer and went to certificate path tab and I see this: rootcertname > intermediatecertname > myservername
myservername is the alias I choose in the first command above.
Then I clicked rootcertname > view certificate > details > copy to file > next > Base 64 encoded x.509 (cer)
It generated rootcertname.cer
Then I clicked intermediatecertname > view certificate > details > copy to file > next > Base 64 encoded x.509 (cer)
It generated intermediatecertname.cer
Then I imported both certificates to the keystore like this:
keytool -keystore myservername.jks -import -alias root -trustcacerts -file rootcertname.cer
keytool -keystore myservername.jks -import -alias intermediate -trustcacerts -file intermediatecertname.cer
Then I ran this command again to list the certificates in the keystore:
keytool -list -keystore myservername.jks
and got this result:
intermediate, Oct 23, 2023, trustedCertEntry,
Certificate fingerprint (SHA-256): xxxx
root, Oct 23, 2023, trustedCertEntry,
Certificate fingerprint (SHA-256): xxx
myservername, Oct 20, 2023, PrivateKeyEntry,
Certificate fingerprint (SHA-256): xxxx
So it has the privatekey (generated in the first command above) plus the root and intermediate certificates from the Certification Authority.
Copied myservername.jks to Tomcat \conf folder.
Tomcat server.xml connector is configured as previously informed.
But when I access the application on the browser using https I still get the same error message:
Not secure - Certificate is not valid
IMPORTANT: Noticed that when I click View Certificate in the Issuer name it says "myservername" (which is the private key alias). Instead, it should display the Certification Authority certificate name.
Meta: this is no longer ontopic, though years ago it was, and I've seen many similar Qs, but can't easily find a good dupe.
So close and yet ... not.
The canonical pure-Java sequence to get a cert-and-key for an SSL/TLS server, including an HTTPS server like Tomcat, is:
1A. generate keypair with keytool -genkey[pair]
; this also generates a dummy self-signed certificate for the generated keypair and the 'dname' (subject name and also issuer name) you enter, plus some other parameters you could have specified but didn't (see below)
1B. create CSR with keytool -certreq
You did these correctly.
2. submit CSR to CA along with other information as needed (usually but not necessarily proof of domain 'ownership') and get back at least a server aka end-entity cert; usually the CA also supplies any needed root and intermediate aka 'chain' cert(s).
Your CA apparently didn't give you the chain, but when you opened it in cryptext.dll (which is the default action for doubleclick .cer on Windows) both the intermediate and root were found in your Windows store. It is common for an enterprise with an in-house CA and domain-joined or otherwise centrally-managed Windows workstations -- especially if the in-house CA is the one provided by Windows AD -- to 'push' their CA root to all machines; it is less common but possible to push the intermediate(s), or that(those) might be cached from previous accesses by this machine to (intranet) server(s) using in-house cert(s).
Thus you dealt with this correctly.
3A. keytool -import[cert]
the root and intermediate(s) (if any), from the top down, to the same keystore under different (unique) alias(es)
3B. keytool -import[cert]
the server cert to the same keystore and same alias as used in 1A and 1B. This replaces the dummy self-signed cert created in 1A by the CA-issued one and also builds its certification path using the cert(s) imported in 3A.
You did 3A but not 3B; as a result the dummy self-signed cert created in 1A remains in place and is used, and since it indeed is not valid it is correctly rejected by the browser. You need to do 3B (and bounce your Tomcat if it is already running).
A variant method is that some CAs provide the end-entity cert PLUS the chain cert(s) in a package using either a PKCS7 format usually labelled p7b or p7c, or a simpler PEM-sequence format. Yours didn't, but given you have the chain certs in your Windows store the 'cert export wizard' can create the PKCS7 format; just select the P7B button and tick the 'include all certs' box. In this case 3A and 3B can be replaced by a single step:
3'. import the p7b/c package or PEM-sequence of (all) certs to the same keystore and alias as 1A and 1B. This both replaces the dummy self-signed cert and builds the certification path from the input, thereby ending up with essentially the same result.
Finally, note that SSL/TLS certificates are usually issued as valid for a domain-style name or set of such names, not an IPaddress. Public CAs require the name be a real domain name i.e. registered in public DNS, but inhouse CAs like the one you used can accept other names if they want, like NetBIOS names. A cert can allow both name(s) and IPaddress(es); look at the Subject Alternative Name field in the cryptext.dll viewer or keytool -printcert
or keytool -list -v
on the keystore.
If your CA gave you an IPaddress-capable cert https://<ipaddr>
will work, but if it gave you a name-only cert you must use https://<name>
and not https://<ipaddr>
.