Verify a PEM certificate against an issued server - ssl

I have been given a certificate file by another team in my organization to connect to a machine they manage.
The file is of the type :
# file EBIP_CACert.crt
EBIP_CACert.crt: PEM certificate
# openssl verify EBIP_CACert.crt
EBIP_CACert.crt: C = SE, ST = Istanbul, L = Istanbul, O = Debon, OU = IT, TK = DebonCA
error 18 at 0 depth lookup:self signed certificate
OK
The way I am trying to verify my SSL connection is by issuing the below command :
# openssl s_client -connect esesslghq27.se:9000 -cert EBIP_CACert.crt
unable to load client certificate private key file
140537395898272:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:703:Expecting: ANY PRIVATE KEY
Looking at the ERROR ANY PRIVATE KEY , Ive tried the solution but was unable to get it to work.
What should I do to make this work and verify the certificate against the node ?

Not sure what you are trying to accomplish, exactly.
If this is a CA cert (as the filename would imply), you'll need to TRUST them, i.e. -CAfile <file>. The -cert option is for a client certificate, for which you'll need the private key.
https://wiki.openssl.org/index.php/Manual:S_client(1)

Related

Understanding openssl. Where is the cert file?

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.

twisted check client SSL trustRoot value

I'm working on a twisted server where there should be a two way SSL handshake. I'm very new to working with these tools so I'm not sure how to set this option. This is my reactor:
def main(reactor):
with open('/opt/ssl/cert.pem') as f:
certdata = f.read()
with open('/opt/ssl/issuer.pem') as f:
issuer_certdata = f.read()
log.info("SSL Certificate Loaded.")
certificate = ssl.PrivateCertificate.loadPEM(certdata)
issuer_certificate = ssl.PrivateCertificate.loadPEM(issuer_certdata)
options = ssl.CertificateOptions(privateKey=certificate.privateKey.original,
certificate=certificate.original,
raiseMinimumTo=ssl.TLSVersion.TLSv1_2,
trustRoot=ssl.trustRootFromCertificates([issuer_certificate]))
factory = protocol.Factory.forProtocol(MPG)
reactor.listenSSL(6060, factory, options)
return defer.Deferred()
From reading https://twistedmatrix.com/documents/16.2.0/api/twisted.internet.ssl.CertificateOptions.html, I found I need to be using the trustRoot argument, and pass it an object that holds the CA. Now, in my case, the server and the clients all have the same CA, so I pass that certificate, such that the CA from that certificate is trusted.
Yet, this doesn't work somehow, and our wireshark tests fail with an error message saying with unknown CA during client certificate valdiation. I don't know if that is because I configured the twisted server wrong, or because the CA info simply doesn't match.
Edit: Since Jean-Paul's original comment, I've tried using the intermediary, the CA and both of them combined as the trustRoot argument, using trustRootFromCertificates. All of them result in an unknown CA error.
PS. I'm on a Centos7, and I've updated /etc/pki/ca-trust/source/anchors/ to include the CA certificate. and ran update-ca-trust
PS2. Testing my server with the command below, I found that it can't validate my own chain when I delete trustRoot from my code above. openssl s_client -connect x.x.x.x:6060 -tls1_2 -state -cert cert.pem -key cert.pem
That is, without the trustRoot argument, this is the certificate chain from openssl:
---
Certificate chain
0 s:C = TR, O = MYCERT
i:C = TR, CN = MYCERT's issuer
---
While, with the trustRoot argument I'm getting:
---
Certificate chain
0 s:C = TR, O = MYCE
i:C = TR, CN = MYCERT's issuer
1 s:C = TR, CN = MYCERT's issuer
i:C = TR, L = ROOT CA
---
I don't know why trustRoot causes this change. I'm probably misunderstanding the whole thing, and am very lost. Any help would be appreciated.

Signing private cert, which key?

I am trying to enable client certificate verification from some php scripts. My server -debian / lighttpd- has a SSL certificate since a while, it works.
It is configured this way :
$SERVER["socket"] == ":443" {
ssl.engine = "enable"
ssl.cipher-list = "EECDH+AESGCM:EDH+AESGCM:AES128+EECDH:AES128+EDH"
ssl.pemfile = "/etc/lighttpd/certs/mydomain.net.pem"
ssl.ca-file =
"/etc/lighttpd/certs/my.domain.ca-bundle"
ssl.dh-file = "/etc/lighttpd/certs/dhparam.pem"
ssl.ec-curve = "secp384r1"
ssl.verifyclient.activate = "enable"
ssl.verifyclient.enforce = "disable"
ssl.verifyclient.username = "SSL_CLIENT_S_DN_CN"
ssl.verifyclient.depth = 1
ssl.verifyclient.exportcert = "enable"
}
I tried to follow the pretty good tutorail here
https://gist.github.com/mtigas/952344
Where the difference is that I did not create a ca.key and ca.crt since I already have them configured with my lighttpd (they are signed by Comodo).
Now, my first doubt is what should I use to sign my client.crt?
This is what I did :
openssl genrsa -des3 -out client1.key 2048
openssl req -new -key client1.key -out client1.csr
Now at this point I need to sign it with the CA, i'd say it is the one identified as ssl.ca-file in the lighttpd.conf, right?
so my.domain.ca-bundle I guess.
Issue is, how do I get a key for it?
I tried to use (-CAkey) the private key I used with the csr used to request the certifcate, but I get X509_check_private_key: key values mismatch
Which one should I use?
Checked a few tutorials and examples, but all of them assume you create your ouw CA
first of all you cannot create your own (CA), a (CA) is a certificate Authority that provides you a ssl certificate. In order to do that you must submit a request, the request basically is a (CSR certificate signing request).After validating your request you'll be able to download your SSL certificate. Next you have to import your ssl certificate on your server where you generated the (CSR). While importing the ssl make sure you choose to import the private key also, at the end of this step you have a .pfx file, to get the private key all you have to do is to convert the .pfx file into a pem file where you can find a .key file that contains the private key.
this article could be helpful: https://www.namecheap.com/support/knowledgebase/article.aspx/9834/69/how-can-i-find-the-private-key-for-my-ssl-certificate
PS: Note that you should import you ssl certificate on the same server you generated the (CSR) otherwise your ssl certificate will be not attached to any private key, you can use this tool 'DigiCert Utility' to import the ssl certificate, generate the (CSR), test your key...

