Encrypting text - security

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.

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.

What is the most appropriated and secure way to encrypt files using private/public keys in Node.js

I was wondering in which use case i should use these methods when encrypting and decrypting files in my node.js application.
The Problem
I want to encrypt some files in my server, after asking other people, i realized that the most recommended method is encrypt those files (larges) using a private key.
Now, i was looking for the docs and saw these methods
crypto.publicEncrypt(pubKey, buffer)
crypto.publicDecrypt(pubKey, buffer)
crypto.privateEncrypt(privKey, buffer)
crypo.privateDecrypt(privKey, buffer)
this is very confusing because i don't know what of them i must to use now, ahm... i don't know what is the most appropriate way to do this securely.
tl;dr encrypt with the public key. Keep your private key safe.
Unfortunately, these methods are poorly named. privateEncrypt should be called something like sign and publicDecrypt should be called something like verify.
When using public-key encryption (also known as asymmetric encryption), one key can be used to write a cipher and the other key can undo that operation. Your public key is potentially known to everyone, and your private key is secret.
If you want to keep something secret, except from the owner of a certain key, you want to encrypt a message with their public key. So if Alice wants to receive encrypted messages, she'll share her public key A_pub and her secret key A_priv, she'll keep to herself.. You'll encrypt your message crypto.publicEncrypt(A_pub, buffer). She'll then decrypt that message with crypto.privateDecrypt(A_priv, buffer).
Doing it the other way is known as a digitial signature.

SSL: How the client decrypt message from server

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.

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.

How could you encrypt user data so only they can decrypt it?

I was thinking about creating a Web app that would let people enter text (using SSL connection) and it would be encrypted before saving to the DB. The goal would be to have it so that only users could decrypt it.
You could have the users enter the key along with their data, and enter it again when they want to see the data, and not store the key. That would be kind of painful for the user, though.
However, if you stored the key on the server you'd have access to it and could potentially decrypt their data.
I don't think it's possible to do it without either having the user enter the key every time or storing the key, but is there some way that I'm not thinking of? Like maybe generating a key from information only the user knows? Something involving cookies?
You should look into public key cryptography. The basic idea is that you can encrypt information using a public key that only the holder of the private key can decrypt. In your scenario, the server would have a record of all the users' public keys and use them to encrypt the information. Then your users would use their private keys, which the server never sees, to decrypt the data.
If you're looking for a way to store the private key client-side, you could look into PersistJS.
Sounds like you could do something using PGP. As a previous post mentioned you would have a public and private key. The private key can be secured by a passphrase. That way you could have the private key potentially stored on the db, since it would still require a passphrase to use it.
The huge problem is that if the user should forget that passphrase, they could lose that data. You could get around that by using an Alternate Decryption Key (ADK). That key is automatically encrypted with everything and can be split between multiple individuals.
From an information security perspective, this only makes sense if the encryption/decryption is done on the user's computer, and not your server (since there's no guarantee that you're not storing the key and/or the plaintext). JavaScript is out of the question, so you need a client application*.
Also, public-key cryptography is computationally expensive. You might want to keep that in mind if you have a lot of users and decide to do encryption/decryption on the server.
* or a Java applet, but that's so 90's. Silverlight or Flash could potentially work, too.

Resources