-----Original Message----- From: Don Flinn [mailto:fl...@alum.mit.edu] Sent: Tuesday, November 14, 2017 1:58 AM To: Tomcat Users List <users@tomcat.apache.org> Subject: Trying to understand How Tomcat uses Keystore for SSL
I've done some reading on SSL and understand the protocol is as follows; Client/Browser sends ClientHello and server Tomcat replies with ServerHello. This establishes the protocol they will use. The server then sends the certificate and the public key - in the clear The browser encrypts a message containing the servers domain, all encrypted with the server's public key to the CA which the browser trusts. The public key is in the certificate. The CA de-crypts the message with the server's private key. So the server's name/ domain must be not encrypted. If the server can decrypt the message it knows the server and it then sends a ack message back to the browser encrypted with the client's private key. The browser and Tomcat then establish a secret key to send messages back and forth. If I have the above correct, I must have keystore set up incorrectly, since running my scenario I get an error in the Chrome debugger,which says This page is not secure "Valid certificate The connection to this site is using a valid, trusted server certificate issued by unknown name. Secure resources All resources on this page are served securely. " Note the 'the certificate is valid and it is issued by unknown name" Why is the issuer unknown, since the issuer's name is in the certificate? letsencrypt has an online web site from which one can download a ca_bundle, a private key and a certificate for your domain Oracle has an article on keytool which says that keytool can not create a pkcs12 keystore but can read it and to use openssl, which I did following their instructions. Concatenate the CA cert, the private key and the user cert then put these in keystore. The result is shown below. Tomcat isn't able to use this keystore to communicate with the browser for some reason. Why? What's missing or incorrect? C:\Users\don\Security\letsenc>%keytool% -list -keystore MMcert.p12 -v -storetype pkcs12 Enter keystore password: Keystore type: PKCS12 Keystore provider: SunJSSE Your keystore contains 1 entry Alias name: tomcat Creation date: Nov 13, 2017 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=info.finwoks.com Issuer: CN=Let's Encrypt Authority X3, O=Let's Encrypt, C=US Serial number: 415913da3a6a956ef3efef2fb2eb4baff17 Valid from: Sat Nov 11 16:05:35 EST 2017 until: Fri Feb 09 16:05:35 EST 2018 Certificate fingerprints: MD5: F5:FD:4F:8B:9A:A0:38:D1:B7:78:B6:36:38:AB:42:31 SHA1: 7C:AB:5C:D3:A9:95:01:FD:43:CC:F5:D5:1D:24:64:1A:BF:4C:AE:66 SHA256: A9:85:5C:34:3D:DA:65:64:2F:C7:45:57:52:3F:EE:0F:D6:70:50:DE:AA:5C:2A:D1:16:F3:29:B9:CB:F3:B2:36 Signature algorithm name: SHA256withRSA Version: 3 Extensions: #1: ObjectId: 1.3.6.1.5.5.7.1.1 Criticality=false AuthorityInfoAccess [ [ accessMethod: ocsp accessLocation: URIName: https://urldefense.proofpoint.com/v2/url?u=http-3A__ocsp.int-2Dx3.letsencrypt.org&d=DwIBaQ&c=V9FsLrJ7wYRfgsJ_KHoq2BENyO08hg3hD97KYyc_QQg&r=ZZk8MXVrcZaLkCc_2C7UFhVW7Nb2LjIIa0VSNP2uvtnzxufjwl_gt-oLYrhgql55&m=VrRTCJmgYLiGtBvYlsLN4_I8HpSXqpyk0AYjVWIJ7pE&s=2xE3g2KMxIhXp_7T0HijZR_rr3gpfiXRkBTeH-vynH8&e= , accessMethod: caIssuers accessLocation: URIName: https://urldefense.proofpoint.com/v2/url?u=http-3A__cert.int-2Dx3.letsencrypt.org_&d=DwIBaQ&c=V9FsLrJ7wYRfgsJ_KHoq2BENyO08hg3hD97KYyc_QQg&r=ZZk8MXVrcZaLkCc_2C7UFhVW7Nb2LjIIa0VSNP2uvtnzxufjwl_gt-oLYrhgql55&m=VrRTCJmgYLiGtBvYlsLN4_I8HpSXqpyk0AYjVWIJ7pE&s=c0wds6Rh-8cC1_Sw8mGuboZbkpcvhCV7Lxtk8_7Z6Ew&e= ] ] #2: ObjectId: 2.5.29.35 Criticality=false AuthorityKeyIdentifier [ KeyIdentifier [ 0000: A8 4A 6A 63 04 7D DD BA E6 D1 39 B7 A6 45 65 EF .Jjc......9..Ee. 0010: F3 A8 EC A1 .... ] ] #3: ObjectId: 2.5.29.19 Criticality=true BasicConstraints:[ CA:false PathLen: undefined ] #4: ObjectId: 2.5.29.32 Criticality=false CertificatePolicies [ [CertificatePolicyId: [2.23.140.1.2.1] [] ] [CertificatePolicyId: [1.3.6.1.4.1.44947.1.1.1] [PolicyQualifierInfo: [ qualifierID: 1.3.6.1.5.5.7.2.1 qualifier: 0000: 16 1A 68 74 74 70 3A 2F 2F 63 70 73 2E 6C 65 74 .. https://urldefense.proofpoint.com/v2/url?u=http-3A__cps.let&d=DwIBaQ&c=V9FsLrJ7wYRfgsJ_KHoq2BENyO08hg3hD97KYyc_QQg&r=ZZk8MXVrcZaLkCc_2C7UFhVW7Nb2LjIIa0VSNP2uvtnzxufjwl_gt-oLYrhgql55&m=VrRTCJmgYLiGtBvYlsLN4_I8HpSXqpyk0AYjVWIJ7pE&s=C8Q4955sg0RlR5YC372IHyvk57_FdgyQfMJRHTVOJUc&e= 0010: 73 65 6E 63 72 79 70 74 2E 6F 72 67 sencrypt.org ], PolicyQualifierInfo: [ qualifierID: 1.3.6.1.5.5.7.2.2 qualifier: 0000: 30 81 9E 0C 81 9B 54 68 69 73 20 43 65 72 74 69 0.....This Certi 0010: 66 69 63 61 74 65 20 6D 61 79 20 6F 6E 6C 79 20 ficate may only 0020: 62 65 20 72 65 6C 69 65 64 20 75 70 6F 6E 20 62 be relied upon b 0030: 79 20 52 65 6C 79 69 6E 67 20 50 61 72 74 69 65 y Relying Partie 0040: 73 20 61 6E 64 20 6F 6E 6C 79 20 69 6E 20 61 63 s and only in ac 0050: 63 6F 72 64 61 6E 63 65 20 77 69 74 68 20 74 68 cordance with th 0060: 65 20 43 65 72 74 69 66 69 63 61 74 65 20 50 6F e Certificate Po 0070: 6C 69 63 79 20 66 6F 75 6E 64 20 61 74 20 68 74 licy found at ht 0080: 74 70 73 3A 2F 2F 6C 65 74 73 65 6E 63 72 79 70 tps://letsencryp 0090: 74 2E 6F 72 67 2F 72 65 70 6F 73 69 74 6F 72 79 t.org/repository 00A0: 2F / ]] ] ] #5: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [ serverAuth clientAuth ] #6: ObjectId: 2.5.29.15 Criticality=true KeyUsage [ DigitalSignature Key_Encipherment ] #7: ObjectId: 2.5.29.17 Criticality=false SubjectAlternativeName [ DNSName: info.finwoks.com ] #8: ObjectId: 2.5.29.14 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: 04 6B 27 5C F4 5E 85 21 24 38 A7 44 2D 7E 69 CA .k'\.^.!$8.D-.i. 0010: CF 31 04 1C .1.. ] ] ******************************************* ******************************************* ---------------------------------------------------------------------------------------------------------------------------- Hi Don, I think I can help you move forward, but just so you know, I am not an official Tomcat developer. Just a mailing list member who once got help here and now giving back :) I think your understanding of how the SSL Handshake is incorrect. In particular, the way you depicted the CA's role in an SSL handshake is incorrect. The CA is never involved in SSL Handshakes. SSL connections are between you and the server, always. There is no third party, and we certainly do not want one! There are plenty of resources to explain SSL Handshake ( I like the page published on IBM's Knowledge Center: https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.1.0/com.ibm.mq.doc/sy10660_.htm) but I'll summarize it here for you. Browser sends ClientHello with a list of cipher suites it can support. Server responds with a cipher suite selection and a digital certificate (which also contains a public key). So far so good. Now, how does the Browser validates that it is communicating with the right/genuine server it was trying to contact? What proof do we have that it is not a usurper? Browser takes the certificate and does this: 1) Is this certificate cryptographically signed by someone I trust? Your computer already contains a list of CA public keys that can be used to validate that a given certificate signature is valid. Keep in mind a certificate may be signed by more than one CA, which is why we often talk of a certificate chain. There only needs to be one signature in that chain that your computer recognizes for this server certificate to be deemed valid. Is that enough to validate that the certificate is valid though? Like a passport, the fact that is genuine and delivered by your government is important, but for the customs office to accept it, it must be YOURS! So that's why there's step two: 2) Is this certificate delivered for the domain name I was trying to access? (is this passport in your name?) If those two critera are met, then the certificate verification is going to succeed and the ssl handshake will move on to the next step which is to start the encrypted session. Here comes problem #2: asymmetrical encryption (such as public key encryption) is a ONE WAY communication channel. While anyone with a public key can encrypt data, ONLY the owner of the private key will be able to decrypt. And a private key is... well... secret!! Only the server has it. So there's no way the client could decrypt whatever the server would say. THAT's why the browser will generate a symmetrical session encryption key. A key that will be used by both the client and server to encrypt data in both directions. And in order to protect that key from being intercepted, we must not send it in the clear. We will use the server's one-way public key to encrypt that symmetrical encryption key and send it to the server. Only with the session key installed on both sides, does the encrypted session begin. This concludes the summary which I hope will help you understand the handshake part. Now I understand your ultimate goal is to get rid of warnings and get that little green lock on your browser. Assuming you have obtained a valid signed certificate from LetsEncrypt, here's what you have to do. Step 1: Start using KeyStore Explorer. It's so much easier to use a GUI than the command line :P http://keystore-explorer.org/ Step 2: You mentioned that LetsEncrypt gave you a keystore with a private key in it. I'm going to assume they gave you a package which contains a private key and a certificate, and that the point was to simplify the process of generating a CSR (Certificate Signing Request). Just know that the fact that the private key was given to you by a third party is a potential security risk to your own security. The NORMAL process is to generate your own private key, generate a CSR, send LetsEncrypt the CSR, obtain a Signed CSR and re-import into your keystore. That has maximum security. Step 3: Make a copy of your original keystore file. Then you can open your keystore with Keystore Explorer and change its format to JKS. Super easy. I think its under the tool menu. You can rename your keystore file so that it ends in *.jks (make sure you saved the keystore using the save button!) Step 4: Copy that jks file to your server under the conf folder of tomcat. Step 4: In your Tomcat server.xml file you need something like this: <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true"> <SSLHostConfig protocols="TLSv1.2"> <Certificate certificateKeystoreFile="localhost.keystore.jks" certificateKeystorePassword="Passssssword!" certificateKeyAlias="alias" /> </SSLHostConfig> </Connector> The alias is just a name used to designate a given certificate in case there are more than one in your keystore. Just a good habit to be specific. You can find what is the alias name for your certificate using Keystore Explorer VoilĂ ! That should give you a valid SSL configuration on your server. If you still get an issue with Chrome warnings, this means the certificate contained in the keystore is not signed properly. You can easily check if a certificate is signed using the Keystore Explorer and right-clicking then view details... see certificate chain. In that chain, you should be able to see some top CA authority signing your cert. If none of those CAs in the chain are approved by chrome, it wont work. You'll need to find another provider. Regards, - Nicolas