Why chain of trust is ok with different CA? - ssl-certificate

I have a .keystore file and Tomcat's configuration is: keystore=.keystore and truststore=.keystore
The .keystore contains a PrivateKeyEntry (signed by CA1) and a trustedCertEntry (CA1).
Everythink ok so far.
If the trustedCertEntry would not be present when importing server certificate, I would get: Failed to establish chain from reply
When I delete the trustedCertEntry (CA1), Tomcat can not start because of: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
Now my question: When I delete trustedCertEntry CA1 and import a trustedCertEntry CA2, Tomcat starts and the certificate chain (view in browser) is: The server certificate which is signed by CA1.
How can this be possible? I would have expected that Tomcat can not start since the trustedCertEntry (CA2) does not match with the PrivateKeyEntry since PrivateKeyEntry was issued from CA1 and not CA2. And since Tomcat can not start without a trustedCertEntry.

Private key is not issued by CA.
Your server certificate is a pair of public and private key. Based on this key pair certificate request was created and this certificate request was signed by CA1. Certificate is valid in your browser as long as CA1 is in trusted CA in certificate store of your browser.
Changing CA in keystore doesn't affect server certificate.
It looks like at least one CA cert is requirement of SSL engine - I'm guessing that any CA cert (i.e. thawte.com/roots, or self-signed) imported to JKS will work for you - JKS must have at least one.

Related

Truststore in TLS connection

According to TLS connection definition, for example, as the client-side, I use keystore to store my private key and certificate, and use truststore to store some kinds of certs. On the server-side, that call it Youtube, it has a root certificate called Youtube.pem which is signed by Google.crt CA.
I know the truststore is to verify the 3rd party certificate during handshake
My question is what should my truststore actually store during handshake?
Youtube.pem (the CA signed certificate sent from 3rd part)
Google.crt (the CA certificate)
According to TLS connection definition, for example, as the client-side, I use keystore to store my private key and certificate, and use truststore to store some kinds of certs.
Yes, but you only need a keystore if you want to use client side authentication. Note that "keystore" and "truststore" indicate how the store is used, they can be of the same type (e.g. PKCS#12) and even the same file.
On the server-side, that call it Youtube, it has a root certificate called Youtube.pem which is signed by Google.crt CA.
No, YouTube is a service, it has a leaf or end-entity certificate. The root certificate is that of a third party CA. The end-entity certificate is usually signed by an intermediate CA certificate, and that is in turn signed by a self signed root certificate.
I know the truststore is to verify the 3rd party certificate during handshake
It is used to validate and verify the trust path from leaf certificate to a trust anchor in your truststore. The trust anchor is usually one of the root certificates stored in your truststore. The leaf certificate is indicated by the end entity / server, the intermediate certificates are usually sent by the server as well, but they could also be retrieved from a cache.
In the case of YouTube, the Google root CA is used, possibly using the GlobalSign root through a linked certificate if the Google root is not present in the trust store.
So your truststore should either contain the Google root certificate or the GlobalSign root for the connection to work in this example.

OpenSSL: Create a self-signed CA with many intermediate certificate levels

I'd like to build my own self-signed CA structure to use in my applications. The idea is presented by the following picture:
So, to summarize it, I want a CA that has several levels of intermediate certificates.
For instance I want to create a Root CA that signs all of my apps and then create an intermediate cert for my first app APP_1. This app is used by several companies so I want that every company has it's own intermediate cert just for them which is signed by APP_1 (you can imagine this intermediate cert as a "child" of APP_1 cert). Company intermediate cert then signs end-user's certificate which he uses on his device.
Is it possible to create this cert hierarchy scheme with OpenSSL?
I've tried to create an example of this scheme and it went well until I tried to verify Company_1 intermediate cert. The verification with the chain was successful, but the verification with the intermediate cert that created this one failed. The command that fails is this one:
openssl verify -CAfile /CA/app_1/certs/app_1.cert.pem /CA/app_1/company_1/certs/company_1.cert.pem
The error is as it follows:
error 2 at 1 depth lookup: unable to get issuer certificate
error /CA/app_1/company_1/certs/company_1.cert.pem: verification failed
What am I doing wrong? Should I also verify the Company_1 intermediate with Root CA as I do with APP_1?
openssl verify by default wants to build the full chain. But you only provide the leaf certificate and the chain certificate and not the root certificate (which is signed by itself). To accept a chain certificate as the final trust anchor instead of a root certificate use the -partial_chain option:
$ openssl verify -partial_chain -CAfile app_1.cert.pem company_1.cert.pem

SSL client verification failure

I have a backend server with SSL only as defaut public interface. This server listens on 443 with cert, key and ca files on, ssl verify client is set to true.
On client side, I have client cert, key and a ca file made of 2 CA files catted together (intermediate CA, root CA) in a single ca.pem file. When I do curl request on my backend server, it works fine. I also tested the server / client cert and key with gnutls-serv and openssl s_server to ensure all was valid.
But when I create a keystore on Apigee (client cert and key file [pem format]) and a trustore (ca.pem file), there is an error:
- target.name fsbca-test
- Properties
- Expression ("fsbca-test" equals target.name)
- ExpressionResult true
- Tree TARGET_fsbca-test
- error The Service is temporarily unavailable
- error.cause General SSLEngine problem
- error.cause.cause General SSLEngine problem
- error.class com.apigee.messaging.adaptors.http.HttpAdaptorException
- state TARGET_REQ_FLOW
- type ErrorPoint
If I put SSL verify client to false on my backend, then the request is correctly diverted by Apigee and I get the response.
If I put IgnoreValidationErrors to true in the target endpoints property, then the request is diverted to my backend server but I can see an error in the server's log: "client sent no required SSL certificate while reading c...".
Any ideas about what could be wrong in what I am doing?
Additional track: could it be an issue on Apigee side with the CA file made of 2 certs (it may ignore trailing certificates found in a .pem). If wanted to test pkcs12 and jks but I failed to upload them to Apigee (the API doc page only describes .pem, JAR and cert action). I wrote a small Java client with pkcs12 keystore and jks trustore and it worked fine from my local workstation.
Thank you in advance for any piece of information that could help me.
Regards
Fr
You should upload your certificates separately (one per cert), and you need the entire trust chain of certificates to be stored in your truststore.
Here is the page about SSL to your backend.
EDIT:
Here is a method I know works:
1) Separate certs into separate PEM files. Do not put more than once cert in a file.
2) Validate each cert using openssl:
openssl x509 -noout -text -in <cert file name>
Validate that no certs are expired, and that the Subject and Issuer fields create a chain of all the certs, with identical names.
The server's certificate, the root certificate, and all certificates in between need to be in the truststore.

