I have a python application running behind an SSL nginx server.
In the nginx config I use "optional_no_ca" because I want to accept self signed certs.
My question is: can I blindly assume that the connection initiator is also the owner of the private part of the public key that I get in the certificate.
I.e. can I use the public key as the user id?
Yes, if the client authenticates with a certificate on SSL/TLS level, this confirms that the client has a corresponding private key.
Yet I would question the approach of using public keys as user IDs. Disclosure of the private key in this situation would need to replace the keypair and thus the user account should be discarded as well (if it's identified by the public key).
Another aspect is that the public keys and client-side certificates are not handy for users to manage.
Related
I have client-side generated a digital signature(JavaScript). The signature is then verified on Java back end. To verify the signature I am passing to the backend - (signature value, public key and message for verification). So far so good, but then the question arises - What if someone performs a man in the middle attack? He can easily generate a signature and send his - (signature value, public key and message.). So in a sense, this makes my current implementation not secure enough.
How can I avoid this? As far as I researched I have to verify that the public key sent is coming from the appropriate client and this is done through CA (Certificate Authority). However, in my case, I am doing this as a final project in university and I am not sure how to approach this problem.
Should I generate the public key certificate on the client side and send them along with the public key? Is it possible to generate self-signed-certificates on client-side and then verify it on the back-end?
What if someone performs a man in the middle attack
A MITM could replace the signature and the public key
How can I avoid this?
Mainly use SSL/TLS and/or...
As far as I researched I have to verify that the public key sent is coming from the appropriate client and this is done through CA (Certificate Authority)
If you use a Certificate Authority, each certificate is signed with the private key of the root CA certificate (or a subCA), so a MITM can not create a valid certificate because he does not own the root private key.
At server side, you can validate that the signature has been performed with a private key that corresponds to a certificate issued by the CA. Note that in this case you are working with certificates, not just with public keys ( a certificate envelopes a public key).
I am doing this as a final project in university and I am not sure how to approach this problem.
You have explained your solution but not the background. I mean why do you decided you need a digital signature? without that information I can not advise you.
Should I generate the public key certificate on the client side and send them along with the public key?
Read my previous comment
Is it possible to generate self-signed-certificates on client-side and then verify it on the back-end?
Yes, of course. You can generate a key pair at client side and associate the public key with the user's account during the registration process (using a secure channel)
This way you do not even need a password. The digital signature with the private key is the authentication proof. Using a CA is optional. The CA could issue a certificate containing the public key, but fot this scenario is not required
Could someone explain to me the following:
Who creates the public key during CSR? Is it CA's responsibility to offer it or it depends on the certificate requester? If the latter is true, in which way the browser client may include in its truststore this public key as to verify the SSL certificate sent from server? If the former is true, how many public keys a CA owns and in which way are all these keys known to the browser client? This is a point I cannot find or give a satisfactory answer since I cannot imagine the client holds a database of an enormous number of public keys...
Thank you very much
Public and private key can only be generated as a pair. Since the CA should not know the private key, the requester has to generate that pair himself.
While the browser has to store the public key of every trustworthy CA, it does not have to include the public key of every https-enabled website like prettykittens.org in its truststore.
So how does the client judge the authenticity of the site?
During the SSL-handshake, the webserver sends its public key and a message signed using CA's public key that roughly says "This is Company XY's public key for prettykittens.org" (aka a certificate). Then the browser only has to verfiy the signature using the CA's public key and is good to go.
I'm stuck trying to get a WCF client to communicate to an IIS Hosted WCF Service with TransportWithMessageCredential.
In this scenario we will have about 20 clients all running the client app. It is planned they will all use the same certificate to communicate with our server to provide encryption (identification is handled separately). Our server root web site is already configured with a certificate. The WCF service will be running from a sub-site and I wish to use this same certificate to secure access from our client app to the service.
If I install a PFX certificate on the client everything is fine. But I do not want to export the Private Key from our server - wouldn't this be a security issue?
If I install a CER certificate file, run my client app, I get the error - “The private key is not present in the X.509 certificate” - sounds reasonable as I did not export one
Maybe I'm missing something; I have googled this a lot and most solutions state to export the private key.
Is there any way to use a CER certificate file without exporting the private key from our server? Or what is considered best practice.
Thanks for any advice.
I need an answer to exactly the same question...
It seems ludicrous that after going to all this trouble to encrypt things with 128 bit keys, wading through an indecipherable mess of acronyms and using prime numbers as large as my credit card balance etc etc... after all that trouble you'd go and export your private key to each and every client machine, only protected by a (possibly insecure) password on the certificate file. Crazy stuff. Pointless.
One thing to remember is that both server and client need to decrypt messages and decryption requires the private key apparently.
So they only way I can see to avoid shipping your server's private key to all and sundry is to have 2 unrelated certificates, one for the server and one for the client.
When a message is sent from client to server, the client encrypts using the server's public key only. The server then decrypts using its private key.
When a message is sent (or a reply more like) from server to client, the server encrypts using the client's public key and the client decrypts using its own private key. Voila?
At least that way the server's private key is never released outside the server. The client private key is still shipped everywhere however.
I think it then boils down to 4 scenarios that are handled with varying degrees of satisfaction -
1) Msg sent from client to server - msg encrypted using server's public key. Server cert must be available on client. Server private key does not have to be present. Would be relatively easy for a rouge client to encrypt and send a message to the server as the server's public key is readily accessible.
2) Msg received on server - msg is decrypted using server's private key. This private key only resides on the server so is pretty secure (physical security?). The server certificate containing the private key shouldn't be accessible to others unless you put a copy in a public FTP folder, or enable remote access, or something daft. And even if someone gets the server certificate, they still need to guess your brilliant password right? As an aside, I have no idea of password protected cert files can be "cracked".
3) Reply sent from server to client - msg is encrypted using client's public key. So server needs client cert (private key not needed). The client public key is again easily available everywhere, so it would be pretty easy to intercept original msg from client to server, ignore its content (as you can't decrypt it without the server's private key), and send some kind of encrypted response back to the client just to see how the client interprets it. Fun.
4) Reply from server received by the client - msg decrypted using the client's private key. This private key is on ALL client machines, in the certificate file, ONLY protected by a password... so it's relatively insecure.
Of course the other option, if you're not too worried about security, is to ship the server certificate everywhere (including server private key) and use it as both the server AND client certificate. I'm sure a lot of people do that.
This answer contains a fair bit of speculation & dot joining, as I can't find a clear explanation out there. I'd be interested to know if I've got close.
=================================================================================
Update: getting there - http://msdn.microsoft.com/en-us/library/ms733102.aspx
Isn't it possible to simply capture the key while it's being negotiated between machines?
Let's say I connect to my bank's website. Browser will send request to bank server. Bank server will send me copy of its SSL certificate. If it's valid, browser will send signed ack. Isn't it possible to simply capture private key at that time?
Your private key (and bank's too) is never sent over the network. The bank's public key is a part of the X509 certificate that it sends to your browser. If banks signs anything it does it using its private key, and your browser verifies the signature using the bank's public key (from the certificate). The whole SSL session is encrypted using symmetric cipher (for performance reasons). To be able to do that both parties need to exchange the session key (different for each connection and renegotiated after defined interval of time). This exchange is done using Diffie-Hellman algorithm. During this exchange the key is not sent over the network, it is computed independently by both parties.
Isn't it possible to simply capture the key while it's being
negotiated between machines?
No because it is never sent, it is computed independently. You would need the server's private key, which is private, to repeat the independent computations that lead to the session key. So it is secure.
Only public key is shared. The bank dosen't need to share the private one.
Private key is not shared and is not stored in the cert.
it seams that, if using HTTPS protocol, packages transferred between browser and web server are all encrypted. And all the browser has to support its communication session with web server is so called certificates.
So I think it's clear that we can use the same certificates to decrypt packages that captured by Wireshark during the login of HTTPS sites.
I googled, and find some tutorials said the private key should be supplied, which i do think impossible and unpractical.
BTW. the following shell command get certificate from host , are there tools to yield the public key?
echo QUIT | openssl s_client -connect <site>:443 | sed -ne '/BEGIN CERT/,/END CERT/p'
Thanks in advance.
No, you cannot decrypt HTTPS/SSL sessions from a network capture, even if you do have the certificates. That is the whole point of Public Key Cryptography on which SSL is based.
What you have in your browser key-store is the certificates that will verify the validity of the public keys of the server. Said public keys are accessible, but they cannot be used to decrypt the session packets because the encryption algorithm is not symmetric.
You would need the private keys of the server in order to descrypt an SSL session and in normal situations it is quite hard to acquire those.
See also the Wikipedia article on TLS for more information.
EDIT:
I will add some more information in layman terms, mostly ripped off from the two links above, to make things a bit more clear.
Public Key Cryptography is based on asymmetric encryption algorithms. Those involve two keys, rather than one, a public key and a private key. Those two keys consist a key pair. Assuming a sufficiently strong algorithm, whatever is encrypted with the public key can only be encrypted with the private one and vice versa. The public key is widely accessible to "everyone" while the private key is stored securely and only used by its owner. How does this help?
The server has a key pair that consists of a world-readable public key and a securely stored (and inaccessible to anyone but the server itself) private key.
The client uses the server's public key to encrypt a rather long random key for a symmetric algorithm at the start of each encrypted session. That key is sent to the server.
Since the symmetric key is encrypted like this, it can only be decrypted using the server's private key. That means that it cannot be extracted from a captured network stream, and since it is used for the rest of the session, neither can any of the information that is transmitted later on.
The server uses its private key to retrieve the session symmetric key and all is well.
Is it? There is still one issue in the above scheme! How will the client get the server's public key? More specifically how does it know that it speaks with the server proper, and not some crook who managed to insert themselves in the middle (See Man In The Middle attack)?
The client cannot possibly know every single public key - there are millions of them. It will have to retrieve them from the servers and then somehow make sure they belong to the server they are interested in.
This is where another function of Public Key Cryptography comes in. Previously we used the public key to encrypt data so that only its intended destination could descrypt it. Now we
do the opposite: We use the private key to encrypt data so that it can only be decrypted with the public key. Essentially we sign the data so that if decrypts with the public key people will know the data came from the server. How does this help?
When the browser is installed it has a relatively small number of public keys (commonly known as certificates) pre-installed. Those belong to Certification Authorities (CA) that are entities (generally companies like Verisign, governments or even some Institutions) that are deemed trustworthy. The Certification Authorities use the corresponding private keys to sign other public keys available in the Internet and so on.
So when the browser contacts a server and receives its public key, that key should be signed with the private key from a certificate pair. That certificate pair would be likewise be signed by another and so on, until the browser comes up to a public key that was signed with the private key that corresponds to one of the Root Certificates that were preinstalled with it. You might want to read a previous answer of mine for more on Root Certificates, or just read the Wikipedia articles.
Since each public key was successively signed until we reached a trusted key, the client can now be certain that the server on the other end of the connection is indeed e.g. MyBank.com and not, say, some criminal's laptop in the next cafe table that is messing with the wireless connection.
While there have been weak SSL algorithms (hence the succession of SSL protocol versions), these days the attacks are generally targeted to the implementations:
Use specially crafted or malformed certificates to fool the browser (and its weak implementation) into thinking that a public key is signed by a trusted entity when it's really not.
Compromise the integrity of the client software (e.g. a virus) to capture the symmetric keys when they are generated. In most of those cases however, it is usually easier to just capture the interesting data as they are entered into the browser by e.g. capturing the keyboard strokes as the user types in their credit card number.
Compromise the server itself and steal the private key. While it's not as easy as targeting unsuspecting clients, it has happened and it has the potential to compromise a significantly larger number of encrypted sessions. The current Public Key Infrastructure (PKI) has a whole mechanism for the revocation and disabling of compromised or otherwise invalid keys.
The last attack can be defeated if the client sends a temporary public key of its own instead of a symmetric key and use an asymmetric algorithm for the whole session. That would make it impossible for an attacker to compromise past sessions by stealing the server's private key. This technique is the basis for ensuring Perfect Forward Secrecy, but unfortunately not all servers implement it yet due to compatibility or performance reasons.
thkala is spot on. You can, assuming you have MiTM, under common circumstances forward a self signed certificate to the victim for which you have the private key, then forward the requests by the victim to the destination server using the servers' real certificate. This will require the vicitm to accept a certificate warning though.
Another way of defeating Ssl is by stripping the ssl session, lookup sslstrip.