Search code examples
javasslkeystoretruststore

How to handle alias in TrustStore


I am running the Java process (Microservice) and trustStore configured in the JVM parameter. If the Microservice needs to connect the external URL which required the cert to be imported in trustStore.

Example: 
example.co.uk -> examplecouk as alias in trustStore
example.com -> examplecom as alias in trustStore
example.in  -> examplein as alias in trustStore

How does Java know that which certs and alias to be picked from the trustStore for the particular endpoint as I don't pass/mention the alias in the JVM params? Is it pick randomly?


Solution

  • user207421 is nearly correct. To be more exact:

    When you as client open an SSL/TLS connection to a server, as part of the handshake the server sends its certificate 'chain' containing its own cert, plus usually one or more linked CA (Certificate Authority) certificates ending with a 'root' CA that should be trusted. See the neighboring Stack https://security.stackexchange.com/questions/20803/how-does-ssl-work/ for an epically complete explanation. Public servers normally use a cert issued and signed by a public CA like Digicert, GoDaddy, LetsEncrypt/ISRG which are already in the standard default truststore (for Java in the file JRE/lib/security/cacerts) so no action is needed. If a server uses a cert from a off-brand or private CA, or a self-signed cert (from no CA at all), then (for Java) some cert in the chain must be added to the client truststore, or otherwise overridden; this is only required to be the server cert in the case where the server cert is self-signed (which is a chain by itself and has no relevant CA certs).

    Java/JSSE implements this through an SSLContext which contains among other things a TrustManager, more specifically an X509ExtendedTrustManager, which is initialized from a truststore. You can create an SSLContext explicitly in code from any set of trusted certs (which doesn't even need to be from a file), or use the default context which uses the default truststore file, which defaults to the filename above unless overridden by a system property.

    When the server cert chain is received it is passed to the context's TrustManager for validation; among (many!) other checks, at each level of a normal chain, or the single level of a self-signed cert, the JSSE TrustManager looks for an anchor cert (edit) which either is the desired cert (same Subject and (Subject)PublicKey) or is the signer of that cert (Subject equals Issuer), and if such an anchor is found it is used validate the cert chain. Note that a normal (CA-issued) leaf cert can have Subject empty if Subject Alternative Name is used instead -- see rfc5280 and rfc2818 -- but a self-signed cert cannot, because it has Subject = Issuer and Issuer must not be empty. Certs for different entities (e.g. different servers) normally are expected to have different keys, although a single entity can have multiple certs with either the same key or different keys, and might correspond to multiple server names and/or addresses.

    (added) This anchor lookup does not use the alias, and neither does anything else in the validation process, which is why the alias is not and does not need to be specified, and the aliases that are needed for (some) other purposes in a KeyStore file or object have no significance for this purpose.

    If the certificate is determined valid in general, for some TLS applications (notably HTTPS) the validator also checks it is for the correct server, specifically that the CommonName attribute in the Subject field, or an entry in the Subject Alternative Name extension if present (which for public CAs it always is and has been for at least a decade it is) matches the host DNS name or IP adddress in the URL. In older versions of Java (through 6 IIRC) this was not done in JSSE but rather in the calling application(s) or library, such as HttpsURLConnection, which as a legacy still has the option to use its own HostnameVerifier instead.

    All of this can be altered by using a custom TrustManager in place of the standard one, and some things like Apache HttpClient do so validly, but you will find (too many) answers here and some other Stacks recommending you 'solve' TLS errors by using a neutered TrustManager that just accepts any cert, regardless of whether it is actually valid and correct, and thus happily connects and sends sensitive data to, or accepts changes from, any attacker who manages to intercept the IP traffic, which is often pretty easy nowadays.