How to implement Secure RSA communication to multiple clients? - security

The situation: Sender A needs to send messages to B. The data is secured using RSA public key encryption. A och B creates private and public keys and shares the public keys. B runs a client that receives the encrypted messages, and decrypts them using the private key on his machine.
Now B goes to another machine, runs the client, receives messages, but the private key isn't there so he can't decrypt them!
Real world scenario: A chat application, like Skype. B can run Skype on several machines that all can receive the messages.
How can I accomplish this, without transferring the private key? How is this usually handled?

GnuPG does this. You can send a message to many people. Lets break it down. Start with a plaintext message M.
Next create a random key, sk.
Use a symmetric cypher. Aes is a solid choice.
Encrypt M with sk. em = E_sk(M)
So A sends to B and C. A gets Bpub and Cpub, that is, their respective public keys.
Then A encrypts sk with each public key. Header = E_Bpub(sk) & E_Cpub(sk)
A then sends Header and em to both B and C.
Both B and C use their respective private keys to decrypt their part of Header and then when they have sk, use sk to decrypt the message.
So to answer your question, something like skype or iMessage has multiple public keys for each user and encrypts sk with all of them so that any device can decrypt the message.
Hope that helps.
Whatsapp's encryption is based on whisper's paper.
https://www.whatsapp.com/security/WhatsApp-Security-Whitepaper.pdf
https://eprint.iacr.org/2014/904.pdf
https://whispersystems.org/

There are several ways how to fulfil the requirement.
1) User external "public key" server, which does not participate in conversation but "returns" public key of specified user on request;
2) Use onion routing: say "A" knows "B", but does not know "C". We suppose B knows them all, therefore, the idea is to is B as a proxy for delivering message to C without clear knowledge "A->C". In addition to that, we could use garlic routing to build more complex networks. This is very difficult way of solution.
3) Use one symmetric key (and symmetric algorithm) for chat. It works, but there are problems with revocation: imagine that someone from the chat group no longer trusted. We should at least exclude they from next messages, but as they know the encryption key, he is aware of all next handshakes between participants.
4) Use session key, on which produce a number of ephemeral keys "one-per-message" (see OTR for example). This is more complex solution, but its simplest implementation has the same disadvantage as the method 3.

I think I have it.
Only AES for the regular messages. The same key for each client.
When a new client connects, usa RSA to send the AES key from the sender to the new client using priority messages. (Recipient sends a request to sender, "give me the AES key, here's my RSA public key") Then process the waiting AES-encrypted messages!
One problem though, the sender must be online to be able to send back the AES key. So when the new client connects he will not be able to accept any messages until sender is online and has been able to respond to the request. But I might be able to live with that.
But... if the SENDER installs a new client on another machine he doesn't have the AES-key anymore...

Related

Secure communication using encrypted messages

