简体   繁体   中英

How does java http client validate Server's CA Certificate?

I am trying to understand SSL and reading different articles. All articles have pictures like this( picture source ):

在此处输入图像描述

There are a lot of examples, but I want to understand step 3 If I use a browser, it's understandable. The browser has itself mechanism for validation. But what if I use my java client? For example, I have an application that makes requests to - https://www.google.com/search?q=weather . How can I validate Google's Certificate? Should I do that? Should I get this Certificate and add it to the trust store? Maybe I should add only not-public certificates to the trust store?

Can anyone explain a chain of steps that java HTTP client makes for validation? (You can use any java HTTP client for explanation)

In step 2 the server provides his server certificate. This is issued and signed by an official Certification Authority (CA, Root CA) like Baltimore Cypertrust, Entrust, DigiCert, Verisign, etc. or a Intermediate Certification Authority (ICA) whereby the certificate of an ICA is issued and signed by a root CA.

Before a CA/ICS issues a certificate it verifies that the requestor (aka subject) of a certificate is that person or company is who he pretends to be and is owner of the domain name the certificate should be issued for.

This builds a so called trust chain, from the server certificate backwards to a trusted authority.

In step 3 is verified that the certificate of step 2 lead to a known CA/ICA. If so the certificate is accepted as trusted. For this Java provides a store with all valid root and intermediate certificates of the certification authorities.

To list it's content, open a command shell, cange to the folder .../jre1.x.y_zzz/lib/security/ and type ../../bin/keytool.exe -keystore cacerts -list . The question for a password can be skipped by pressing enter key. Now you get a list of all certificates which are stored in the default store.

dude@cs04n4 /cygdrive/c/Program Files/Java/jre1.8.0_301/lib/security
$ ../../bin/keytool.exe -keystore cacerts -list
Keystore-Kennwort eingeben:

*****************  WARNING WARNING WARNING  *****************
* Die Integrität der Informationen, die in Ihrem Keystore gespeichert sind, *
* wurde NICHT geprüft. Um die Integrität zu prüfen, *
* müssen Sie Ihr Keystore-Kennwort angeben.                  *
*****************  WARNING WARNING WARNING  *****************

Keystore-Typ: JKS
Keystore-Provider: SUN

Keystore enth▒lt 92 Eintr▒ge

sslrooteccca [jdk], 31.07.2020, trustedCertEntry,
Zertifikat-Fingerprint (SHA-256): 34:17:BB:06:CC:60:07:DA:1B:96:1C:92:0B:8A:B4:CE:3F:AD:82:0E:4A:A3:0B:9A:CB:C4:A7:4E:BD:CE:BC:65
digicertassuredidg3 [jdk], 25.08.2016, trustedCertEntry,
Zertifikat-Fingerprint (SHA-256): 7E:37:CB:8B:4C:47:09:0C:AB:36:55:1B:A6:F4:5D:B8:40:68:0F:BA:16:6A:95:2D:B1:00:71:7F:43:05:3F:C2
verisignuniversalrootca [jdk], 25.08.2016, trustedCertEntry,
Zertifikat-Fingerprint (SHA-256): 23:99:56:11:27:A5:71:25:DE:8C:EF:EA:61:0D:DF:2F:A0:78:B5:C8:06:7F:4E:82:82:90:BF:B8:60:E8:4B:3C
digicerttrustedrootg4 [jdk], 25.08.2016, trustedCertEntry,
Zertifikat-Fingerprint (SHA-256): 55:2F:7B:DC:F1:A7:AF:9E:6C:E6:72:01:7F:4F:12:AB:F7:72:40:C7:8E:76:1A:C2:03:D1:D9:D2:0A:C8:99:88
...
ttelesecglobalrootclass2ca [jdk], 25.08.2016, trustedCertEntry,
Zertifikat-Fingerprint (SHA-256): 91:E2:F5:78:8D:58:10:EB:A7:BA:58:73:7D:E1:54:8A:8E:CA:CD:01:45:98:BC:0B:14:3E:04:1B:17:05:25:52
addtrustqualifiedca [jdk], 25.08.2016, trustedCertEntry,
Zertifikat-Fingerprint (SHA-256): 80:95:21:08:05:DB:4B:BC:35:5E:44:28:D8:FD:6E:C2:CD:E3:AB:5F:B9:7A:99:42:98:8E:B8:F4:DC:D0:60:16
digicertglobalrootca [jdk], 25.08.2016, trustedCertEntry,
Zertifikat-Fingerprint (SHA-256): 43:48:A0:E9:44:4C:78:CB:26:5E:05:8D:5E:89:44:B4:D8:4F:96:62:BD:26:DB:25:7F:89:34:A4:43:C7:01:61

dude@cs04n4 /cygdrive/c/Program Files/Java/jre1.8.0_301/lib/security

When seting up a SSL connection you can either choose to use this default trust store or to use your own. If you decide to use your own trust store you must create it and import the server / root certificates you trust.

The whole Public Key Infrastructure (PKI) is needed to tell whether the guy who sent you data is actually that guy and not some man-in-the-middle. For this there should be some 3d-party (whom you trust) who checks whether the owner of the website and creates and signs a certificate for him. You can check that the certificate is valid because it's signed by CA and you trust that CA.

How do you set up whom to trust? You need to store a list somewhere. In case of Java the storage of trusted authorities and their public keys is in the file $JAVA_HOME/lib/security/cacerts . This file originally came from Java installation and it contains major CA's with certificates (yes, they will get expired at some point). This file can be modified (CA certificates can be added or removed) with a keytool utility which comes with Java.

Now it's a bit more complicated because CA have levels of certificates: there's a Root cert which is used to sign Intermediate certs, which then are used to sign site owner's certificate. When your Java code needs to communicate using TLS/SSL it needs to:

  1. Download site's certificate
  2. Check that it's signed by a trusted CA

But while site's cert is signed by Intermediate cert, we don't always store it in cacerts . Usually only the Root certificate is stored. In such case there are 2 choices - either add Intermediate cert to cacerts (bad solution) or the website's owner needs to set up a certificate chain which will include both his cert, the cert that signed him, the cert that signed that one and so on until it reacher the Root. In this set up as long as you can check any certificate in this chain - you will trust that website.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM