I'm generating SSL certificates with Let's Encrypt. It works fine, I have the CSR, the key and the certificate chain including the intermediate certificate for those browsers which don't know Let's Encrypt Certificate Authority yet. When creating a new certificate in Plesk (12), I copy-and-paste the given data, click on apply, apply the created certificate to the domain and it works as expected. Testing with openssl says
$ openssl s_client -crlf -connect mydomain.com:443 -servername mydomain.com
<snip>
Certificate chain
0 s:/CN=www.mydomain.com
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
i:/O=Digital Signature Trust Co./CN=DST Root CA X3
2 s:/O=Digital Signature Trust Co./CN=DST Root CA X3
i:/O=Digital Signature Trust Co./CN=DST Root CA X3
</snip>
Now, three month later, I have to re-issue those certificates. As I want to automate it, I want to use a CLI solution, like Plesk offers:
$ plesk bin certificate \
-u mycertificatename \
-domain mydomain.com \
-cert-file mynewcert.crt \
-key-file mykey.key
The problem: The certificate gets updated and is shown as expected in Plesk, but the intermediate certificate doesn't show up when testing with openssl:
Certificate chain
0 s:/CN=www.mydomain.com
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
Any ideas? Did I forget to restart any service? Or any (un)documented feature?
Try to use option
-cacert-file <path> CA certificate file
with path to CA file which containts all intermediate certificates
Related
I am using the command ...
openssl s_client -showcerts -connect reds-cluster-01:443
And I get the output:
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, CN = RapidSSL TLS DV RSA Mixed SHA256 2020 CA-1
verify return:1
depth=0 CN = *.my-co-example.com
verify return:1
CONNECTED(00000003)
---
Certificate chain
0 s:/CN=*.my-co-example.com
i:/C=US/O=DigiCert Inc/CN=RapidSSL TLS DV RSA Mixed SHA256 2020 CA-1
-----BEGIN CERTIFICATE-----
MIIGnxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxgkqhkiG9w0BAQsFADBZ
...
I assume that means somewhere on the filesystem of my server there would be a file somewhere that has the string ...
MIIGnxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxgkqhkiG9w0BAQsFADBZ
... in it. How can I find that file without having to execute something like?
sudo grep -sr MIIGnxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxgkqhkiG9w0BAQsFADBZ /
I assume that means somewhere on the filesystem of my server there would be a file somewhere that has the string ...
This assumption is wrong. What you see is part of the server certificate, which need to be checked against a CA certificate located in the local trust store. The server certificate is typically not in the local trust store. See SSL Certificate framework 101: How does the browser actually verify the validity of a given server certificate? for more on certificates are checked.
You can see more with "CURL -W CERTS" from Daniel Stenberg (also on Stack Overflow), which works on curl for the past 25+ years.
When a client connects to a TLS server it gets sent one or more certificates during the handshake.
Those certificates are verified by the client, to make sure that the server is indeed the right one: the server the client expects it to be; no impostor and no man in the middle etc.
When such a server certificate is signed by a Certificate Authority (CA), that CA’s certificate is normally not sent by the server but the client is expected to have it already in its CA store.
(So no file to check on the filesystem)
Ever since the day SSL and TLS first showed up in the 1990s user have occasionally wanted to be able to save the certificates provided by the server in a TLS handshake.
The openssl tool has offered this ability since along time and is actually one of my higher ranked stackoverflow answers.
Now (for curl 7.88.0,to be shipped in February 2023), Daniel proposes:
Using the –write-out (-w) option and the new variables %{certs} and %{num_certs}, curl can now do what you want.
Get the certificates from a server in PEM format:
$ curl https://curl.se -w "%{certs}" -o /dev/null > cacert.pem
$ curl --cacert cacert.pem https://curl.se/
That is easier to parse than the openssl s_client -showcerts -connect current alternative.
This question already has answers here:
SSL working in chrome but sometimes in Firefox and not on IOS, Android or Blackberry
(2 answers)
Closed 1 year ago.
I've put together a Linux (Centos 7) server to serve eye-n-sky.net.
Serving content from that site to browsers on Win10 and Linux systems works beautifully. However, when I use openssl to access the site,
openssl s_client -connect eye-n-sky.net:443
the site certificate is rejected,
Verify return code: 21 (unable to verify the first certificate)
I've concluded that the way a browser verifies the certificate is different from what openssl does. Am I on the right track?
I've tested this on three different openssl instances (Debian, Centos, FreeBSD) and have consistent results.
Openssl as a client to other sites, e.g. www.godaddy.com, microsoft.com, work fine, being able to verify the certificate against the installed CA chain.
Believing that I was missing a CA cert, I used the -CAfile option to specify the possibly missing cert, to no effect.
What am I missing? I'm guessing that openssl has a stricter verification discipline, but I don't know where that gets configured.
Thanks,
Andy
Summary: yes, eye-n-sky was providing only it's cert when it needed to include the intermediate and root certs.
However, it took me forever to figure out that my Apache version did not support including the chain in the server cert file. Instead, I had to provide the chain file separately in an SSLCertificateChainFile directive.
OpenSSL's command-line s_client utility has nothing built in to validate the server's certificate. Browsers have a built-in list of trusted certificates to verify the server certificate against.
You have to supply the trusted certificates using options such as -CAfile file or -CApath directory. Per the OpenSSL 1.1.1 s_client man page:
-CApath directory
The directory to use for server certificate verification. This
directory must be in "hash format", see verify(1) for more
information. These are also used when building the client certificate
chain.
-CAfile file
A file containing trusted certificates to use during server
authentication and to use when attempting to build the client
certificate chain.
Note the use of words such as "certificate chain". If you go to godaddy.com you'll see that the server's cert is for *.godaddy.com, but it was signed by Go Daddy Secure Certificate Authority - G2, and that intermediate certificate was signed by Go Daddy Root Certificate Authority - G2 - a different certificate. There's a total of three certificates in that chain.
Verify return code 21 is "no signatures could be verified because the chain contains only one certificate and it is not self signed", so if your CA file only had the certificate from Go Daddy Root Certificate Authority - G2 and not the one from Go Daddy Secure Certificate Authority - G2, OpenSSL would see from the server's cert itself that it was signed by Go Daddy Secure Certificate Authority - G2 and could go no further - it doesn't have that cert to see who signed it.
I have created a SSl certificate using these commands:
openssl genrsa -out kc_ca-key 2048
openssl req -new -out san_domain.csr -key kc_ca-key -config openssl.cnf
openssl x509 -req -days 3650 -in san_domain.csr -signkey kc_ca-key -out kc_ca-cert -extensions v3_req -extfile openssl.cnf
openssl.cnf file contains the common name, country name, subject alternative name and all such information.
In browser, I am able to connect securely after importing this certificate but when i run curl command with same certificate, i get the following error:
NSS error -8156 (SEC_ERROR_CA_CERT_INVALID)
* Issuer certificate is invalid.
* Closing connection 0
curl: (60) Issuer certificate is invalid.
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
How to resolve this error
There is not enough information to determine what your problem is.
I am making the following assumptions:
You sent the certificate request (CSR) to a CA provider and got a certificate back.
You setup some sort of web server with that certificate
I am also assuming that you used a "Windows" web browser like IE or Chrome that uses the windows certificate store to test the certificate.
The CA that signed your certificate is a well known CA that has there root certificates in all the common CA Lists.
If the above is true and a web browser like Firefox (that uses it's internal CA list) fails it's because the web server is using a certificate without any intermediate certificates.
You need to go find the intermediate certificates for your CA signed certificate, combine them into a certificate chain and setup your web server with this certificate chain. The details of how to do this will depend on your web server.
Once the web server is setup with a correct certificate chain then your curl command (and firefox) should work fine.
The reason that windows works fine is because windows keeps a list of common intermediate certificates that it can verify a certificate chain with. A openssl based client doesn't, so the intermediate certificates have to come from the SSL socket server (e.g. web server) down to the client to be able to verify the certificate chain back to a trusted root certificate in the client CA list.
On my Github enterprise when I install the SSL certificate with the key its displaying an error message:
"Github ssl cert The certificate is not signed by a trusted
certificate authority (CA) or the certificate chain is missing
intermediate CA signing certificates."
I was given from our certification authority team 4 certificates.
SSL certificate : github.pem
A set of 3 CA certificates : root, subca and subca2
On my Github enterprise management console, it needs 2 entries
A x509 SSL certificate
Unencrypted key
I have tried github.pem key alone and with different combination by concatenating CA certificates, but its failing always with the same error.
Is there a pattern to concatenate the certificate?
Any clue how i can resolve this?
Thanks in advance.
Please abide the following steps to add 3 certificates to your .pem file:
Open your domain certificate pem file in Notepad ++.
Add intermediate (DigiCertCA2.pem) certificate under Domain certificate.
Add root certificate (TrustedRoot.pem) to your domain certificate.
Save the .pem file that have the following 3 certificates (domain , intermediate, root).
Upload the modified certificate.pem file and the private key.
click on Save Settings.
I had the same issue.
When trying to load the PEM and Key files to GitHub Enterprise I got the same message. The cert was created using the exact same methods as I have done before, but was failing.
Github ssl cert The certificate is not signed by a trusted certificate authority (CA) or the certificate chain is missing intermediate CA signing certificates.
Steps I took:
Created a cert for the server (webserver with Private Key)
Exported from my users personal store (PFX including all certs in the path and export all extended properties)
C:\OpenSSL-Win64\bin> openssl.exe pkcs12 -in git_key_included.pfx -nocerts -out priv-key.pem -nodes
C:\OpenSSL-Win64\bin> openssl.exe pkcs12 -in git_key_included.pfx -nokeys -out cert.pem
C:\OpenSSL-Win64\bin> openssl rsa -in priv-key.pem -out server.key
I eventually figured it out by opening the PEM using Notepad++. The openssl commands work fine on the old exported cert, but swap around the ordering of the certs on the new exported cert. The broken cert had:
Primary SSL certificate
Root certificate
Intermediate certificate
Instead of the correct ordering of:
Primary SSL certificate
Intermediate certificate
Root certificate
So I swapped them around and it worked.
I have a certificate (for example this one) saved in a local file. Using openssl from the command line, how can I display the entire chain from this certificate to a root CA? I tried:
openssl verify -verbose -purpose sslserver -CApath /etc/ssl/certs InCommonServerCA.txt
and got this confusing output that only seems to show the leaf certificate:
InCommonServerCA.txt: C = US, O = Internet2, OU = InCommon, CN = InCommon Server CA
error 26 at 0 depth lookup:unsupported certificate purpose
OK
Any ideas?
For local certificates you can see the subject and direct issuer using:
openssl x509 -noout -subject -issuer -in test.crt
subject= /C=US/ST=Utah/L=SLC/O=My Organization/CN=my.server.com
issuer= /C=BE/O=GlobalSign nv-sa/CN=GlobalSign Organization Validation CA - SHA256 - G2
But that doesn't indicate if the certificate includes any intermediate certificates or the full chain of trust. The verify command you listed will fail if your system cannot validate the chain (example: you are missing an intermediate certificate or the root is not trusted), showing an error message like:
error 20 at 0 depth lookup:unable to get local issuer certificate
If you want to verify each entry in the file, you can use this script to show the chain of trust for a local certificate:
~ % ssl_chain.sh google.crt
0: subject= /C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
issuer= /C=US/O=Google Inc/CN=Google Internet Authority G2
1: subject= /C=US/O=Google Inc/CN=Google Internet Authority G2
issuer= /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
2: subject= /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
issuer= /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
google.crt: OK
If you want to verify the chain and purpose, your openssl command is correct. The "OK" indicates the chain verifies. The error indicates there is an issue with that certificate being used for an sslserver purpose. It looks like your certificate is a CA cert, not a leaf cert.
What kind of chain info are you trying to display? You could look at the subject and issuer fields to show chaining. The verify command you used above proves that the one cert signed the other cert.