I have a question about how to encrypt messages between users. Note i will only talk about cryptography theory and not platform dependent code like C++ with Windows Cryptography. I am talking about system programming and not web programming encryption with TLS, SSL, etc...
Also, ignore Certificates and Signing of messages, so just think of the Public keys as already being verified as not fraudulent and messages as being from the correct user.
I believe the best way to reach fast and secure encryption communication between users is to have both users with a session key because symmetric encryption is faster than asymmetric, and using asymmetric encryption (RSA) for the secure transfer of the session key.
I know there are other key agreement algorithms like Diffie-Hellmans, but lets stick with RSA which is what i've chosen.
Please tell me if you see where this might be a insecure (man-in-the-middle attack) or drastically inefficient way of performing encrypted communications.
Theory steps:
i.) Parties = {Server, Client}
ii.) Server: Generate session key (RC4)
iii.) Client: Generate private/public key pair (RSA)
iv.) Client: Send public key to Server
v.) Server: Encrypt session key with Client's Public Key, then send encrypted
session key to Client
vi.) Client: Decrypt session key using Client's Private Key
vii.) Both parties now hold the session key for fast encrypted communications
Server(Server's Session key) <--> Session Key's encrypted packet (Communication medium) <--> Client(Server's Session key, Client's Public/Private key pair)
Thanks!
Assumptions:
Public Key Tampering is not possible.
I think you mean this, by "ignore Certificates and Signing of messages"
Cryptosystem is not broken.
Symmetric cipher is not broken (RC4 is broken, for example)
Asymmetric cipher is not broken
One-way Hash function is not broken
Random number generator is not broken
Under these conditions, that's perfectly safe. In fact what you described in your question is how PGP works.
If you are willing to learn more about attacks against PGP, go here.
And if you are willing to learn basics of cryptology, this is an excellent beginner tutorial.
lets stick with RSA which is what i've chosen.
That's where your biggest vulnerability is.
Protocols such as TLS (which can use RSA) SSH and PGP provide a well defined mechanism for negotiating encryption, and implementations such as openssl provide a documented, tested, portable, robust and we'll tested abstraction layer.
Rolling your own solution carries massive risks of injecting vulnerabilities. And entails ongoing pain in maintenance.
BTW RC4 is considered broken by many people.

Man in the middle attack in LAN

I am pretty new in this kind of things.
I have a local area network, accessed by some users via cable some and via wifi others.
I have developed a local application in php which receives only some of the LAN clients as authentic users; they can be identified by the system with an algorithm of key exchange similar to Diffie–Hellman's, to estabilish a secret key. The client then asks to be identified throug such a channel.
The problem is, MITM attack is possible in this kind of situation. I read wikipedia about how such an attack is executed: somebody listens the messages of the two, and puts himself between them creating two different secret keys for the client and server.
This attack is reality, so it must be possible; but I do not understand how it happens in a LAN:
the attacker can listen to the messages, and inject message of his own, impersoning the two subjects of the communications by forging https' IP fields if necessary...
But he can't prevent the original unforged message to reach, concurrently (but also later, because of forging process taking the attacker computer some time) with his malevolent forged one, the recipient! Especially in a wifi connection, which cannot be cut off for a single user, for example cutting his cable.
So, client and server receive two different http requests from each other, a true and a forged one; isn't this a way for them to recognize that such an attack is in progress?
Maybe this question is newby-ous; as I said, I am pretty new at this.
I think that is a scenario where you would use a digital signature (which also uses the idea that asymmetric encryption/Diffie-Hellman uses, that is "public and private key") to sign your messages.
The MITM attacker can not forge a message with a bad "from" and then sign it with the private signature of the original sender. The recipient uses the public part of the signature/certificate to validate the message. So that way he will not only know he is being attacked but also which message is genuine.

Encrypted and authorized multicast

I have a server (will be noted as 'A') that transmits multicast to some end stations.
I would like only those that are privileged to see the information, to actually see it.
There is a third party server ('B') that manages unicast communications with both 'A' and the end stations and SSL with both of them.
My goal is to implement a secured multicast:
Two necessary givens:
It has to be multicast.
I want the security in the Application level (not the Network or Transport)
Questions:
Are there such implementations? I've tried searching for "secured multicast" etc. and have come across only IP Multicast security. I want an applicative implementation. If so, Could you recommend some and how to use them?
I thought about generating a special symmetric key - during the communication of 'A' and 'B' and during the conversation of 'B' and end station = to pass it (over SSL) to the end stations.
a. Is that a good idea?
b. A problem I see is that revealing the key becomes easier because of the amount of stations. I thought about replacing the key every hour. I shall inform the stations the key has changed by sending multicast messages: (sequence_number, encrypted_message) - this way every time the key changes then sequence_number++.
What do you think of the implementation? Have better ideas?
I wrote an app called UFTP (http://uftp-multicast.sourceforge.net) that does exactly this.
In terms of key management, each multicast session performs a TLS-like key exchange between the sender and each receiver, then uses the negotiated key for each receiver to send out the group key which is used to encrypt the data. By doing key negotiation for each session, this eliminates complications related to re-keying mid session.
Authentication is done via key fingerprinting, with fingerprints being communicated out-of-band. This is simpler than a certificate based system and minimizes overhead. Each sender and receiver has an RSA or ECDHA key they are identified by.
What you describe is a simple application of PKI:
Each station creates an RSA keypair and sends its public key to the server.
The server generates a random symmetric key and encrypts the multicast message using this symmetric key. New symmetric key should be generated for each message but usually it's not a big deal.
The symmetric key is encrypted using each station's public RSA key. Products of all such encryptions (i.e. encrypted session keys) are merged with encrypted data and compose the multicast packet.
Unfortunately such scheme will cause a significant extra data load on the multicast message, but this is caused by length of keys and the length can't be reduced without sacrificing security.

Security: How vulnerable is this authentication/encryption scheme?

I have a client-server game, where the client connects to a server and stays connected during the game (approx 5-60 min).
I want new clients to be able to register securely, as well as allowing existing clients to authenticate with no worries that the login credentials are exposed.
The thing is that for performance reasons it would be best to stick with a simple and cheap encryption like RC4 for the game session, but a symmetric key does not make it easy to secure the registration procedure.
Since I will want to keep a separate login server anyway, my idea is like this:
Client sends a HTTPS request to the login server with credentials (or registration information)
The login server collects the user information, and generates a temporary RC4 session encryption key
The user information + RC4 session + timestamp + digest (I can rely on both servers to be synchronized timewise) with a secret symmetric key, shared between game server and login server.
The packaged data + RC4 session encryption key + ip address to the game server is sent as a reply to the HTTPS request to the client.
The client opens a connection to the game server, sends an initial unencrypted hello message with the encrypted user information as a payload.
The game server unpacks the data packaged in (3). It now knows the user and the RC4 encryption key it is supposed to use.
If the timestamp indicates that the login credentials has expired, an error is returned to the client (who is then to retrieve new information). If the decrypted user data cannot be verified with the digest a different error is returned.
If everything checks ok, the server sends an unencrypted LOGIN_OK, and the RC4 encrypted communication starts.
Possible security concerns:
The game server 100% trusts the user info it has decrypted. This makes the servers completely decoupled which is nice, but if the key is compromised, users could completely fake their user info. This could be alleviated somewhat by rotating these keys, so that every day or month has a new key. Both game and login servers could get this from a third server that manages their keys. It might be overkill since: a) in case of a break-in where source code is exposed on the servers, they can be restarted with a new key b) a good enough key + encryption should make brute force attacks hard (suggestions on algorithm?)
RC4 isn't the most secure algorithm, but I make sure to throw away the first 512 bytes or so and each key is only valid for a limited time, e.g. 24h.
Doesn't seem susceptible to man-in-the middle from what I can see: SSL secures the RC4 session key, in (5) the RC4 session key sent to the game server is encrypted as well. All that is possible is DoS and to cause the user request a key again. If the data in (2) is cached until it expires, this should not create a new packet.
The encryption in (3) could be improved by adding random bits to the key. Those random bits are sent together with the encrypted packet, and presented to the game server in (5). In (6) the game server adds those random bits to his key and uses the result to decrypt the data. This way and attacker cannot see when the packed data changes.
Are there any vulnerabilities I'm overlooking here?
A summary of payloads created:
Client login-credentials (protected by SSL), sent to login server
User info + timestamp + temporary game server session key + digest encrypted by login server using a secret key shared with game server, given to the client that - without modifying it - passes it to the game server. Ought to be temper resistant because: a) client does not know the secret key b) has timestamp to avoid resending same data c) digest to verify content was encrypted correctly
temporary game server session key sent by the login server to the client together with the encrypted payload. Protected by SSL.
Client game server login packet, consists of encrypted packet received by login server.
A summary of encryption keys:
Temporary game server session key: randomly generated by login server for encrypted game server <-> client communication. Generated by login server, given to client and game server.
Secret user info encryption key. Shared between game server and login server, used pass user info to game server with client as messenger. Client does not possess this key.
First of all I wouldn't use RC4. There are both faster and more secure stream ciphers around so if you control both client and server then you can probably do better than RC4. Discarding only 512 bytes may not be enough for the Fluhrer, Mantin and Shamir attack, but even if you discard more bytes there's also the Klein's attack etc. I don't know if it's worth the trouble.
Second, make sure that the keys you generate are random. I know it seems obvious but for an example see: http://www.debian.org/security/2008/dsa-1571
But the real problem is this part: "The game server 100% trusts the user info it has decrypted. This makes the servers completely decoupled which is nice, but if the key is compromised, users could completely fake their user info."
You have to assume that the user knows the key. His game client has to know the key so it can communicate with the server. If the user can use his real data to log in via ssl, get a key for stream cipher and then send whatever info he wants to the game server then all the attacker has to do is just get an account and do whatever he wants.
It doesn't matter how often you change the key because every time you change it you have to still give it to the client so you might as well change it after every byte and it still wouldn't matter here.
This is more important than the cipher used or the key generation because no one will brute force the key if he just gets it.
You should never trust the client. You should store the client data on the server side and match it with the key or sign the data and verify it or use HMAC etc. because if the game server 100% trusts the user info then you will have problems sooner o later. There is pretty much no way around it.
It sounds like you're trying to reinvent SSL. Why not issue each client a certificate (signed by your own root authority), and have them connect to the game server over SSL, with mutual authentication?
I understand you cannot use SSL between the game server and the client as you don't want to go through the handshake again.
The protocol seems ok from a first glance. There is no replay attack also as you really need the symmetric session key to do anything meaningful. The best thing you can do is switch to AES is also very fast and very secure. I highly doubt you will see any performance hit by switching to AES.
Also the first security concern bullet point you mentioned is not really a concern. Well it is a concern for all clients on the desktop, for example your browser has the same problem talking over HTTPS. So you don't really have to solve it. Your game logic somehow has to look for bad behavior if you want to actively monitor manipulation attempts. You cannot solve it by re-keying.
I ended up also posting on sci.crypt and I'll try to summarize the suggested changes (as far as I understand them) below in case it might be of interest.
Step 1: Client sends a HTTPS request to the login server with credentials
Assuming that the credentials take the form of a login token, also add a self-assigned unique id.
Step 3: The user information + RC4 session + timestamp + digest
Use an encryption algorithm that ensures integrity, instead of using a digest explicitly. E.g. AES-GCM or AES-CCM. Add the extra id field in step 1. Add the ip to the game server as well.
Step 4: The packaged data + RC4 session encryption key + ip address to the game server is sent as a reply.
Giving the timestamp to the client will allow the client to know when the session has expired. This avoids unnecessary connects to the game server with expired credentials.
Step 5: The client opens a connection to the game server, sends an initial unencrypted hello message with the encrypted user information as a payload.
Add the self-assigned id in step 1 unencrypted to the payload.
Step 6: The game server unpacks the data packaged in (3). It now knows the user and the RC4 encryption key it is supposed to use.
The game server matches both its own ip with the encrypted ip, as well as the encrypted id with the id given by the client. The first prevents the user from going to a different server with the same credentials.
Step 8: If everything checks ok, the server sends an unencrypted LOGIN_OK, and the RC4 encrypted communication starts.
At this point the game server cannot be sure of the client's identity. Use the session key and encrypt nonce + strictly increasing session id + login success state using AES-GCM/CCM and send it to the client.
The client decrypts and checks the login success state. If this is true, then the client knows that the game server knows the session key (GCM/CCM verifies that the packet has not been tampered with). The client returns sid + nonce.
The server verifies sid + nonce is the same as the values sent.
Finally the client and server creates new session keys by hash-ing the session key with sid + nonce + salt to create the key for the consequent communication, to prevent a possible replay attack.
Regarding RC4
There are vulnerabilities in RC4, but it probably would suffice for this scheme because of the rather aggressive key rescheduling. However, there are modern ciphers which are more secure and faster, such as Snow 2.0 or Trivium.
Just use SSL to the game server. Modern cryptanalysis has resulted in a few very fast implementations of some of the better encryption algorithms. For example, well optimized AES implementations can easily encrypt at better than 150MB/s on any remotely modern machine. Also while AES is held with high regard, it does have two weaknesses that I know of, but when used correctly those weaknesses become insignificant.
I noticed that you failed to mention that you would be using an advanced key scheduling algorithm between the client and the game server. Failing to do so would make the weaknesses of the encryption algorithm much more severe. SSL/TLS should do the key scheduling for you.

