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.
Related
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.
TL;DR
Do I have to sign every single message, or is there a more efficient way of verifying the origin of messages?
I am developing a simple crypto protocol for fun. Of course I know that in any serious project, I should just use some industry standard, like OpenSSL, but this is for learning and experimenting.
The idea is that the communicating terminals exchange RSA public keys, then using these keys they exchange an AES key securely, so that the AES key can be used to encrypt every message from this point. I have already implemented all of this, and it works fine.
The problem is: a potential attacker cannot read anything thanks to AES, but could still for example cause errors or attempt to hijack the communication or do some other nasty stuff by being man-in-the-middle (for instance she/he could copy an encrypted message and disrupt things by sending it again and again). What I need is digital signature so I can confirm that messages are coming from the valid source and I'm in luck, because I already have a working RSA implementation.
I know how digital signatures work (taking the hash of the message and encrypting it using the private key, etc.), but the only way I can think of making this work is to sign every single message, then check whether the signature is valid or not on the receiving side. However, I'm concerned that this will slow down my protocol. The whole purpose of using AES to secure the communication (or any symmetric key encryption) is that it's a lot faster than RSA (or any public key encryption). Wouldn't doing this defeat the purpose of AES (or any symmetric key encryption)? So the question is: do I have to sign every single message? Or is there a more efficient way of doing this? How does for example OpenSSL handle this?
TL;DR Use authenticated encryption.
In symmetric encryption it is possible to produce a Message Authentication Code (MAC) that enables you to check whether a message that you sent was (maliciously) manipulated. A man-in-the-middle attacker has only a negligible advantage of forging an authentication tag for a message that you haven't tagged.
There are many ways of doing this, but it's generally seen that a MAC should authenticate the ciphertext and not the plaintext (Should we MAC-then-encrypt or encrypt-then-MAC?). Popular MAC algorithms are HMAC (e.g. HMAC-SHA256), CMAC/OMAC1 or GMAC. There are also some distinct authenticated modes such as GCM, EAX, OCB, SIV, CWC, etc. Those combine a mode to achieve confidentiality and a mode for authenticity without the need of different keys for both.
But this is not enough because this only enables the receiver to detect tampering or forgeries of messages. An attacker may still mount other attacks such as replay or delay attacks. Therefore you need to send nonces (such as a message counter) and time stamps along. The receiver would have to keep a record of previously sent messages (by storing the nonces) and not accept any messages that are sent too late judging by its internal clock.
In order to prevent the attacker from changing the nonces and time stamps at will, those also have to be authenticated. Most authenticated modes are actually Authenticated Encryption with Associated Data which can authenticate additional non-secret data such as nonces and time stamps.
The use of authenticated encryption can make a purely symmetric communication relatively tamper-proof under the assumption that the key was exchanged confidentially and was also verified through conventional digital-signatures such as RSA-PSS or Ed25519 (EdDSA).
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.
I am considering building an API system that uses HMAC. The server and client will have a shared secret, the client will sign the requests, the server will validate, and proceed if all is well. The trouble with this sort of system is that the secret has to be stored in a way where it can be retrieved, such as a database. If someone were to steal the secret, they have the key needed to do basically anything that user is authorized to do.
I was thinking that there must be a more secure alternative. Are there any flaws with using RSA?
Client has the "public" key instead of a shared secret. (The public key must still be kept secret for my use case.)
Client will hash the message with SHA-1 or whatever as normal.
Instead of adding the hash to the message directly, the hash will be encrypted via it's public key, and then sent with the message.
Server has the "private" key (to decrypt messages) but has no knowledge of the "public" key. (This is the part that makes this more secure than the normal approach. If the database is stolen, no keys are stolen that can impersonate a user.)
Server will decrypt the hash and validate the message as normal.
Is there anything wrong with this approach? Are there known implementations of this or something similar?
It depends on the asymmetric cryptosystem you chose:
(EC)Diffie-Hellman: It does not work. Publickey is directly derived from the privatekey via the generator, e.g. [d]G = Q
RSA: Usually people chose fixed publickeys like 0x010001. This is done for efficiency reasons. If you take a large enough, fully random e and derive d from it there is no possibility to calculate p and q given d and N OR e and N. Actually they are pretty equally then and the label private and public don't make much sense anymore. All that relies on a smmyetrical property of RSA. Be sure not to walk into textbook RSA issues. And be sure to ask enough clever people about it, this is just my thoughts on it.
If you base your crypto system on a proof of possession of a secret you need to, well - keep it secret :)
But yes, if you dont need the speed of a symmetric authentication then you can use a assymetric signature. Typically it is done with a signed hash, but you can also use a signed hmac.
The terminology is normally, that you sign with a secret key and validate with the public key (even when the signing operation looks like an encryption).
I'm not a cryptography expert, I actually only have a little bit of experience using it at all. Anyways, the time has come where one of my applications demands that I have some encryption set up. Please note, the program won't be managing anything super critical that will be able to cause a lot of damage.
Anyways, I was just trying to see if this scheme that I'm using is common and if there are flaws (of which there may be completely stupid & horribly flawed design, that's why I'm asking).
Ok, I have a client -> server communication. The Client I can hard code in the public portion of a 2048-bit RSA key. When the client wants to initiate a secure connection, he sends his username, md5 hash of his password, and a hash of a random UUID, all of which has been encrypted against the server's Public Key. The server receives the information and decrypts using its private key. Checks the database to see if his login + pass work & if they do, create a new entry in the "Sessions" table in the DB. This includes a SessionID, UID (user ID), and the UUID hash. Using the corresponding session ID's UUID as the keyphrase, the server will then send back a message that has the Blowfish encrypted word "Success!" + a random UUID (this message is Digitally Signed so we can determine if it came from the server or not). From that point on, when the client sends info to the server, it will be with a plaintext sess_id & include a Blowfish encrypted message, using the corresponding Session ID's blowfish secret (stored encrypted in the DB) as the key to encrypt / decrypt.
Specifically, I am curious as to whether this system "should work" or if anyone notices that it's glaringly obvious that a vulnerability exists, such as MITM.
Issues I can see off the top of my head (although you have left out most of the details, which is where the devil famously resides):
If you're using a UUID generator rather than a real cryptographic RNG, it likely has insufficient entropy. Don't discount this - in the real world, the favourite way of covertly weakening an encryption system has been to weaken the RNG;
Your initial RSA encryption sounds like it is susceptible to a small-exponent attack, and potentially other creative attacks. There's too much structure there to be comfortable;
It sounds like there's numerous opportunities for replay attacks;
What block cipher mode are you using with Blowfish?
I recommend using TLS/SSL - it's had a lot more friendly eyes looking at it for a lot longer than anything you build yourself ever will.
Just use SSL or DTLS, IKEv2, HIP, EAP or some suitable standard protocol. Don't try to invent your own crypto protocols, nobody has enough expertise to do this on their own. Your protocol doesn't have nearly enough entropy in it, so far as I can see, so your resulting keys will be pretty weak.
From that point on, when the client sends info to the server, it will be with a plaintext sess_id & include a Blowfish encrypted message, using the corresponding Session ID as the key to encrypt / decrypt.
If you're sending the session id in plaintext, and using it as the encryption key, how is that secure?
I see no reason why you can't use standard SSL authentication and let the library implementer worry about the handshaking.