I have created a back-end/processing/statistics for POS transactions for a retail store chain. The thing is, now it is time to move from alpha to beta, and we need some sort of safety for the incoming data. And this is where I am lost. How do I implement some resemblance of security in this kind of system?
What I have come up with is a simple asymetric key/value pair, that is unique for each POS system, where the server has all of the private keys, and each pos has the public part of this exchange. In addition to this, all of the data exchange is sent via HTTPS.
Does this kind of thing make sense? Or is there a better way to keep the data safe?
P.S. Since there is a need to reconfigure each POS seperately, that is in no way connected to this system, having to do manual work at each POS is not a problem.
You'd like to accomplish 2 things:
1) Encrypt the traffic so that it is hidden from outsiders (confidentiality). You can accomplish this quite easily simply by enforcing that SSL is used for traffic between the client(s) and the server. The server will require an x509 certificate to accomplish this.
2) Ensure that all traffic coming to the server originates from a trusted client/POS (integrity). You can accomplish this using a couple of different techniques, both of which require an x509 certificate installed on each client (POS) system:
a) Require that all requests to the server be accompanied by client certificates. In this scenario, the client (POS) has a x509 certificate installed, for which it is able to access its own private key (the server does not, and should not have this private key, it belongs to the client). The server is configured to require client certificates with each request, it also is configured to validate that the client certificate presented does indeed match one of the POS systems. So if you add a new POS later, you need to make a change to the server ensuring that it will consider the new POS cert valid. Here is a description of the protocol for your own enrichment, you shouldn't need to know exactly how it works (because most tools IIS, Apache, etc. will abstract much of this for you) but it does demystify things a bit. http://publib.boulder.ibm.com/infocenter/tivihelp/v5r1/index.jsp?topic=%2Fcom.ibm.itim.infocenter.doc%2Fcpt%2Fcpt_ic_security_ssl_authent2way.html
OR
b) Require that all requests to the server are digitally signed by trusted clients. Public key (asymmetric) encryption allows you to sign a message. Basically it is signed with the client's (POS) private key, and then anyone (including the server) can verify its integrity by validating the signature using the client's public key. Many tools will actually encrypt and sign the message, which is OK, but if you're already using SSL and performance is a concern, you don't need to encrypt twice. If security is more important than performance, encrypting twice can't hurt. Here is some more info on digital signatures: http://www.cgi.com/files/white-papers/cgi_whpr_35_pki_e.pdf
So you should have a pretty good plan of how to proceed. Feel free to ask around here when you set out to implement these solutions, as there are a lot of things that usually don't work the first time around and debugging it is often difficult. I do recommend a tool called Fiddler or WireShark, which can help debug web services to some extent. Be sure that your client(s) can access their own private keys, and that the certificates of the clients are trusted by the server. Good luck.
http://fiddler2.com/
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....
This is in context of an application in cloud communicating to internal application through vpn over https connection. (Both the applications are of same organization)
So, even when using the above things, is it required add an additional layer of security by encrypting the credit card information so that the other application needs to decrypt it using predefined key?
If you are dealing with credit card numbers then you really need to follow PCIDSS. 4.1 states that when sending cardholder information over open or public networks it must be "appropriately" encrypted. It only states HTTPS (so SSL/TLS must be enabled).
I appreciate that you are not limiting your question to only credit card information.
I would say that for most things HTTPS is absolutely fine. I have had to encrypt a second user's password before (to validate information on a form that the first user entered, a bit like a signature) but that is not related to what you are talking about using HTTPS and encryption with.
Your question might be worth posting over at security.stackexchange
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.
I am still quite new to cryptography, so please excuse any rookie mistakes. I am shure this has been asked a couple of times, but I have no idea what to search for.
So, I have a server, which receives commands over http from my smartphone. Currently everything is encrypted using AES with a password, which can be set in the server's config.
The problem is that, when someone intercepts my requests, he cannot decrypt the commands, but he can resend the encrypted command to my server.
Two solutions I imagine are:
encrypt a timestamp within the command, so they are invalid after a period of time, but with the disadvantage that still (within that period) the commands can be resent.
the server sends some random stuff to the client, which must encrypt that and send the encrypted stuff back (I think that will kill my http approach)
I am shure there are better ways (maybe another algorithm?), any help is welcome.
Again, I don't have much experience with cryptography and programming is just a hobby :D
Please do not try to reinvent secure communication. SSL and SSH are two very widely used, and very good protocols for secure communication, both of which will address replay, as well as many other security issues that you've not yet thought of (re-ordering, removing messages, inserting messages from one place into another, etc).
It seems you need both encryption and authentication.
As stated by others, please only use SSL (HTTPS) for encryption for HTTP requests. SSL is exceptional for encryption. SSL can do authentication but there are better solutions for authentication of users from smartphones.
For authentication of the user, there are many options. For smartphone connections I suggest you also not invent your own authentication protocol and use tried and tested solutions such as OpenID and OATH. There are many libraries that support this. Using such protocols opens the possibility of authenticating users using their existing Google, Facebook, Twitter accounts etc.
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.