Is this scenario secure?

I'm using RSA to encrypt communication between a server and a client.
Lets say we have 2 Asymetric keys, key 1 and key2.
The server has key1 (Private) from the start and the client has the key1(public)
So here is the scenario:
the client generates key2
client connects to the server
sending key2(public) encrypted with key1(public)
from now on the server will send all data encrypted with the key2(public)
the client sends some random data to the server
the server sends back the same data hashed
the client verifies that the data is right
As far as I can see this should prevent a man-in-the-middle attack, or am I missing something?
At point 7 the client should know if someone is trying to give the server the wrong key to encrypt with, as no one else but the server can decrypt key2(public).
If there is anything that can be done to improve the security please tell me.
The best thing you can do to improve the security is to use an existing design and not try to reinvent the wheel. I'm not saying that what you've done is necessarily wrong, but just that many people much smarter than you and me have spent a lot of time thinking about this problem. Use TLS instead.
As long as key1 (private) has not been intercepted somehow by a third-party, your scenario looks secure.
I think I saw this somewhere in a paper actually. In it, Alice gave Bob an unlocked box (key 1 public), then Bob put a bunch of his own boxes (key 2 public) in it, locks it and sends it back to Alice. Alice then opens the box(key 1 private), and now she can securely seal the boxes that Bob just gave her.
Despite the box analogy, that's essentially what you're doing, so I'd say its secure.
I agree, just use TLS.
Also, what value do steps 5 through 7 provide? A MITM wanting to do an attack that would work after steps 1-4 (e.g. DoS of some sort by passing n transactions through and then stopping, forcing a retry from the start) could do so just as well after 5-7. What do they add?
-- MarkusQ
No, this protocol is not safe.
A man-in-the-middle can intercept the data sent by the client and send whatever it wants to the server, since you haven't specified any mechanism for the server to authenticate the client or verify the integrity of messages it receives.
Sure, you could doctor up your protocol to fix these glaring problems, but there would be others. If you ever fix them all, you'd have something that maps to TLS or SSH, so why not just start there?
#Petoj—the problem I was focusing on was that of the server trusting the messages it receives; your proposal doesn't provide any security there. However, if you are worried about confidentiality, you still have a problem, because the MITM could pass messages back and forth unaltered until he sees what wants to find because you don't have any privacy on the client messages.
Your proposal seems to be aimed at ensuring the integrity of messages from the client. You've developed the protocol to the point where the client can't distinguish between an attack and a network failure. Rather than trying to help the client determine whether the server acted on a tampered message, allow the server to verify the integrity of the message before acting on it.
I will agree with Greg that you are reinventing the wheel. What you are essentially describing is some basic form of key exchange. Incidentally, in order to ensure that it is secure against man-in-the-middle attacks you must also be certain of the server's identity, i.e. ensure that the client can know with certainty that what it believes to be public(key1) really is the server's and not the man-in-the-middle's (e.g. using a CA or having the server's public(key1) in secure storage on the client side.)
Moreover, there are additional considerations you must be aware from a systems standpoint, such as:
asymmetric key encryption is slower than symmetric key encryption, which is one of the reasons why existing solutions such as TLS will use asymmetric key encryption only to negotiate a temporary symmetric key, which is then used for channel encryption.
if traffic analysis by a third-party succeeds in cracking a temporary symmetric key, you have not compromised you asymmetric key pair. You are encouraged to re-negotiate the temporary key relatively often for this reason. Arguably, generating a new key2 in your scenario would mitigate this aspect.

Resources