SSL: How the client decrypt message from server - security

I've read and watched a lot of articles and videos about SSL AES and RSA, but one thing is ALWAYS missing in every explanation( or I just don't get it ) is how the client decrypts sensitive data that comes from the server!(e.g. how much money you have)
I get it that your public key can encrypt anything and send it to the server and anyone can have it, but what do you do when you want to retrieve something from the server?
Does it comes just as plain text?
Any of the articles and videos point that out, they all just say that you have a private key that you shouldn't share and a public key that you can encrypt your messages and share it in the internet, but they don't say how the client makes a GET request with a encrypted message and decrypt it so it can be human readable.
As it says in this link about AES:
Asymmetric cryptography works by having two different keys, one for
encryption and one for decryption. It's also often called 'public key
cryptography' because it's possible to make one key public (allowing
someone to encrypt a message) while keeping the other private (only
the holder of the private key can decrypt the message encrypted with
its related public key).
Any help is welcome!
I will leave some links about web security that I found useful to learn:
https://www.coursera.org/learn/internet-history/lecture/L7HzI/security-integrity-and-certificate-authorities

If you want all the details grab a copy of SSL and TLS: Designing and Building Secure Systems. For a more arid lecture, read RFC2246 The Transport Layer Security (TLS) Protocol.
The short story is this: during the TLS/SSL handshake the client and the server exchange a secret (the PMS, pre-master-secret). This secret is used to derive session keys, initialization vectors and HMAC keys for use by client and server. Each one uses this keys to encrypt and sign everything send from it's side, and each one use the other's key to decrypt and validate the data sent by the other.
Nothing ever goes in clear text, in any direction.
Authorization and authentication based on the certificate used is a completely orthognal issue.

Related

How to prevent MITM attacks when implementing E2EE?

I'm working on a project where two clients can send files to each other via web sockets (using Socket.IO). Each chunk is encrypted with AES.
Currently, the clients connect to the server, they each generate an RSA public/private key pair on their devices, they then announce their public keys to the server which sends them to the other client, and this gets stored by said client. Before data is sent, it is encrypted with AES using a random key and a random IV, and the AES key is then encrypted using the other client's public key. The data is sent across, the other client then decrypts the AES key using their RSA private key, and finally decrypts the content using the decrypted AES key and saves it to a file on their disk.
The issue is that the server could easily just replace one client's public key with its own, and steal the data. The only solution I can think of is for the clients to contact one another and manually verify their public keys... I'm not sure how I'd go about automating this process. Services that provide E2EE seem to generate a matching code on each device, but I'm having trouble finding any information about how this is actually implemented, like how would two devices generate matching codes without talking to a server or each other in between, and if they do, then the server knows the code anyway right?
I've considered using WebRTC to send the public key from one client to the other without having the data go through the server, but I'd appreciate alternative approaches. Thank you in advance! :)
To prevent MITM, users are supposed to "manually compare public key fingerprints through an outside channel", as explained in this article regarding the Signal Protocol.
Usually, it means checking an hexadecimal string over a trusted communication: face to face, phone, ... Depending on your requirements, you might also consider that an attacker cannot access both your tool and emails at the same time and consider emails your trusted communication.

Client Side Encryption Security of key

This may sound a bit naive but I am missing something and I want someone to enlighten me.
To prevent man in the middle attacks where your password in plain text could be easily read, client Side Encryption is done where the password is encrypted so a man in the middle can only find data which is gibberish for him. However, for the encryption, the server needs to send a key over the network.
So, my question is, if a man in the middle attack occurs, then he would be able to see the key as well which was sent for the encryption on the client side. With the key in his possession, the encrypted password can be very easily decrypted. Hence, the whole purpose of the encryption is defeated.
What am I missing here?
First, a precision: the attack you are talking about is not a MITM but passive eavesdropping. In a MITM, the attacker relays back and forth messages from the two parties.
Sending a symmetric key along with the encrypted data would of course be silly as an eavesdropper would sniff it as well as the data. This is why asymmetric encryption (aka public key encryption) is used.
In asymmetric cryptography, ciphers do not operate with a single key but with a key pair, composed of a public key and a private key. Public and private key are created together at the same time using a special algorithm and they are strictly connected to each other. The client encrypts the data with the server's public key, which is the only key that is shared publicly; this data can only be decrypted by the server with the server's private key. The communication from the server to the client is done in the same way.
You might want to read about PKC here:
https://enigmail.wiki/Introduction_to_Cryptography,_PGP,_and_Enigmail
https://en.wikipedia.org/wiki/Public-key_cryptography
It is worth noting that a MITM attack can actually happen at the moment one of the parties shares his public key with the other:
First, Alice asks Bob for his public key. If Bob sends his public key to Alice, but Mallory is able to intercept it, a man-in-the-middle attack can begin. Mallory sends a forged message to Alice that claims to be from Bob, but instead includes Mallory's public key.Alice, believing this public key to be Bob's, encrypts her message with Mallory's key and sends the enciphered message back to Bob. Mallory again intercepts, deciphers the message using her private key, possibly alters it if she wants, and re-enciphers it using the public key Bob originally sent to Alice. When Bob receives the newly enciphered message, he believes it came from Alice. [Wikipedia]
This is actually the weak point of PKC; the solution is either to use a centralized Certificate Authority (this is how it is done for the SSL certificates used in HTTPS), or use a shared Web of Trust. Both solutions have their advantages and drawbacks.

