i think i have an error on my understanding on the SSL handshake, but do i?
My application cant verify itself on the api. After some digging with wireshark i noticed that theres no "certificate verify" step and my private key certificate is not signed with one of the trusted authorities so my first thought was that.
The catch is: If i add the same certificate to my browser(firefox) and call the API i get a popup for the certificate selection and it actually works.
Isnt it supposed to only accept certificates that are listed under the Distinguished Names? Or is this only required for the public key and the private not necessarily?
What does firefox actually do in background when the popup comes, create a custom certificate chain?
Setup is as followed:
API is under https:somerandomurl
API-Server integrated a certificate of ours for auth (for all i know)
(this cert is actually a cert for https:someotherurl)
Client has truststore with cert for somerandomurl
Client has keystore with PKCS#12 cert
My guess is that my application has wrong/no certificate chain because as far as i know the PKCS#12 cert contains a pub and a private key BUT the pub is not for "somerandomurl" but "someotherurl". But thats just a guess, maybe its just the trusted auths
Related
We have a K8S service leveraging NGINX and in some flows would like to accept client certificate authentication.
Service has a dynamic list of public trusted client certificates (PEM format), and the root CAs aren't known.
In NGINX, it seems like the best setting to use would be:
nginx.ingress.kubernetes.io/auth-tls-verify-client: optional_no_ca
While sending the full certificate ($ssl_client_escaped_cert) to the upstream service to compare the entire public cert.
The question is whether NGINX will still perform the client cert validations during SSL handshake (and only skips CA checks), to verify the request is indeed sent by the one and only owner of the cert and its private key.
It will still check in the TLS handshake that the public key in the certificate can be used to verify the signature in CertificateVerify, i.e. that the client actually owns the private key to the sent certificate.
It will not check that the certificate itself is issued by a trusted CA etc - such verification are expected to be done elsewhere.
I have done some research about how do browsers work with CA-signed certificates. The browser comes with a list of trusted CA's public keys. When a CA-signed certificate was received by a browser, the browser decrypts the certificate using the trusted CA's public key to get the server's public key.
I am confused about how does the browser work with self-signed certificates. A self-signed certificate is signed by the server's private key. When a browser receives a self-signed certificate, how does the browser decrypt the cert to get the public key without knowing the public key?
When a CA-signed certificate was received by a browser, the browser decrypts the certificate using the trusted CA's public key to get the server's public key.
The browser does not decrypt the certificate to get the public key. The browser just uses the public key of the CA to verify the issuers signature of the certificate. See SSL Certificate framework 101: How does the browser actually verify the validity of a given server certificate?.
When a browser receives a self-signed certificate, how does the browser decrypt the cert to get the public key without knowing the public key?
Again, there is no decryption. But apart from that there is no way for the browser to check if the self-signed certificate is valid. A self-signed certificate basically is somebody claiming to be themselves. Contrary to a CA signed certificate there is no trusted third party which says this but just the (untrusted) owner of the certificate itself.
Thus the only way such a certificate can be trusted in the browser is either because it was explicitly added as trusted or if the user of the browser explicitly added an exception after they got a warning about the certificate.
What is the proper way of using SSL certificates for private applications? By private I mean that I am the only user, and software is running on my computers.
I want to have a encrypted communication between two of my programs. I want to send passwords between them, so I need to be sure that remote program is not fake/hacked.
As far as I understand I don't need to get paid SSL certificate from the CA, if there is no third party involved.
Is the following correct?
Server has a private key and self-signed SSL certificate.
Client has a copy of server's self-signed certificate (it needs to be well protected).
During the handshake server sends the certificate to client.
client checks if the certificates are the same.
client can start encrypted transmission.
Is there other way?
Server has a private key and self-signed SSL certificate.
Yes
Client has a copy of server's self-signed certificate (it needs to be well protected).
The client has either a copy of the certificate or the certificates public key or the fingerprint of these. Since the certificate is public these information do not need to be protected. Only the private key of the server (residing only in the server side) needs to be protected because using this key one could prove ownership of the certificate.
During the handshake server sends the certificate to client.
Yes.
client checks if the certificates are the same.
Kind of. It might check the certificate or the public key or the fingerprints.
client can start encrypted transmission.
Yes.
I would recommend that you read the OWASP article about certificate and public key pinning. It also contains sample code for various environments.
Client has a copy of server's self-signed certificate (it needs to be well protected).
Clients do not have copy of the server certificate. They get it in SSL handshake
client checks if the certificates are the same.
NO! Clients will have the public certificate of the Certificate Authorities who would have signed the server certificate. They will validate the server cert with the CA cert including things like certificate expiry, CRLs. Not compare for 'sameness'
In your case you are using the self-signed certificates. The clients should be made to ignore the self signed certificate and proceed with SSL handshake.
I would recommend you read through SSL handshake sequence again.
Doesn't everyone in the world have a copy of Gmail's SSL certificate? If so why does our browser trust gmail.com just because it sent me this certificate? Can't any old person send me this same certificate just by going to gmail.com and downloading it?
No. The server sends its certificate and a digital signature signed by its private key during the SSL handshake. Only the true certificate owner can do that.
This is all described in RFC 2246.
Read up on...
http://en.wikipedia.org/wiki/Public-key_infrastructure
Basically google sends down its public key to your browser through SSL. How can the browser trust it's really google? The public key in turn is signed by a CA (certificate authority). The browser is pre-configured with well known CAs.
It's not possible (or to be more precise hard enough to be impractical) to forge google's cert. That's because you don't have google's private key. Unless you used this same key, your forged cert would fail validation with the CA.
I'm consuming a web service from an Android device using HTTP(s) with SSL. A self-signed (untrusted) certificate is used for client authentication.
I have a general understanding of how public/private keys are used for SSL. From my understanding I can clearly see how a certificate can be used to set up a secure connection and transmit data securely. However I do not understand how they are used for client authentication since the certificate contains the public key and is not kept a secret.
I have a few questions:
Where can I read about how SSL and certificates can be used for client authentication?
Even if the certificate was not made public...by visiting the HTTPS URL in a browser I can view and save the certificate. I can then package up the certificate in a key store and use it from an application.
In this post Jeremy Huiskamp writes
client auth will automatically be performed when the server requests
it
...so client authentication as well as encryption of data can be performed with certificates?
Edited to answer the first part of my question: The client keystore should contain not only the server's public key but also the client's private key. The server must then be able to decrypt using the client's public key? Does this mean the keystore should have two certificates?
First, a quick point about the terminology in public key cryptography:
you sign and decrypt/decipher using a private key,
you verify (a signature) and encrypt/encipher using a public key.
(You don't really "decrypt" using a public key.)
Using SSL/TLS with or without client-authentication, the server presents a certificate (*) for which it has the private key. The server sends its certificate during the SSL/TLS handshake (at the beginning of the connection) and is able to decipher what the client sends using its private key (which it keeps private). The private key and certificates are stored in the server's keystore (or equivalent if it's not implemented in Java).
As part of this, the client uses its truststore, which is a form a keystore that contains trusted certificates, to verify the server certificate. The server certificate could be trusted by being explicitly in the truststore or, in most cases, trusted by linking in to a trusted CA certificate in the truststore (PKI).
The terminology between keystore and truststore in Java can be a bit confusing, you can find more details in this answer.
Regarding your question, the client's truststore doesn't contain the server's public key, but either its certificate or a CA certificate with which it should be verifiable. (It's not just about having the public key, but knowing whose it is, using the other pieces of information in the certificate.)
When you use client-certificate authentication in addition to this, there is a truststore (or equivalent) on the server side and a keystore on the client side too, since the roles are reversed for this purpose.
In the SSL/TLS handshake that uses client-authentication, the server requests a certificate from the client, who sends it (if available).
At the end of this handshake, the client sends a CertificateVerify message, which signs all the messages exchanged so far between the client and the server (so it's something known to both) using the client certificate private key. The server is then able to verify this signature against the public key within the client certificate it has obtained as part of this exchange. This proves to the server that whoever is on the client side has the private key corresponding to the public key in the certificate it has sent.
The next step for the server is to verify whether to trust this certificate, i.e. whether to trust the binding between identity and public key as presented and "sealed" within the certificate.
This is usually done using a PKI, whereby you check the certificate against a known CA, or if your deployment environment is sufficiently small, against a fixed set of trusted certificates. (There can be alternative methods of verification, but their usability will really depend on the circumstances where you want to deploy this system.)
Therefore, for your second question:
The client keystore should contain at least the client's certificate and its private key.
The client truststore should contain the server certificate or a CA certificate with which the server certificate can be verified.
Since both keystore and truststore are a keystore (in the storage format sense, usually a file) used for a different purpose, it's often possible to use the same keystore to serve both the purpose of keystore and truststore.
(*) There are cipher suites that don't rely on certificates, but that's unusual and off topic for this question.
A certificate just binds an identity to a public key. This binding is not secret, so there is no need to keep the certificate secret. If I have John Smith's certificate, I can prove that John Smith owns the secret key corresponding to a particular public key. But since I don't know that secret key, the certificate is of no use to me.
When authentication occurs by certificate, one step is always to have whoever presents the certificate prove they know the secret key corresponding to the public key in the certificate. If you cannot pass that step, the authentication fails.
The server's keystore should have the server's certificate. The client's keystore should have the client's certificate. The client will present its certificate to the server, so the server will learn the client's public key that way. (And vice-versa.)