Nginx SSL certificate

I have two files from the certification service :
CSR.txt :
Looks like this :
-----BEGIN CERTIFICATE REQUEST-----
Code
-----END CERTIFICATE REQUEST-----
and Private Key with same format
I'm trying to set them up on Nginx but I'm always getting this error
failed (SSL: error:0906D06C:PEM routines:PEM_read_bio:no start line error:140DC009:SSL routines:SSL_CTX_use_certificate_chain_file:PEM lib)
I have renamed file1.txt to domain.crt
and file2.txt to domain_key.key
"the site's identity is not verified", this notification appears in Firefox. This means that the ownership of the domain was not verified by a CA or the organzation is not included on the certificate which provide all the information on the certificate. This happen when the type of certificate do only validate the ownership of the domain via email address or meta tag URL.
See: https://www.globalsign.com/ssl/domain-ssl/
It is hard to tell what you are doing, but it looks like you are confusing a Certificate Signing Request (CSR) with a real Certificate (CRT).
So, in order to configure your nginx server for SSL/TLS, follow these steps:
Generate a strong RSA key-pair (openssl genrsa ...)
Generate a Certificate Signing Request (CSR) (openssl req -new ...)
Send the request to a Certificate Authority (CA)
Get a signed certificate (CRT) back from your CA
You can then configure your server to use your "server.key" and your "server.crt" files for SSL/TLS encryption.
If you still get a similiar error, try to remove everything before ----- BEGIN CERTIFICATE ----- and after ----- END CERTIFICATE -----.

OpenSSL: unable to verify the first certificate for Experian URL

