As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
First of all,
do those successful commercial MMORPGs use encryption for game data transmission?
I got an impression that many developers tend to not use encryption, because it can not prevent reverse engineering for cheating and making private server, but doesn't it effectively reduce the number of those?
Encryption also impacts performance, even just a little.
Good encryption does prevent network sniffering and man-in-the-middle, are these important for MMORPGs?
How about protecting chat messages for privacy concerns?
How do you think?
PS: I'm talking about game data, not user/password, auth info need to be encrypted for sure.
Encryption is a tool. Make sure the tool fits the problem.
Encryption is useful for essentially three things: 1) 3rd party can't view data, 2) both parties are who they say they are, 3) data hasn't be modified. None of those really apply here. Remember the client is on the user (attacker) machine. If they modify the client it will gladly sign & encrypt any message they want.
The second thing to consider is the fact that the client has the keys and thus you should assume the attacker also has the keys. Even if you use asymmetric encryption the client has the key to decrypt anything it receives. If you send "private data" to the client an attack can find the key and decrypt it.
A good MMORPG (deisgned to make cheating difficult) should assume two things:
a) user/attacker can see any data sent to client (so don't send things to client you don't want user to see)
b) an attacker can send any possible command to the user (so don't rely on the client for security).
In most MMORPG the client is little more than a dumb terminal with impressive graphics. All computation, error checking, and validation occurs server side. The client doesn't determine is you hit or miss, nor does it determine how much damage. The client simply tells the server "I am attack with item 382903128." or some other action (not result). The server validates that the player has access to that option, has the item, and the command is valid at this time. To prevent sniffing attacks the client is only given data that the user would have access to anyways.
In any security context, you need to think about what exactly the threat scenarios are.
Attacker A has access to a machine running the game client and wants to write a bot to automate his actions so as to win battles easily.
Attacker B is eavesdropping on packets on a local network, with the aim of
Stealing login credentials so as to play the game for free.
Spying on player-to-player private chat, perhaps to gain advantage in the game, or maybe for blackmail or harassment in the real world.
Inserting extra behaviour into the stream of commands, e.g. instructions to buy or sell items at prices that make money for the attacker.
Encryption has no effect on attacker A (since the game client can decrypt the communication, so can the attacker; counter-measures must be taken on the server) but defeats attacker B.
I disagree with some of the other answers about the value of the data being transmitted. Your private chats with other players are as worthy of protection as your instant messages with them, and your gold and possessions, earned with hours of toil, deserve some protection from attackers, if perhaps not as much as your dollars in a bank account.
During the 90's Ever Quest used a low level packet encryption. I recall fondly as there used to be a side application that would sniff the packet data and give you a zone wide info about everyone in the zone. The EQ team crippled this for a while when they added the packet encryption, but that didn't stop the hacker community as they would just get the key out off the client machine. So in the end, it really didn't help in any way.
As to the other MMO's out there, I've not looked at the packet data to make a determination one way or the other.
You don't need encryption for security per se.
Consider this 'packet':
<USER_ID><COMMAND><MD5HASH>
The MD5HASH is generated from the USER_ID + COMMAND + some other value both the server and client know, but is not transmitted over the wire (user email or some token supplied securely during login). The server can reconstruct the string used for hashing and verify the authenticity of the command. If some man-in-the-middle changes the COMMAND, the hash won't match.
Besides validating authenticity this method also allows you to check you received the entire instruction. (It's possible that your 'game packet' is spread across multiple TCP/IP packets, some might get lost, etc.)
This does not prevent snooping around in messages, but is does prevent tampering. It's a game, who cares about what players say? I mean, emails are unencrypted and nobody cares about those, while their contents is more valuable than the average in-game chat.
Encryption is always a good thing if it actually protects valuable data. For that would be bank data, mails, instant messaging and file transfers. Not because I'm terribly paranoid of my ISP or network provider, but there is a specific risk if you are in an open network (for instance, school networks or company networks), that someone might be reading sniffing network traffic.
For MMORPGS I don't see a benefit in either security nor in performance, since most data is highly session based and man-in-the-middle attacks are rather unlikely (because, afterall, why would you want to sniff and attack such a connection?).
What I would do is to transmit passwords and login credentials as hashed values (or even encrypt just that part), and leave the rest of the connection cleartext; so you don't suffer from CPU hogging and lag caused by encryption (especially when there is a heavy load on the server).
At least the login should be encrypted, and the client should verify the public key of the server against a white-list to prevent man-in-the-middle attacks.
Encrypting the data transfered during the game itself isn't that important.
You need to distinguish encryption and obfuscation which have quite different goals.For example SSL is useful as encryption but useless as obfuscation since the encryption happens in known APIs, and it's trivial to intercept the plaintext when it gets passing into/out from these APIs.
Obfuscation needs to be mixed into your own code and doesn't need to be cryptographically secure.
Encryption needed vs administrators of local network or Wi-Fi, they potentially could sniff your traffic/packets and grab/change game information/passwords.
Tipically (99.99999%) accounts are hacked by trojans, not by packet sniffing. So in 99.99999% encryption is useless.
Encryption is totally useless vs Botting or Cheating. For that cases there is special forces, like - Anti-Cheating/Bot systems.
Related
I'm working on IoT gateway which will collect data from IoT devices. IoT device is a constrained device which couldn't use HTTPS.
It sends periodically small amount of data - from sensors, with some aditional information as time, message id, unit id etc.
Right now we've got an implementation of gateway as REST API in Java open for everyone. So It accepts requests as JSON from any device, without ensuring that data comes from our device are not corupted or compromised.
Without having ability to secure data by HTTPS, what is the best way to design interface between gateway and device?
Without having ability to secure data by HTTPS, what is the best way to design interface between gateway and device?
You can still use a symmetric encryption/authentication to ensure integrity and confidentiality, which should be feasible even for low end devices
As an inspiration you may have a loot at JWE with a shared key.
You could limit replays using some timestamp/counter or having idempotent consumers.
Regardless that - missing tls/https ypu have to take care of a lot of things, such as how to protect a shared key, update if revoked, etc
If the device can't do https (with any set of cipher suites) you will probably have to make serious compromises and not have some aspects of a secure connection. A bit simplified, but https is pretty much the minimal full suite of how it can be done, there is nothing "unnecessary". You might not need everything, but it entirely depends on your usecase and threat model. Before implementing this, you should have a full understanding of exactly what https provides, and how, so you can use applicable parts. Also note that this is not at all straightforward to implement, a custom implementation will likely be vulnerable.
How constrained is your device really? There are small implementations of TLS that wouldn't require you to compromise on security such as wolfSSL.
Footprint sizes (compiled binary size) for wolfSSL range between 20-100kB depending on build options and the compiler being used.
Regarding runtime memory usage, wolfSSL will generally consume between 1-36 kB per SSL/TLS session.
Anyway, I would not recommend you try and implement your own cipher suite unless you REALLY know what you are doing.
Given the kind of tools you've mentioned having access to (HTTP/JSON), I suggest looking at JOSE, which is a standardized way of signing and encrypting this kind of data. Specifically you'll be interested in JWE, JWS, and JWT. The learning curve for JOSE is unfortunately somewhat steep and the docs are somewhat sparse, but it is quite effective and implemented on a variety of platforms, and will save you a lot of headache in inventing your own protocols (which is quite difficult to do correctly). I've had pretty good luck building custom systems around JOSE.
There are some key questions you need to ask:
Do you need mutual authentication, or only authentication of the device? If the device only writes and never reads, then you likely only need to authenticate the device and not the server.
Can you accept the risk of a single shared secret baked into the devices? The problem with a single shared secret is that if any device is reverse engineered, then all protection is lost until you phase out all devices with that key.
Can you accept the manufacturing cost of a per-device secret? Depending on your manufacturing process, generating a unique secret for each device may be difficult.
Can you accept the on-device storage space and processing requirements of a client certificate? If not, can you accept the logistics of maintaining a server-side database of every device's key? (If you can except neither, then you'll have to go with a single shared secret for the whole system.)
My gut feeling is you're talking about a device that can handle the complexity of a client cert, but not a full HTTPS stack. If you also can handle the complexity of generating a certificate during manufacturing, or your customers are willing to register their devices, then I recommend the following:
During manufacture or registration, generate a certificate and signing request. Send it to your server to be signed, and install the signed X.509 on the device. (Generating a CSR on the device is also an option, but many small devices lack the entropy to generate a decent random number. There are tradeoffs either way.)
Generate a certificate for the server, and install its public key on all devices.
Assuming the amount of data you're sending is small, I'd bundle it all into the JWT (web token), encrypted to the server's public key, and signed with the client's private key. Typically JWTs are used to exchange authentication information, but they're really just a standardized container for sending signed and encrypted JSON data, so they really can be anything you want.
In order to prevent replay attacks, the server needs to keep track of messages its seen before. There are two main approaches I like, depending on your situation:
Make the jti (JWT ID) a combination of the timestamp and a random value (in which case the server just needs to keep a cache of recent JTIs and reject too-old timestamps)
Make the jti a combination of the device id and a monotonically increasing message id. The server then needs to keep track of the last-seen message id for each device, and reject any ids less-than-or-equal to that.
If you don't need encryption, look at JWS instead, which just signs the data. None of these techniques require encryption, and it's a little simpler if you take that part out (you don't need a server certificate, for example). You can still prevent replays, and only allow trusted clients to connect. It is possible for someone to reverse engineer your device and pull out its client cert. The advantage of a client cert is that if you discover the abuse, you can then just ban that one cert. With a shared secret you can't do that.
The basic advantage of all of this is that JOSE is based on JSON, which is something you already understand and know how to parse and work with. But it's also reasonably compact for a string-based protocol. It's also extremely flexible in terms of algorithms, which makes it much easier to implement on smaller hardware. You could build all the same things by hand using public/private keys, but JOSE has already thought through many of the tricky security problems.
If only it were better documented....
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
What I'm trying to do is send information in web requests between a application I've made for a computer, and obviously a web server.
I want this information to be encrypted for security issues, this software may be something people want to crack and I don't want them seeing whats being exchanged between the client and the server.
So, my question is, what is the most efficient way to encrypt data on the client side, send it to the server side, then be decrypted. And then also in reverse with the server encrypting and the client decrypting.
EDIT:
I just want a method of valid encryption for the data being sent between the client and the server. A secure way to encrypt data on the client, then send it to the server, and have it decrypted. This whole thing was described very poorly. As programs such as fiddler, can monitor the requests sent from the C++ application to the server, and the response it gives back. All in plain text. I just need this data and response to be encrypted and be able to be decrypted on both sides.
The tool you want is a pinned TLS certificate. See the OWASP introduction to the topic.
The point of pinning a certificate is that your HTTPS session will not trust every root in the local keystore. It will instead only trust a limited number of roots, specifically the ones you specify (and ideally control). With that, it is not possible to simply inject a rogue root certificate into the local keystore in order to monitor local traffic.
That said, it is not particularly difficult to circumvent pinned certificates if you control the machine the client is running on. But it is not particularly difficult to circumvent any simple mechanism if you control the machine the client is running on. The techniques used to circumvent certificate pinning (namely, modifying the client), will circumvent every client-side encryption scheme.
This is discussed regularly on StackOverflow, and has been for years. Here is one of the various answers that links to several others:
Secure https encryption for iPhone app to webpage
The key lesson is that "anti-cracking" is not "security." It is achieved through obfuscation and other anti-reverse-engineering techniques. This is not a winnable problem. It requires ongoing improvements as attackers defeat your defenses. You should expect to allocate non-trivial resources to this on an ongoing basis, or you should apply modest resources (like pinning) and accept that they won't be very effective but they aren't very costly to manage.
(I used to do this as part of a team of over a dozen full-time people committed to preventing these kinds of attacks. We spend millions of dollars a year on the problem, working together with law enforcement around the world, and deploying extensive custom security hardware. We still got beaten and had to adapt our methods as attacks improved. That's what I mean by "non-trivial resources.")
Use SSL to encrypt traffic between client and server.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 7 years ago.
Improve this question
The goal of this question is that I am just trying to better understand the nature of P2P and networking and security / encryption. I am a front-end web developer and my knowledge of the networking stack is not great if we go lower than HTTP requests.
That being said, I am trying to understand how torrent traffic is "sniffed" by ISPs and the content identified. I feel like this question will expose my ignorance, but is it not possible to have some sort of HTTPS-like P2P protocol that would not be so readable?
I grasp that a given packet has to identify its destination to the network along the way, but couldn't torrent packets be configured to show ONLY their destination, so that nobody could identify its purpose along the way, until it arrived at its destination? Why is it apparently an unrectifiable situation that ISPs can just look at P2P traffic and know everything about it, yet SSH is extremely safe?
Every answer here seems to have a different interpretation of the question, or rather, a different assumed purpose of the encryption. Since you compare it to https, it seems like a reasonable assumption is that you're looking for authentication and confidentiality. I'll enumerate a few attempts in decreasing level of "security". This is a bittorrent centric answer, because you tagged the question with bittorrent.
SSL
Starting with the strongest system, it is possible to run bittorrent over SSL (it's not supported by many clients, but in a fully controlled deployment it can be done). This gives you:
Authentication of every peer participating
The ability to pick which peers are let into the swarm by signing their certificate with the swarm root.
SSL encryption of all peer connections + tracker connections
The tracker can authenticate every peer connecting to it, but even if the peer list (or one peer) is leaked or guessed, there's still the peer-to-peer authentication, blocking any unauthorized access.
Bittorrent over SSL has been implemented and deployed.
encrypted torrents
At BitTorrent (in the uTorrent client) we added support for symmetric encryption of torrents at the disk layer:
Everything in the bittorrent engine would operate on encrypted blocks. The data integrity checks (sha-1 hashes of pieces) would be done on encrypted blocks and the .torrent file would have hashes of the encrypted data. An encrypted torrent like this is backwards compatible with clients that don't support the feature, but they won't be able to access the data (just help out the swarm and seed it).
To download the torrent in an unencrypted form, you would add the &key= argument to the magnet link, and uTorrent decrypts and encrypts data at the disk boundary (leaving the data on disk in the clear). Anyone adding the magnet link without the key, would just get encrypted data.
There are some other details involved too, like encrypting some of the metadata in the .torrent file. Such as the list of files etc.
This does not let you pick which peers get to join. You can give access to the peers you want, but since it's a symmetric key, anyone with access can invite anyone else, or publish the key. It does not give you any stronger authentication than you had when you found the magnet link.
It gives you confidentiality among trusted peers and the ability to have untrusted peers help out with seeding.
bittorrent protocol encryption
The bittorrent protocol encryption is probably better described as obfuscation. Its primary intention is not to authenticate or control access to a swarm (it derives the encryption key from the info-hash, so if you can keep that a secret you do get that property). The main purpose is to avoid trivial passive snooping and shaping of traffic. My understanding is that it's less effective to avoid being identified as bittorrent traffic these days. It also provides weak protection against sophisticated and active attacks. For instance, if the DHT is enabled, or tracker connections are not encrypted, it's easy to learn about the info-hash, which is the key.
In the case of private torrents (where DHT and peer exchange are disabled) assuming the tracker runs HTTPS there aren't any obvious holes in it. However, my experience is that it's not uncommon for https trackers to have self signed certificates, and for clients to not authenticate trackers. Which means poisoning the DNS entry for the tracker may be enough to enter the swarm.
Torrent traffic can be encrypted, and there are VPNs/SOCKS proxies that can be used to redirect traffic, i.e., via another country through an encrypted tunnel before connecting to peers. That said, even if you use such services, there are a lot of ways of leaking traffic via side channels (e.g., DNS lookups, insecure trackers, compromised nodes), and most people aren't knowledgeable enough to follow all proper security/anonymity precautions. Furthermore, restricting yourself to communicating only with clients who have also forced encryption will limit the number of peers you can connect to.
The problem you're considering is the difference between point-to-point encryption where there are only two peers in a private context and an unbounded number of peers in a public context.
Decryption by any of the public peers can only be effected if there's a primer somewhere -- a decryption key that is available for all the public peers to use. In the case of protecting from the ISPs, they would also have access to that key unless there was some exclusionary protocol for only sharing the key amongst everyone else. It's not practical to do this.
In a point-to-point connection, a TLS key negotiation eventually creates a session encryption key that is shared by both peers. The key is pseudorandom and session-specific. Data shared on the internet this way would be unusable to clients that didn't participate in the key negotiation.
Bittorrent traffic (specifically the peer-peer protocol used to transfer the bulk of the data) can be encrypted. But it's the kind of encryption that does not provide strong confidentiality/authentication guarantees, similar (but not identical) to HTTP2's opportunistic encryption
Client-Tracker communication can be encrypted with HTTPS.
These two components give you a working, albeit restricted, bittorrent stack that's encrypted and whose contents are not visible to a passive observer.
ISPs may still be able to identify it as "bittorrent, probably" based on side-channel data (packet sizes/traffic patterns, domains contacted, ...) but they won't know exactly what is being transferred.
After the player is authenticated, he receives a random, unique identification token. Every packet sent by him includes the token. A typical message would be:
token sequence_number commands
The problem is that, if somebody saw a packet, the person would be able to act as the player and give all the player's coins to somebody else for example. Or read the player's messages, or do anything short of stealing personal info.
So I thought encryption would be a requirement. But I've found many people advocating against it, one even says "it's complete paranoia" (https://gamedev.stackexchange.com/a/25551/33993).
Is there a way to avoid MITM attacks without encryption? If not, is avoiding them unnecessary?
The linked question says, "Only if it is an in-game purchase/micro-transaction - and then why not just use something tried and true like HTTPS."
Https is regarded as sufficient for MITM protection.
By which I mean: Yes!, you should send your traffic on Https!
It will have an impact on performance, but (obviously) lots and lots of effort has gone into optimizing that. A lot of the cost happens on establishing an Https connection. For an ongoing game connection, you should be able to keep it open, and the performance impact will be lessened.
As commenters have mentioned, Https uses TLS for encryption. You can build your own TCP or even UDP protocol using TLS, as well, but these days I'd recommend if possible, use boring old TCP/Https. All the platforms have APIs for it, there's ways to make it realtimey, and it plays probably the easiest with home routers & firewalls, and will be unsurprising when you explain it to others.
See pusher and socket.io and long polling for examples of using http/https for realtime.
MITM protection without encrypting the communication channel is difficult. You could use a Message Authentication Code (MAC) to protect key components from being changed. But you still need a shared secret that has to be exchanged over a different channel or using encryption (HTTPS).
You might want to take a look at the Hawk authentication scheme on how to exchange data securely over an unencrypted channel.
Typical encryption (example: HTTPS) is not sufficient to defeat MITM (http://en.wikipedia.org/wiki/Man-in-the-middle_attack) attacks. The wiki page has a simple example of how MITM is able to defeat encryption. There are complex methods to defeat MITM but they are typically overkill for a web game.
To answer your question, encryption does not defend against MITM, but it is necessary to implement encryption as it has more to do with securing sensitive information (example, passwords, session keys etc) as it passes through the internet. Otherwise anyone listening on the network will be able to see those information in plain text.
Instead of spending a bunch of $$ on ssl, can I implement RSA on my own? (I don't care about proving the site's identity; I just want to encrypt a password between clients and the server to protect from man-in-the-middle attacks). I've read that any custom solutions are likely to be very insecure, but could someone read my plan and give a thoughtful response?
First I would create public and private keys. I would encrypt the client password with javascript by translating the letters of the password to ascii-values, and then multiply or add (any suggestions?) these ascii-values to get the "unencrypted message". I would then encrypt this message using javascript and the public key.
On the server, I would decrypt the secure message using the private key and end up with the sum/product of the password's ascii-values. Any tips on how to get the individual letters from that?
Edit: I've reached the conclusion that SSL is the best way to go. I was only looking at the client to server side of the deal (where all the client sends is a password). Of course, the information sent by the server to the client is valuable, and should not be vulnerable to MITM attacks. Thanks for the free SSL suggestions.
Thanks
There are a bunch of reasons not to roll your own encryption.
SSL gives the user confidence that the site is secure and that eavesdroppers cannot view the password on the wire. If you don't use SSL then the usual browser indications that the site is secure will not be present.
It's really hard to get RSA right (or any crypto algorithm for that matter). First off, using raw RSA is insecure and you need to have an appropriate padding mechanism and wotnot to make it actually secure. RSA can also only encrypt n-1 bytes of data, where n is the size of the key.
Leave crypto to the cryptographers. The first issue with your proposed system is that you're missing the point of using a secure transport: You don't need to do any special encoding of your data (the conversion to ascii and multiplying/summing or whatever part) because the secure transport means that eavesdroppers cannot see what's going past.
Your proposal does not protect against man-in-the-middle attacks. It (kinda) prevents eavesdropping, which is a different problem.
That said, you certainly can implement RSA in Javascript with a bit of effort, but just be aware that it is unlikely to be secure until you've had a bunch of cryptanalysts look at it and try to break it. You will make a mistake somewhere along the line, even if you are the best programmer in the world.
The user experience will also suffer because it will be very hard for the user to verify that they are, in fact, talking to your server.
SSL is a well known, well analysed, not-yet-broken protocol that can be free if you use a self-signed certificate (another poor user experience, but at least it's still fairly secure). Think very carefully before you decide to cheap out on the crypto, and make sure you weigh the cost of a certificate against your development time (it'll take you many hours to implement RSA) and the potential cost of leaking important customer information (their password). The cost of the certificate is likely to be insignificant compared to the rest of the project cost.
You can use a self-signed certificate on the server and trust it explicitly on the client (i.e. encode certificate parameters etc). So you don't need to reinvent the wheel. I would say more - depending on the library you can use PSK (pre-shared key) cipher suites and get rid of certificates completely.
I'm not sure you need SSL if you cannot afford a certificate. Obviously, your data you intend to protect does not have much value.
The public/private key system is best way to go. By the time you figure out how to roll your own and get your CA certificate included in all the major browsers and Operating Systems and become your own Certificate authority, I think you will find spending a few 100$ on cert is cheap.
If you are looking for SSL but not spending money use www.startssl.com as that will allow you to use SSL free. Creating your own solution will take time and if not done the correct way will be insecure.
Yes, it is possible to implement plain RSA "by hand" in this way. To create the unencrypted message, you can simply use the bits of the message. For example, if your password is cheese:
c h e e s e
0x63 0x68 0x65 0x65 0x73 0x65
The number to encrypt could then be simply 0x636865657365. You'll need to use math routines that can handle large integers (native Javascript numbers aren't big enough).
Standard warnings apply, your solution will have a fatal flaw in some way, etc etc.
I don't care about proving the site's identity; I just want to encrypt a password between clients and the server to protect from man-in-the-middle attacks)
That's exactly why you do care about proving the site's identity.
That in turn is why just using RSA without an authentication scheme isn't secure. It's no good having a secret conversation when you can't identify who you're talking to.