Openssl verify with chained CA and chained Cert

I have a certificate chain as:
root CA -> intermediate CA -> org CA -> client Cert
When I verify the client cert with CA as root CA -> intermediate CA -> org CA, it works:
$ cat org_1_ca/ca_crt.pem intermediate_ca/ca_crt.pem root_ca/ca_crt.pem > /tmp/test123.pem
$ openssl verify -CAfile /tmp/test123.pem client/client_crt.pem
client_crt.pem: OK
But when I chained my client cert with org CA (org CA -> client Cert), and have the rest of the chain as CA (root CA -> intermediate CA), it doesn't:
$ cat intermediate_ca/ca_crt.pem root_ca/ca_crt.pem > /tmp/test12.pem
$ openssl verify -CAfile /tmp/test12.pem client/org1_client_crt.pem
client/org1_client_crt.pem: C = US, ST = CA, L = LA, O = PP, OU = TEST, CN = user
error 20 at 0 depth lookup:unable to get local issuer certificate
Is this something that fundamentally wrong or openssl verify doesn't like that? I tried the same thing with nginx and and openssl connect and there was no luck there. Any help is appreciated.
The openssl commandline verify operation reads only one certificate, the first one, from the file given as operand, or from each file if more than one is given. This differs from the files specified with the -CAfile -trusted -untrusted options which can (and typically do) contain multiple certs.
Your file client/org1_client_crt.pem presumably contains the client cert and the 'org CA' cert, in that order. Only the client cert is used, the 'org CA' cert is ignored, and as a result you do not have a valid chain to verify.
If you want to use commandline to mimic/test the validation that a receiver (for a client cert, the server) would do, supply the leaf cert as the operand and all other transmitted (chain) certs with -untrusted, and the anchor(s) plus any 'known' intermediates in the truststore either explicit or defaulted.
There is no openssl connect operation; I assume you mean openssl s_client with options including -connect since that's one place it would make sense to use a client cert chain. The -cert option to s_client similarly uses only the first cert in the file. There is no option on commandline to specify the client chain except in the most recent version, 1.1.0, and even there it isn't documented so you have to read the help message carefully or the code, although the API/library has long supported this for code you write yourself.
Through 1.0.2 if you want to send a client cert with full chain to the server (as you should per the RFCs), assuming the server requests client authentication which is not usual and not the default for nginx (among others), you have to use a trick: supply all the certs needed for the client chain in the truststore, in addition to the anchor(s) needed to verify the server, either using -CAfile and/or -CApath explicitly, or using (modifying if needed) the default truststore unless your openssl is an older non-RedHat version where the default truststore didn't work in s_client s_server s_time only.
And the same is true about the server cert/chain in s_server except that it is used almost always instead of very rarely.

Unable To Trust Self-Signed SSL Certificate

I have an application running on Centos7 that needs to connect to a remote host over HTTPS. However, it is unable to verify the certificate and fails. Also, if I try to download a file from the server using wget, I get the below error:
[root#foo:~]# wget https://10.65.127.9/index.html
--2017-05-22 09:03:01-- https://10.65.127.9/index.html
Connecting to 10.65.127.9:443... connected.
ERROR: cannot verify 10.65.127.9's certificate, issued by ‘/CN=us6877vnxe7827’:
Unable to locally verify the issuer's authority.
To connect to 10.65.127.9 insecurely, use `--no-check-certificate'.
So I get the certificate from the host:
openssl s_client -connect 10.65.127.9:443 <<<'' | openssl x509 -out /etc/pki/ca-trust/source/anchors/mycert.pem
And execute the following to process it:
update-ca-trust extract
This however results in the same issue.. If I run:
openssl s_client -connect 10.65.127.9:443 -showcerts -debug
I do get some errors and various messages:
depth=0 CN = us6877vnxe7827
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = us6877vnxe7827
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/CN=us6877vnxe7827
i:/CN=us6877vnxe7827
Server certificate
subject=/CN=us6877vnxe7827
issuer=/CN=us6877vnxe7827
---
No client certificate CA names sent
---
Verify return code: 21 (unable to verify the first certificate)
Any ideas what I may be missing? If any further info helps, please let me know.
For wget you need to provide the certificate authority (CA) certificate(s) that signed the https server certificate. If you have those CA certificates - add them under --ca-certificate=file or --ca-directory=directory options
If you don't have them and you want to skip https server certificate verification (unsecure and can be dangerous) then use --no-check-certificate option.
I had the same problem with Jenkins trying to connect to our GitLab server.
The server does have a valid official certificate in our case, but Java didn't except it.
You are right about downloading the certificate.
However, the application you are mentioning is probably running inside a Java Virtual Machine (as a lot of applications are).
So from the point that you downloaded the certificate to a PEM file, you may have to add it to the VM's trusted certificates instead.
This article describes how to do that. Hope it helps.