I am trying to verify an SSL connection to Experian in Ubuntu 10.10 with OpenSSL client.
openssl s_client -CApath /etc/ssl/certs/ -connect dm1.experian.com:443
The problem is that the connection closes with a Verify return code: 21 (unable to verify the first certificate).
I've checked the certificate list, and the Certificate used to sign Experian (VeriSign Class 3 Secure Server CA - G3) is included in the list.
/etc/ssl/certs/ca-certificates.crt
Yet I don't know why it is not able to verify the first certificate.
The entire response could be seen here:
https://gist.github.com/1248790
The first error message is telling you more about the problem:
verify error:num=20:unable to get local issuer certificate
The issuing certificate authority of the end entity server certificate is
VeriSign Class 3 Secure Server CA - G3
Look closely in your CA file - you will not find this certificate since it is an intermediary CA - what you found was a similar-named G3 Public Primary CA of VeriSign.
But why does the other connection succeed, but this one doesn't? The problem is a misconfiguration of the servers (see for yourself using the -debug option). The "good" server sends the entire certificate chain during the handshake, therefore providing you with the necessary intermediate certificates.
But the server that is failing sends you only the end entity certificate, and OpenSSL is not capable of downloading the missing intermediate certificate "on the fly" (which would be possible by interpreting the Authority Information Access extension). Therefore your attempt fails using s_client but it would succeed nevertheless if you browse to the same URL using e.g. FireFox (which does support the "certificate discovery" feature).
Your options to solve the problem are either fixing this on the server side by making the server send the entire chain, too, or by passing the missing intermediate certificate to OpenSSL as a client-side parameter.
Adding additional information to emboss's answer.
To put it simply, there is an incorrect cert in your certificate chain.
For example, your certificate authority will have most likely given you 3 files.
your_domain_name.crt
DigiCertCA.crt # (Or whatever the name of your certificate authority is)
TrustedRoot.crt
You most likely combined all of these files into one bundle.
-----BEGIN CERTIFICATE-----
(Your Primary SSL certificate: your_domain_name.crt)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Your Intermediate certificate: DigiCertCA.crt)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Your Root certificate: TrustedRoot.crt)
-----END CERTIFICATE-----
If you create the bundle, but use an old, or an incorrect version of your Intermediate Cert (DigiCertCA.crt in my example), you will get the exact symptoms you are describing.
SSL connections appear to work from browser
SSL connections fail from other clients
Curl fails with error: "curl: (60) SSL certificate : unable to get local issuer certificate"
openssl s_client -connect gives error "verify error:num=20:unable to get local issuer certificate"
Redownload all certs from your certificate authority and make a fresh bundle.
I came across the same issue installing my signed certificate on an Amazon Elastic Load Balancer instance.
All seemed find via a browser (Chrome) but accessing the site via my java client produced the exception javax.net.ssl.SSLPeerUnverifiedException
What I had not done was provide a "certificate chain" file when installing my certificate on my ELB instance (see https://serverfault.com/questions/419432/install-ssl-on-amazon-elastic-load-balancer-with-godaddy-wildcard-certificate)
We were only sent our signed public key from the signing authority so I had to create my own certificate chain file. Using my browser's certificate viewer panel I exported each certificate in the signing chain. (The order of the certificate chain in important, see https://forums.aws.amazon.com/message.jspa?messageID=222086)
Here is what you can do:-
Exim SSL certificates
By default, the /etc/exim.conf will use the cert/key files:
/etc/exim.cert
/etc/exim.key
so if you're wondering where to set your files, that's where.
They're controlled by the exim.conf's options:
tls_certificate = /etc/exim.cert
tls_privatekey = /etc/exim.key
Intermediate Certificates
If you have a CA Root certificate (ca bundle, chain, etc.) you'll add the contents of your CA into the exim.cert, after your actual certificate.
Probably a good idea to make sure you have a copy of everything elsewhere in case you make an error.
Dovecot and ProFtpd should also read it correctly, so dovecot no longer needs the ssl_ca option.
So for both cases, there is no need to make any changes to either the exim.conf or dovecot.conf(/etc/dovecot/conf/ssl.conf)
If you are using MacOS use:
sudo cp /usr/local/etc/openssl/cert.pem /etc/ssl/certs
after this Trust anchor not found error disappears
For those using zerossl.com certificates, drag and drop all certificates (as is) to their respective folders.
Cut and pasting text into existing files, may cause utf8 issues - depending upon OS, format and character spacings.