I am working on an application that needs to encrypt all of its traffic on a LAN environment and so the speed of encryption is important and the cpu time needs to be reduced to let the application have more cpu cycles for itself. I am thus trying to understand what are my existing options besides rolling my own since I'm not a cryptographer.
I am trying to go now for a comprehensive list of all semi-valid options to be able to measure and test them:
TLS -- Not considered fast, maybe possible to tune the ciphers
SSH -- Maintaining ssh tunnels may be a burden
UDT -- Should be high performance, how is the optional encryption?
CurveCP -- By DJB so encryption is good, not sure about the transport part
MinimaLT -- DJB contributed crypto know-how, others did the transport
IPSec -- non-trivial to configure
What else I missed?
Go with TLS. The chances that the provider has heard of it and that acceleration is already present is rather high. SSH would also be an option, but it is generally used for administration.
About the other options:
UDT -- Should be high performance, how is the optional encryption? Good question, and a quick search did not find too much information, so avoid.
CurveCP -- By DJB so encryption is good, not sure about the transport part Anything mainly done by DJB requires university grade understanding of cryptography.
MinimaLT -- DJB contributed crypto know-how, others did the transport. See above. The main documentation seems to be a paper about MinimalLT.
IPSec -- non-trivial to configure And possibly security at the wrong level. Personally I would avoid, may be tricky to setup on a cloud provider.
So there you are, in the end transport level security always seems to gravitate towards TLS.
Try to go for a ciphersuite with AES and ECDSA/ECDH(E) if you want a high chance of a speedy implementation and a high level of security.
Related
I realized there is no encryption in CANBus communication. So my question is: Does it worth to add an encryption method to CANBus communication in a vehicle. Since the communication takes place between the ECU's in the same vehicle, I believe CANBus is safe against the remote attacks/attackers. So I think encryption is not necesssary. However, putting an encryption in CANBus might make it harder to make your vehicle get reverse engineered. Am I correct? To sum up, I have 3 questions:
Does CANBus needs an encryption method and does adding it worth to effort?
If yes what kind of encryption method would be the best for the CANBus communication in a vehicle?
Does adding an encryption to CANBus in your vehicled, would make it harder to get reverse engineered?
Not really. Depends what you want to protect against. To prevent a car thief from hacking into your CAN bus, use the usual protection measures against thieves: locks and alarms.
A couple of horrible car designs connect a MCU on the bus to the Internet for firmware updates. If you do that, you risk getting it hacked remotely, if an attacker can figure out how to download their own firmware into that MCU. Jeep had some design flaw like that iirc. But the design flaw is not of the CAN bus itself, it is the provided internet access to a MCU which also has access to the bus.
I suppose whatever is currently regarded as safe. But if it involves a lot of heavy math, it might be unsuitable for that purpose, since these are hard real-time systems, often with low end, decentralized CPUs. They won't be able to do heavy floating point math fast enough.
Of course.
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....
Foreword: I don't really know much about security or encryption or how it works.
I am developing a small server for a game that uses ENet, which doesn't support higher level things such as security (e.g. SSL/TLS in the TCP world) to, as I think they said, maintain simplicity and embeddability. Supposing that this game requires at least some reasonable degree of security and authentication (e.g. logging in and such), what would be a good approach?
I am designing an application protocol, and i am wondering if i still need include checksum in the protocol since tcp/ip already has checksum.
what's your opinion?
The BitTorrent protocol has a heavy amount of additional error correction and detection layered on top of TCP, so clearly the protocol designers saw the need for it.
The TCP checksum is quite weak, so you probably want an application level one if you are at all worried about reliability.
In particular the TCP checksum is not a secure hash, and there is no signature, so if you're worried about malicious changes then you need to add the security yourself.
To add to the other answers, you should probably look into Message Authentication Codes. MACs are a more robust way to detect errors than a simple TCP checksum.
If you want something robust, take a look at [HMAC][2]. HMAC provides both error detection and authentication (via shared keys).
If you want something quick and dirty, why not use sha1 hashes?
This Paper (When the CRC and TCP checksum disagree) suggests that since the TCP checksumming algorithm is rather weak, there would occur an undetected error every 16 million to 10 billion packets using TCP.
Are there any application developers out there who protect the data against such kind of errors by adding checksums at the application level?
Are there any patterns available to protect against such errors while doing EJB remote method invocation (Java EE 5)? Or does Java already checksum serialized objects automatically (additionally to the underlying network protocol)?
Enterprise software has been running on computers doing not only memory ECC, but also doing error checking within the CPU at the registers etc (SPARC and others). Bit errors at storage systems (hard drives, cables, ...) can be prevented by using Solaris ZFS.
I was never afraid of network bit errors because of TCP - until I saw that article.
It might not be that much work to implement application level checksumming for some very few client server remote interfaces. But what about distributed enterprise software that runs on many machines in a single datacenter. There can be a really huge number of remote interfaces.
Is every Enterprise Software vendor like SAP, Oracle and others just ignoring this kind of problem? What about banks? What about stock exchange software?
Follow up: Thank you very much for all your answers! So it seems that it is pretty uncommon to check against undetected network data corruption - but they do seem to exist.
Couldn't I solve this problem simply by configuring the Java EE Application Servers (or EJB deployment descriptors) to use RMI over TLS with the TLS configured to use MD5 or SHA1 and by configuring the Java SE clients to do the same? Would this be a way to get reliable transparent checksumming (although by overkill) so that I would not have to implement this at application level? Or am I completely confused network-stack wise?
I am convinced that every application that cares about data integrity should use a secure hash. Most, however, do not. People simply ignore the problem.
Although I have frequently seen data corruption over the years - even that which gets by checksums - the most memorable in fact involved a stock trading system. A bad router was corrupting data such that it usually got past the TCP checksum. It was flipping the same bit off and on. And of course, no one is alerted for the packets that in fact failed the TCP checksum. The application had no additional checks for data integrity.
The messages were things like stock orders and trades. The consequences of corrupting the data are as serious as it sounds.
Luckily, the corruption caused the messages to be invalid enough to result in the trading system completely crashing. The consequences of some lost business were nowhere near as severe as the potential consequences of executing bogus transactions.
We identified the problem with luck - someone's SSH session between two of the servers involved failed with a strange error message. Obviously SSH must ensure data integrity.
After this incident, the company did nothing to mitigate the risk of data corruption while in flight or in storage. The same code remains in production, and in fact additional code has gone into production that assumes the environment around it will never corrupt data.
This actually is the correct decision for all the individuals involved. A developer who prevents a problem that was caused by some other part of the system (e.g. bad memory, bad hard drive controller, bad router) is not likely to gain anything. The extra code creates the risk of adding a bug, or being blamed for a bug that isn't actually related. If a problem does occur later, it will be someone else's fault.
For management, it's like spending time on security. The odds of an incident are low, but the "wasted" effort is visible. For example, notice how end-to-end data integrity checking has been compared to premature optimization already here.
So far as things changing since that paper was written - all that has changed is we have greater data rates, more complexity to systems, and faster CPUs to make a cryptographic hash less costly. More chances for corruption, and less cost to preventing it.
The real issue is whether it is better in your environment to detect/prevent problems or to ignore them. Remember that by detecting a problem, it may become your responsibility. And if you spend time preventing problems that management does not recognize is a problem, it can make you look like you are wasting time.
I've worked on trading systems for IBs, and I can assure you there is no extra checksumming going on - most apps use naked sockets. Given the current problems in the financial sector, I think bad TCP/IP checksums should be the least of your worries.
Well, that paper is from 2000, so it's from a LONG time ago (man, am I old), and on a pretty limited set of traces. So take their figures with a huge grain of salt. That said, it would be interesting to see if this is still the case. However, I suspect things have changed, though some classes of errors may still well exist, such as hardware faults.
More useful than checksums if you really need the extra application-level assurance would be a SHA-N hash of the data, or MD5, etc.