Encrypting text

I'm wondering if it's possible to encrypt text client side.
The situation is that I have a block of text I want to encrypt, and then save the encrypted text to a file. Only after a certain amount of time has passed will my program decrypt it. Another requirement I have is to be able to transfer the file with the encrypted text and be able to decrypt it with other copies of my program on various machines.
The problem is where to store the key. The only implementation I can think of that would work is if I store the key server side, and have it return the key after a certain time has passed.
Is there a way to do this client side (i.e. without any internet access)?
You can surely encrypt text on the client side, but the real problem is key management.
If the assumption is no Internet access, then you're going to have to package a certificate in the client that contains both keys, private to encrypt, public to decrypt, unless you use a symmetric key. Was going to suggest just generating a local, temporary symmetric key, but you state you must be able to decrypt the text on other machines that won't have it, so that won't work. At first blush, and maybe I'm overlooking something obvious, is packaging a cert on the client with public and private keys, and that introduces its own set of problems, eg protecting the cert with the private key.

Protecting a file using asymmetric cryptography

I know how asymmetric cryptography works. I know there are two keys (one private and one public).
When someone wants to communicate they exchange their public keys encrypt messages with those public keys AND then the respective message could be decrypted ONLY by the user that has the private key.
Now, I'm using Node.js and I need to do something like this...
I need an application that EACH hour reads a database, extracts data and saves it to a file that I need to send to another server.
My problem is that I DON'T WANT that file will be visible to other, I do the transfer using SSH so there is no problem BUT
I must encrypt that file because I'm not the admin of that server SO maybe someone could read it. Unfortunately the admin is the same for both servers.
So my idea is to encrypt the file with a public key, and then only he who has the private key(me) could decrypt it.
I think it is pointless using something like:
var key = 'blablabla'
If I use a public key, there is no problem, all can read it..... it is public indeed. But with this public key, nobody can decrypt the message, so it is
something like one-way encryption.
Now, could someone tell me if I need a signer/verifier to do this job, OR maybe I have to generate two keys (public/private) with openssl and pass those keys to a cipher/dechiper?
I'm looking at crypto modules, but there are no examples....
In general, your idea is right - you encrypt using public key and decrypt using private key of yours. However, practically the procedure is more complex. Random symmetric key is generated and the data is encrypted using that key. Then the public key is used to encrypt the random key. Encrypted key is sent to recipient together with encrypted data. On the other side encrypted key is decrypted using a private key, then the data is decrypted.
You can use OpenPGP keys or X.509 certificates to do the job.
In case of OpenPGP the standard offers encryption and decryption as atomic procedures (on the user level). In case of X.509 certificates you need to use PKCS#7 / CMS.
OpenSSL library offers operations with PKCS#7 / CMS, however when I look at nodeJS API for OpenSSL, that API is very limited and doesn't expose those functions. Maybe you can write your own nodeJS module which will interface with OpenSSL and provide missing functions.
Another alternative is to use OpenPGP keys and node-gpg module. That module uses gnupg to do the actual job, so gnupg must be installed.
Unfortunately I don't see any other suitable libraries in the 3rd-party module list provided in nodeJS wiki.

What is a good browser level encryption product?

I'm looking for a product that can provide browser-level encryption of textual data before it's sent to a backend server. HTTPS can be the secure transport mechanism but we need the packet to be encrypted on the browser first. The data packet must end up in encrypted form on the backend database. Use case is: user fills out form on the browser, user submits the form data, before sending the data over the wire, the browser encrypts the data, the data ends up in the backend database in encrypted form, at some point in time, all of the data will be collected from the backend database, moved to a disconnected computer and decrypted at that point.
HTTP over SSL/TLS (HTTPS) is secure enough. It actually is as secure as it gets.
With SSL/TLS you can choose the cipher suite and adjust the encryption algorithms and key sizes according to your needs. 2048-bit RSA and 256-bit AES should be secure enough.
In addition to encryption, SSL provides authentication. AND it is natively supported by virtually every browser in existence. Please don't reinvent the wheel.
I agree that TLS is good enough for a lot of cases and I've written a little about it in my journey to see how it works. It does have some issues like governments being able to compel certificate authorities to grant certificates to allow man-in-the-middle attacks, but in general it's pretty good.
You might be interested in the design of systems like LastPass that encrypt things in addition to using TLS (details here). I would say that your best approach if you think TLS isn't good enough is to do something in addition to it rather than in lieu of it.
That's what HTTPS (SSL/TLS) is for. It should be plenty secure enough.
But as you state in your answer to my query, you want the form data to be stored in the database in its encrypted form. A quick Google search brings up JQuery.Gibberish-AES. It's a JQuery plugin that will do AES encryption and can utilise an RSA public key.
Using this you could generate a public/private key pair, keep the private key on the super-secret disconnected computer, and publish the public key with your form. You can then encrypt the data, store it in your database, and even if someone got root access to the database server they could decrypt the data because the secret key is on your secure disconnected machine.
I'm sure there'd be similar plug-ins/libraries for other client-side frameworks if you don't use JQuery.
I'd still use SSL/TLS for the connection, because that provides the server authentication (and client authentication if you want) to protect against a man-in-the-middle.

Resources